001/**
002 *
003 * Copyright (c) 2010 The Regents of the University of California.
004 * All rights reserved.
005 *
006 * Permission is hereby granted, without written agreement and without
007 * license or royalty fees, to use, copy, modify, and distribute this
008 * software and its documentation for any purpose, provided that the
009 * above copyright notice and the following two paragraphs appear in
010 * all copies of this software.
011 *
012 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
015 * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY
016 * OF SUCH DAMAGE.
017 *
018 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY
022 * OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
023 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
024 */
025
026package org.kepler.gui.kar;
027
028import java.awt.Cursor;
029import java.awt.event.ActionEvent;
030import java.io.File;
031import java.util.ArrayList;
032import java.util.HashMap;
033import java.util.Iterator;
034import java.util.LinkedHashMap;
035import java.util.List;
036import java.util.Set;
037
038import javax.swing.Action;
039import javax.swing.ImageIcon;
040import javax.swing.JLabel;
041import javax.swing.JOptionPane;
042import javax.swing.KeyStroke;
043import javax.swing.SwingWorker;
044import javax.swing.UIManager;
045
046import org.apache.commons.logging.Log;
047import org.apache.commons.logging.LogFactory;
048import org.apache.tools.ant.DefaultLogger;
049import org.apache.tools.ant.Project;
050import org.kepler.build.Run;
051import org.kepler.build.modules.CurrentSuiteTxt;
052import org.kepler.build.modules.Module;
053import org.kepler.build.modules.ModuleTree;
054import org.kepler.build.modules.ModulesTxt;
055import org.kepler.build.project.ProjectLocator;
056import org.kepler.build.util.Version;
057import org.kepler.configuration.ConfigurationManager;
058import org.kepler.configuration.ConfigurationManagerException;
059import org.kepler.configuration.ConfigurationProperty;
060import org.kepler.kar.KARFile;
061import org.kepler.kar.ModuleDependencyUtil;
062import org.kepler.kar.karxml.KarXml;
063import org.kepler.modulemanager.ModuleDownloader;
064import org.kepler.modulemanager.gui.ModuleDownloadProgressMonitor;
065import org.kepler.util.ShutdownNotifier;
066
067import diva.gui.GUIUtilities;
068import ptolemy.actor.gui.TableauFrame;
069import ptolemy.util.MessageHandler;
070import ptolemy.vergil.toolbox.FigureAction;
071
072/**
073 * This action opens the ModuleManager for downloading new modules that are
074 * specified in the KAR dependencies.
075 */
076public class ImportModuleDependenciesAction extends FigureAction {
077
078        private static String DISPLAY_NAME = "Import Dependent Modules";
079        private static String TOOLTIP = "Import Kepler Modules that are needed for this KAR file.";
080        private static ImageIcon LARGE_ICON = null;
081        private static KeyStroke ACCELERATOR_KEY = null;
082
083        // //////////////////////////////////////////////////////////////////////////////
084
085        private TableauFrame parent;
086
087        private final static Log log = LogFactory.getLog(ImportModuleDependenciesAction.class);
088
089        private File _archiveFile = null;
090        private boolean _updateHistoryAndLastDirectory = true;
091        private KarXml _karXml = null;
092        private List<String> _dependencies = null;
093        private boolean _exportMode = false;
094        private boolean _needToDoAForceExport = false;
095        private Object _downloadLock = new Object();
096        
097        /** The user choice when dealing with a KAR with missing dependencies. */
098        public enum ImportChoice { FORCE_OPEN, FORCE_EXPORT, DO_NOTHING, DOWNLOADING_AND_RESTARTING };
099
100        /**
101         * Constructor
102         * 
103         *@param parent
104         *            the "frame" (derived from ptolemy.gui.Top) where the menu is
105         *            being added.
106         */
107        public ImportModuleDependenciesAction(TableauFrame parent) {
108                super(DISPLAY_NAME);
109                if (parent == null) {
110                        IllegalArgumentException iae = new IllegalArgumentException(
111                                        "ViewManifestAction constructor received NULL argument for TableauFrame");
112                        iae.fillInStackTrace();
113                        throw iae;
114                }
115                this.parent = parent;
116
117                this.putValue(Action.NAME, DISPLAY_NAME);
118                this.putValue(GUIUtilities.LARGE_ICON, LARGE_ICON);
119                this.putValue("tooltip", TOOLTIP);
120                this.putValue(GUIUtilities.ACCELERATOR_KEY, ACCELERATOR_KEY);
121        }
122
123        /**
124         * Explicitly set the dependencies for this dependeny broken KAR
125         * @param deps
126         */
127        public void setDependencies(List<String> deps) {
128                _dependencies = deps;
129        }
130        
131        /**
132         * Explicitly set the Archive file for this dependency broken KAR file.
133         * 
134         * @param archiveFile
135         */
136        public void setArchiveFile(File archiveFile) {
137                _archiveFile = archiveFile;
138        }
139        
140        /**
141         * By default, dialogs describe and attempt to Open KAR. 
142         * Change from Open to Export using this variable.
143         * @param export
144         */
145        public void setExportMode(boolean export){
146                _exportMode = export;
147        }
148        
149    /**
150     * Change whether or not to update Kepler's Recent Files menu, and 
151     * last directory setting.
152     * Default is true.
153     *
154     * @param updateHistoryAndLastDirectory
155     */
156        public void updateHistoryAndLastDirectory(boolean updateHistoryAndLastDirectory) {
157                _updateHistoryAndLastDirectory = updateHistoryAndLastDirectory;
158        }
159        
160        public void setKarXml(KarXml karXml) {
161                _karXml = karXml;
162        }
163        
164        public boolean getNeedToDoAForceExport(){
165                return _needToDoAForceExport;
166        }
167
168        /**
169         * Invoked when an action occurs.
170         * 
171         *@param e
172         *            ActionEvent
173         */
174        @Override
175    public void actionPerformed(ActionEvent e) {
176                super.actionPerformed(e);
177                                
178                ImportChoice choice = checkDependencies();
179                
180                if (_archiveFile != null) {
181                        if(choice == ImportChoice.FORCE_OPEN) {
182                                OpenArchiveAction oaa = new OpenArchiveAction(parent);
183                                try {
184                                        log.debug("FORCE OPEN, call OpenArchiveAction.openKAR");
185                                        oaa.openKAR(_archiveFile, true, _updateHistoryAndLastDirectory);
186                                } catch (Exception e1) {
187                                        // TODO Auto-generated catch block
188                                        e1.printStackTrace();
189                                }
190                        }else if (choice == ImportChoice.FORCE_EXPORT){
191                                _needToDoAForceExport = true;
192                        }
193                }
194                
195        }
196        
197        /** Check the dependencies and ask the user how to proceed. */ 
198        public ImportChoice checkDependencies() {
199                
200                ConfigurationManager cman = ConfigurationManager.getInstance();
201                ConfigurationProperty cprop = cman.getProperty(KARFile.KARFILE_CONFIG_PROP_MODULE);
202                ConfigurationProperty KARComplianceProp = 
203                        cprop.getProperty(KARFile.KAR_COMPLIANCE_PROPERTY_NAME);
204                String KARCompliance = KARComplianceProp.getValue();
205
206                final ArrayList<String> dependencies = new ArrayList<String>();
207                try {
208                        if (_dependencies != null){
209                                // dependencies were given
210                                dependencies.addAll(_dependencies);
211                        }
212                        else if (_archiveFile != null) {
213                                // kar file was given
214                                KARFile karFile = null;
215                                try {
216                                    karFile = new KARFile(_archiveFile);
217                                    dependencies.addAll(karFile.getModuleDependencies());
218                                } finally {
219                                    if(karFile != null) {
220                                        karFile.close();
221                                    }
222                                }
223                        }
224                        else {
225                                // karxml was given
226                                dependencies.addAll(_karXml.getModuleDependencies());
227                        }
228                }
229                catch(Exception ex) {
230                        ex.printStackTrace();
231                }
232                
233                //ModuleTree moduleTree = ModuleTree.instance();
234                //String currentModList = formattedCurrentModuleList(moduleTree);
235                
236                boolean dependencyMissingFullVersion = !(ModuleDependencyUtil.
237                                isDependencyVersioningInfoComplete(dependencies));
238                LinkedHashMap<String, Version> unsatisfiedDependencies = 
239                        ModuleDependencyUtil.getUnsatisfiedDependencies(dependencies);
240
241                String keplerRestartMessage = null;
242                String unableToOpenOrExportInStrictKARComplianceMessage = null;
243                String manualActionRequired = null;
244                String unSats = formattedUnsatisfiedDependencies(unsatisfiedDependencies);
245                final List<String> unSatsAsList = new ArrayList<String>(unsatisfiedDependencies.keySet()); 
246
247                String formattedDependencies = formatDependencies(dependencies);
248                String htmlBGColor = "#" + Integer.toHexString( 
249                                UIManager.getColor("OptionPane.background").getRGB() & 0x00ffffff );
250                //XXX augment if additional strictness levels added
251                if (KARCompliance.equals(KARFile.KAR_COMPLIANCE_STRICT)){
252                        if (dependencyMissingFullVersion){
253                                if (_exportMode){
254                                        unableToOpenOrExportInStrictKARComplianceMessage = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR " +
255                                                "lacks complete versioning information in its module-dependency list:<strong>"+
256                                                formattedDependencies +"</strong><br><br>You must change your KAR opening compliance " +
257                                                "preference to Relaxed before trying to export this KAR.<br><br>" +
258                                                "You can Force Export, but some artifacts may not be included in the KAR.</body></html>";
259                                }else{
260                                        unableToOpenOrExportInStrictKARComplianceMessage = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR " +
261                                                "lacks complete versioning information in its module-dependency list:<strong>"+
262                                                formattedDependencies +"</strong><br><br>You must change your KAR opening compliance " +
263                                                "preference to Relaxed before trying to open this KAR.<br><br>" +
264                                                "You can attempt a Force Open, but this may cause unexpected errors.</body></html>";
265                                }
266                        }
267                        else{
268                                if (!unsatisfiedDependencies.isEmpty()){
269                                        if (_exportMode){
270                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">Your KAR opening compliance preference is set to Strict. To export this KAR in<br>" +
271                                                        "Strict mode you must restart Kepler with these additional module(s):<strong>" + 
272                                                        unSats +"</strong><br><br>Would you like to download (if necessary) and restart Kepler using these modules now?" +
273                                                        "<br><br><strong>WARNING: All unsaved work will be lost, and auto-updating turned off if it's on<br>"+
274                                                        "(re-enable using the Tools=>Module Manager...)</strong><br><br>" +
275                                                        "You can Force Export, but some artifacts may not be included in the KAR.</body></html>";
276                                        }else{
277                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">Your KAR opening compliance preference is set to Strict. To open this KAR in<br>" +
278                                                        "Strict mode you must restart Kepler with these additional module(s):<strong>" + 
279                                                        unSats +"</strong><br><br>Would you like to download (if necessary) and restart Kepler using these modules now?" +
280                                                        "<br><br><strong>WARNING: All unsaved work will be lost, and auto-updating turned off if it's on<br>"+
281                                                        "(re-enable using the Tools=>Module Manager...)</strong><br><br>" +
282                                                        "You can attempt a Force Open, but this may cause unexpected errors.</body></html>";
283                                        }
284                                }
285                                else{
286                                        if (_exportMode){
287                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">Your KAR opening compliance preference is set to Strict. To export this KAR in<br>" +
288                                                        "Strict mode you must restart Kepler using this module set in this order:<strong>" + 
289                                                        formattedDependencies +"</strong><br><br>Would you like to restart Kepler using these modules now?" +
290                                                        "<br><br><strong>WARNING: All unsaved work will be lost, and auto-updating turned off if it's on<br>"+
291                                                        "(re-enable using the Tools=>Module Manager...)</strong><br><br>" +
292                                                        "You can Force Export, but some artifacts may not be included in the KAR.</body></html>";
293                                        }else{
294                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">Your KAR opening compliance preference is set to Strict. To open this KAR in<br>" +
295                                                        "Strict mode you must restart Kepler using this module set in this order:<strong>" + 
296                                                        formattedDependencies +"</strong><br><br>Would you like to restart Kepler using these modules now?" +
297                                                        "<br><br><strong>WARNING: All unsaved work will be lost, and auto-updating turned off if it's on<br>"+
298                                                        "(re-enable using the Tools=>Module Manager...)</strong><br><br>" +
299                                                        "You can attempt a Force Open, but this may cause unexpected errors.</body></html>";
300                                        }
301                                }
302                        }
303                }
304                else if (KARCompliance.equals(KARFile.KAR_COMPLIANCE_RELAXED)) {
305                        if (dependencyMissingFullVersion){
306                                // if there's a dependency missing full version info, situation should be either 1) a 2.0 kar, in which case
307                                // it lacks the full mod dep list and so user must use MM, or 2) it's a 2.1 kar created from an svn 
308                                // checkout of kepler, in which case, the power user should use the build system to 
309                                // change to unreleased versions of a suite containing the required modules as necessary
310                                if (_exportMode){
311                                        manualActionRequired = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR " +
312                                                "requires the following unsatisfied module dependencies that lack complete versioning information:<strong>"+
313                                                unSats +"</strong><br><br>Please use the Module Manager or build system to change to a suite that uses these modules.</strong>" +
314                                                "<br><br>You can Force Export, but some artifacts may not be included in the KAR.</body></html>";
315                                }else{
316                                        manualActionRequired = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR " +
317                                                "requires the following unsatisfied module dependencies that lack complete versioning information:<strong>"+
318                                                unSats +"</strong><br><br>Please use the Module Manager or build system to change to a suite that uses these modules.</strong>" +
319                                                "<br><br>You can attempt a Force Open, but this may cause unexpected errors.</body></html>";
320                                }
321                        }
322                        else{
323                                if (!unsatisfiedDependencies.isEmpty()){
324                                        if (_exportMode){
325                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR requires you restart Kepler with these " +
326                                                        "additional module(s):<strong>" + 
327                                                        unSats + "</strong><br><br>Would you like to " +
328                                                        "download (if necessary) and restart Kepler using these modules now?" +
329                                                        "<br><br><strong>WARNING: All unsaved work will be lost</strong><br><br>" +
330                                                        "You can Force Export, but some artifacts may not be included in the KAR.</body></html>";
331                                        }else{
332                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR requires you restart Kepler with these " +
333                                                        "additional module(s):<strong>" + 
334                                                        unSats + "</strong><br><br>Would you like to " +
335                                                        "download (if necessary) and restart Kepler using these modules now?" +
336                                                        "<br><br><strong>WARNING: All unsaved work will be lost</strong><br><br>" +
337                                                        "You can attempt a Force Open, but this may cause unexpected errors.</body></html>";
338                                        }
339                                }
340                                else{
341                                        //THIS SHOULDN'T HAPPEN
342                                        log.error("ImportModuleDependenciesAction WARNING unsatisfiedDependencies is empty, this shouldn't happen, but is non fatal");
343                                        if (_exportMode){
344                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR requires you restart Kepler with these " +
345                                                        "module(s):<strong>" + 
346                                                        formattedDependencies + "</strong><br><br>Would you like to " +
347                                                        "restart Kepler using these modules now?" +
348                                                        "<br><br><strong>WARNING: All unsaved work will be lost</strong><br><br>" +
349                                                        "You can Force Export, but some artifacts may not be included in the KAR.</body></html>";
350                                        }else{
351                                                keplerRestartMessage = "<html><body bgcolor=\""+htmlBGColor+"\">This KAR requires you restart Kepler with these " +
352                                                        "module(s):<strong>" + 
353                                                        formattedDependencies + "</strong><br><br>Would you like to " +
354                                                        "restart Kepler using these modules now?" +
355                                                        "<br><br><strong>WARNING: All unsaved work will be lost</strong><br><br>" +
356                                                        "You can attempt a Force Open, but this may cause unexpected errors.</body></html>";
357                                        }
358                                }
359                        }
360                }
361                
362                String[] optionsOkForceopen = { "OK", "Force Open" };
363                String[] optionsOkForceexport = { "OK", "Force Export" };
364                String[] optionsYesNoForceopen = { "Yes", "No", "Force Open" };
365                String[] optionsYesNoForceexport = { "Yes", "No", "Force Export" };
366
367                
368                if (unableToOpenOrExportInStrictKARComplianceMessage != null){
369                        JLabel label = new JLabel(unableToOpenOrExportInStrictKARComplianceMessage);
370                        if (_exportMode){
371                                int choice = JOptionPane.showOptionDialog(parent, label, "Unable to export in Strict mode", 
372                                        JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, optionsOkForceexport, optionsOkForceexport[0]);
373                                if (optionsOkForceexport[choice].equals("Force Export")){
374                                        return ImportChoice.FORCE_EXPORT;
375                                }
376                        }else{
377                                int choice = JOptionPane.showOptionDialog(parent, label, "Unable to open in Strict mode", 
378                                                JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, optionsOkForceopen, optionsOkForceopen[0]);
379                                if (optionsOkForceopen[choice].equals("Force Open")){
380                                        return ImportChoice.FORCE_OPEN;
381                                }
382                        }
383                        return ImportChoice.DO_NOTHING;
384                }
385                
386                if (manualActionRequired != null){
387                        JLabel label = new JLabel(manualActionRequired);
388                        if (_exportMode){
389                                int choice = JOptionPane.showOptionDialog(parent, label, "Use Module Manager", JOptionPane.DEFAULT_OPTION,
390                                                JOptionPane.WARNING_MESSAGE, null, optionsOkForceexport, optionsOkForceexport[0]);
391                                if (optionsOkForceexport[choice].equals("Force Export")){
392                                        return ImportChoice.FORCE_EXPORT;
393                                }
394                        }else{
395                                int choice = JOptionPane.showOptionDialog(parent, label, "Use Module Manager", JOptionPane.DEFAULT_OPTION,
396                                                JOptionPane.WARNING_MESSAGE, null, optionsOkForceopen, optionsOkForceopen[0]);
397                                if (optionsOkForceopen[choice].equals("Force Open")){
398                                        return ImportChoice.FORCE_OPEN;
399                                }
400                        }
401                        return ImportChoice.DO_NOTHING;
402                }
403                
404                JLabel label = new JLabel(keplerRestartMessage);
405                if (_exportMode){
406                        int choice = JOptionPane.showOptionDialog(parent, label, "Confirm Kepler Restart", 
407                                        JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, 
408                                        optionsYesNoForceexport, optionsYesNoForceexport[1]);
409        
410                        if (optionsYesNoForceexport[choice] == "No") {
411                                // user doesn't want to download.
412                                return ImportChoice.DO_NOTHING;
413                        } else if (optionsYesNoForceexport[choice].equals("Force Export")){
414                                return ImportChoice.FORCE_EXPORT;
415                        }
416                }else{
417                        int choice = JOptionPane.showOptionDialog(parent, label, "Confirm Kepler Restart", 
418                                        JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, 
419                                        optionsYesNoForceopen, optionsYesNoForceopen[1]);
420        
421                        if (optionsYesNoForceopen[choice] == "No") {
422                                // user doesn't want to download.
423                                return ImportChoice.DO_NOTHING;
424                        } else if (optionsYesNoForceopen[choice].equals("Force Open")){
425                                return ImportChoice.FORCE_OPEN;
426                        }       
427                }
428                
429                parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
430
431                
432                SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
433                        @Override
434                    public Void doInBackground() throws Exception {
435                                try {
436                                        
437                                        //download needed modules
438                                        ModuleDownloader downloader = new ModuleDownloader();
439                                        ModuleDownloadProgressMonitor mdpm = new ModuleDownloadProgressMonitor(
440                                                        parent);
441                                        downloader.addListener(mdpm);
442                                        if (!unSatsAsList.isEmpty()){
443                                                downloader.downloadModules(unSatsAsList);
444                                        }
445                                        else{
446                                                // this shouldn't happen, but if it does, resorting
447                                                // to downloading all dependencies should be a safe bet
448                                                log.error("ImportModuleDependenciesAction WARNING unSatsAsList is empty, " +
449                                                                "this shouldn't happen, but is non fatal");
450                                                downloader.downloadModules(dependencies);
451                                        }
452                                        
453                                        //rewrite modules.txt
454                                    ModulesTxt modulesTxt = ModulesTxt.instance();
455                                    modulesTxt.clear();
456                                        for (String dependency : dependencies) {
457                                                //System.out.println("ImportModuleDependency doInBackground modulesTxt.add("+dependency+")");
458                                                modulesTxt.add(dependency);
459                                        }
460                                    modulesTxt.write();
461                                    
462                                    //delete and write "unknown" to current-suite.txt
463                                    CurrentSuiteTxt.delete();
464                                    CurrentSuiteTxt.setName("unknown");
465                                        
466                                    // if KARCompliance is Strict, user is restarting w/ specific versions of modules
467                                    // and we don't want them to potentially auto update on restart to available patches
468                                    turnOffAutoUpdatesIfStrictMode();
469                                    
470                                    //restart Kepler using new modules
471                                    spawnNewKeplerAndQuitCurrent();
472                                        
473                                        return null;
474                                } catch (Exception ex) {
475                                        ex.printStackTrace();
476                                        JOptionPane.showMessageDialog(parent,
477                                                        "Error downloading module: " + ex.getMessage());
478                                        return null;
479                                }
480                        }
481
482                 @Override
483                 protected void done() {
484                                //never reached.
485                        }
486                        
487                };
488
489                worker.execute();
490                                
491                parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
492                
493                return ImportChoice.DOWNLOADING_AND_RESTARTING;
494        }
495        
496        /** Wait for the download to complete. This method does not return
497         *  since Kepler restarts once the download finishes.
498         */
499        public void waitForDownloadAndRestart() {
500            synchronized(_downloadLock) {
501                try {
502                _downloadLock.wait();
503            } catch (InterruptedException e) {
504                MessageHandler.error("Error waiting for download to complete.", e);
505            }
506            }
507        }
508        
509        /**
510         * If KARCompliance is STRICT, turn off auto-download of new patches (
511         * "check-for-patches" config param)
512         */
513        private void turnOffAutoUpdatesIfStrictMode() {
514                ConfigurationManager cman = ConfigurationManager.getInstance();
515                ConfigurationProperty cprop = cman
516                                .getProperty(KARFile.KARFILE_CONFIG_PROP_MODULE);
517                ConfigurationProperty KARComplianceProp = cprop
518                                .getProperty(KARFile.KAR_COMPLIANCE_PROPERTY_NAME);
519                String KARCompliance = KARComplianceProp.getValue();
520                if (KARCompliance.equals(KARFile.KAR_COMPLIANCE_STRICT)) {
521                        ConfigurationProperty mmConfigProp = ConfigurationManager.getInstance()
522                                        .getProperty(ConfigurationManager.getModule("module-manager"));
523                        ConfigurationProperty checkForPatches = mmConfigProp
524                                        .getProperty("check-for-patches");
525                        try {
526                                if (checkForPatches.getValue() != null && 
527                                                checkForPatches.getValue().equals("true")){
528                                        checkForPatches.setValue("false");
529                                        ConfigurationManager.getInstance().saveConfiguration();
530                                }
531                        } catch (ConfigurationManagerException e) {
532                                e.printStackTrace();
533                        }
534                }
535        }
536        
537        private void spawnNewKeplerAndQuitCurrent(){
538                
539        Project project = new Project();
540        project.setBaseDir(ProjectLocator.getProjectDir());
541        DefaultLogger logger = new DefaultLogger();
542        logger.setMessageOutputLevel(Project.MSG_INFO);
543        logger.setOutputPrintStream(System.out);
544        logger.setErrorPrintStream(System.out);
545        project.addBuildListener(logger);
546
547        //XXX call ShutdownNotifer.shutdown() before spawning new process,
548        // to avoid 2nd instance potentially interfering with quitting first.
549        // see: http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5484
550        System.out.println("ImportModuleDependency notifiying shutdown listeners " +
551                        "of impending shutdown. Closing any open databases may take awhile...");
552        ShutdownNotifier.shutdown();
553        
554        System.out.println("ImportModuleDependency Spawning new Kepler process");
555        Run run = new Run();
556        run.setTaskName("run");
557        run.setProject(project);
558        run.init();
559        run.setSpawn(true);
560        run.execute();
561        
562        System.out.println("ImportModuleDependency Ending current Kepler process");
563        System.out.println("NOTE: This will probably throw an exception as the current" +
564                        " process is terminated while a new Kepler process starts. This is normal and expected.");
565        
566        //XXX why exit with error arg here?
567        System.exit(1);
568        }
569        
570        /**
571         * simple helper method
572         * @param unsatisfiedDependencies
573         * @return formatted html unsatisfied dependency list
574         */
575        private static String formattedUnsatisfiedDependencies(HashMap<String, Version> unsatisfiedDependencies){
576                StringBuilder strBuilder = new StringBuilder("");
577                
578                Set<String> unsatisfieds = unsatisfiedDependencies.keySet();
579                
580                if (!unsatisfieds.isEmpty()){
581                        strBuilder.append("<br>");
582                }               
583                Iterator<String> itr = unsatisfieds.iterator();
584                int cnt =0;
585                while (itr.hasNext()){
586                        if (cnt%5 == 0){
587                                strBuilder.append("<br>");
588                        }
589                        strBuilder.append(itr.next());
590                        if (itr.hasNext()){
591                                strBuilder.append(", ");
592                        }
593
594                        cnt++;
595                }
596                return strBuilder.toString();
597        }
598        
599        /**
600         * simple helper method
601         * @param dependencies
602         * @return formatted html dependency list
603         */
604        private static String formatDependencies(List<String> dependencies){
605                StringBuilder strBuilder = new StringBuilder("");
606                
607                if (!dependencies.isEmpty()){
608                        strBuilder.append("<br>");
609                }
610                
611                Iterator<String> itr = dependencies.iterator();
612                int cnt =0;
613                while (itr.hasNext()){
614                        if (cnt%5 == 0){
615                                strBuilder.append("<br>");
616                        }
617                        strBuilder.append(itr.next());
618                        if (itr.hasNext()){
619                                strBuilder.append(", ");
620                        }
621
622                        cnt++;
623                }
624                return strBuilder.toString();
625        }
626
627        /**
628         * simple helper method
629         * @param moduleTree
630         * @return return formatted html module list
631         */
632        private static String formattedCurrentModuleList(ModuleTree moduleTree){
633                StringBuilder strBuilder = new StringBuilder("");
634
635                List<Module> modList = moduleTree.getModuleList();
636                
637                if (!modList.isEmpty()){
638                        strBuilder.append("<br>");
639                }
640                
641                for (int i=0; i<modList.size(); i++){
642                        if (i%5 == 0){
643                                strBuilder.append("<br>");
644                        }
645                        strBuilder.append(modList.get(i));
646                        if (i != modList.size() -1){
647                                strBuilder.append(", ");
648                        }
649                }
650                return strBuilder.toString();
651        }
652        
653}