Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.framework / org.gvsig.andami / src / main / java / org / gvsig / andami / Launcher.java @ 42449

History | View | Annotate | Download (162 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.andami;
24

    
25
import java.awt.BorderLayout;
26
import java.awt.Cursor;
27
import java.awt.Dimension;
28
import java.awt.EventQueue;
29
import java.awt.Frame;
30
import java.awt.KeyboardFocusManager;
31
import java.awt.Point;
32
import java.awt.Toolkit;
33
import java.awt.event.ActionEvent;
34
import java.awt.event.ActionListener;
35
import java.awt.event.WindowEvent;
36
import java.awt.event.WindowListener;
37
import java.io.BufferedOutputStream;
38
import java.io.BufferedReader;
39
import java.io.File;
40
import java.io.FileFilter;
41
import java.io.FileInputStream;
42
import java.io.FileNotFoundException;
43
import java.io.FileOutputStream;
44
import java.io.FileReader;
45
import java.io.IOException;
46
import java.io.InputStream;
47
import java.io.InputStreamReader;
48
import java.io.OutputStreamWriter;
49
import java.io.Reader;
50
import java.io.StringWriter;
51
import java.net.Authenticator;
52
import java.net.MalformedURLException;
53
import java.net.PasswordAuthentication;
54
import java.net.URL;
55
import java.net.URLClassLoader;
56
import java.nio.channels.FileChannel;
57
import java.security.AllPermission;
58
import java.security.CodeSource;
59
import java.security.PermissionCollection;
60
import java.security.Permissions;
61
import java.security.Policy;
62
import java.text.MessageFormat;
63
import java.util.ArrayList;
64
import java.util.Arrays;
65
import java.util.Collections;
66
import java.util.Comparator;
67
import java.util.Enumeration;
68
import java.util.HashMap;
69
import java.util.HashSet;
70
import java.util.Iterator;
71
import java.util.List;
72
import java.util.Locale;
73
import java.util.Map;
74
import java.util.Map.Entry;
75
import java.util.Properties;
76
import java.util.Set;
77
import java.util.TreeSet;
78
import java.util.logging.Level;
79
import java.util.prefs.Preferences;
80

    
81
import javax.swing.ImageIcon;
82
import javax.swing.JButton;
83
import javax.swing.JComponent;
84
import javax.swing.JDialog;
85
import javax.swing.JFrame;
86
import javax.swing.JOptionPane;
87
import javax.swing.JPopupMenu;
88
import javax.swing.ListSelectionModel;
89
import javax.swing.SwingUtilities;
90
import javax.swing.UIManager;
91

    
92

    
93
import org.apache.commons.cli.CommandLine;
94
import org.apache.commons.cli.CommandLineParser;
95
import org.apache.commons.cli.Options;
96
import org.apache.commons.cli.ParseException;
97
import org.apache.commons.cli.PosixParser;
98
import org.apache.commons.configuration.PropertiesConfiguration;
99
import org.apache.commons.io.FileUtils;
100
import org.apache.commons.lang3.JavaVersion;
101
import org.apache.commons.lang3.StringUtils;
102
import org.apache.commons.lang3.SystemUtils;
103
import org.apache.log4j.AppenderSkeleton;
104
import org.apache.log4j.PatternLayout;
105
import org.apache.log4j.PropertyConfigurator;
106
import org.apache.log4j.RollingFileAppender;
107
import org.apache.log4j.spi.LoggingEvent;
108
import org.apache.log4j.spi.ThrowableInformation;
109
import org.exolab.castor.xml.MarshalException;
110
import org.exolab.castor.xml.ValidationException;
111

    
112
import org.gvsig.andami.actioninfo.ActionInfo;
113
import org.gvsig.andami.actioninfo.ActionInfoManager;
114
import org.gvsig.andami.config.generate.Andami;
115
import org.gvsig.andami.config.generate.AndamiConfig;
116
import org.gvsig.andami.config.generate.Plugin;
117
import org.gvsig.andami.impl.UnsavedDataException;
118
import org.gvsig.andami.messages.Messages;
119
import org.gvsig.andami.messages.NotificationManager;
120
import org.gvsig.andami.persistence.serverData.ServerDataPersistence;
121
import org.gvsig.andami.plugins.ExclusiveUIExtension;
122
import org.gvsig.andami.plugins.ExtensionDecorator;
123
import org.gvsig.andami.plugins.IExtension;
124
import org.gvsig.andami.plugins.PluginClassLoader;
125
import org.gvsig.andami.plugins.config.generate.Action;
126
import org.gvsig.andami.plugins.config.generate.ActionTool;
127
import org.gvsig.andami.plugins.config.generate.AlternativeNames;
128
import org.gvsig.andami.plugins.config.generate.ComboButton;
129
import org.gvsig.andami.plugins.config.generate.ComboButtonElement;
130
import org.gvsig.andami.plugins.config.generate.ComboScale;
131
import org.gvsig.andami.plugins.config.generate.Depends;
132
import org.gvsig.andami.plugins.config.generate.Extension;
133
import org.gvsig.andami.plugins.config.generate.Extensions;
134
import org.gvsig.andami.plugins.config.generate.LabelSet;
135
import org.gvsig.andami.plugins.config.generate.Menu;
136
import org.gvsig.andami.plugins.config.generate.PluginConfig;
137
import org.gvsig.andami.plugins.config.generate.PopupMenu;
138
import org.gvsig.andami.plugins.config.generate.PopupMenus;
139
import org.gvsig.andami.plugins.config.generate.SelectableTool;
140
import org.gvsig.andami.plugins.config.generate.SkinExtension;
141
import org.gvsig.andami.plugins.config.generate.SkinExtensionType;
142
import org.gvsig.andami.plugins.config.generate.ToolBar;
143
import org.gvsig.andami.plugins.status.IExtensionStatus;
144
import org.gvsig.andami.plugins.status.IUnsavedData;
145
import org.gvsig.andami.ui.AndamiEventQueue;
146
import org.gvsig.andami.ui.DisablePluginsConflictingLayoutPanel;
147
import org.gvsig.andami.ui.MDIManagerLoadException;
148
import org.gvsig.andami.ui.ToolsWindowManager;
149
import org.gvsig.andami.ui.fonts.FontUtils;
150
import org.gvsig.andami.ui.mdiFrame.MDIFrame;
151
import org.gvsig.andami.ui.mdiFrame.MainFrame;
152
import org.gvsig.andami.ui.mdiManager.MDIManagerFactory;
153
import org.gvsig.andami.ui.splash.MultiSplashWindow;
154
import org.gvsig.andami.ui.theme.Theme;
155
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
156
import org.gvsig.andami.ui.wizard.UnsavedDataPanel.UnsavedDataPanelListener;
157
import org.gvsig.installer.lib.api.Dependencies;
158
import org.gvsig.installer.lib.api.Dependency;
159
import org.gvsig.installer.lib.api.InstallerLocator;
160
import org.gvsig.installer.lib.api.InstallerManager;
161
import org.gvsig.installer.lib.api.PackageInfo;
162
import org.gvsig.installer.lib.api.creation.MakePluginPackageServiceException;
163
import org.gvsig.installer.swing.api.SwingInstallerLocator;
164
import org.gvsig.installer.swing.api.execution.AbstractInstallPackageWizard;
165
import org.gvsig.installer.swing.api.wizard.InstallerWizardActionListener;
166
import org.gvsig.installer.swing.api.wizard.InstallerWizardPanel;
167
import org.gvsig.tools.ToolsLocator;
168
import org.gvsig.tools.exception.ListBaseException;
169
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
170
import org.gvsig.tools.swing.api.ToolsSwingLocator;
171
import org.gvsig.tools.swing.api.windowmanager.WindowManager.MODE;
172
import org.gvsig.tools.swing.icontheme.IconTheme;
173
import org.gvsig.tools.swing.icontheme.IconThemeManager;
174
import org.gvsig.tools.util.FolderSet;
175
import org.gvsig.tools.util.FolderSet.FolderEntry;
176
import org.gvsig.utils.DateTime;
177
import org.gvsig.utils.DefaultListModel;
178
import org.gvsig.utils.XMLEntity;
179
import org.gvsig.utils.xml.XMLEncodingUtils;
180
import org.gvsig.utils.xmlEntity.generate.XmlTag;
181

    
182
import org.slf4j.Logger;
183
import org.slf4j.LoggerFactory;
184

    
185
/**
186
 * <p>
187
 * Andami's launching class. This is the class used to create the Andami's
188
 * plugin environment.<br>
189
 * </p>
190
 *
191
 * <p>
192
 * <b>Syntax:</b> <br>
193
 * java [-Xmx512M (for 512MB of RAM)] [-classpath={a colon-separated(unix) or
194
 * semicolon-separated(windows) list of files containg base library of classes}]
195
 * [-Djava.library.path=PATH_TO_NATIVE_LIBRARIES]
196
 * PATH_TO_APPLICATION_HOME_DIRECTORY PATH_TO_APPLICATION_PLUGINS_DIRECTORY
197
 * [{list of additional custom application arguments separated by spaces}]
198
 * </p>
199
 *
200
 *
201
 * @author $author$
202
 * @version $Revision: 40305 $
203
 */
204
public class Launcher {
205

    
206
    public static abstract class MapWithAlias<Item> extends HashMap<String, Item> {
207

    
208
        private HashMap<String, String> aliases = new HashMap<String, String>();
209

    
210
        public abstract String[] getAliases(Item item);
211

    
212
        public boolean isAlias(String key) {
213
            return aliases.get(key) != null;
214
        }
215

    
216
        public String getMainKey(String key) {
217
            Item item = super.get(key);
218
            if (item != null) {
219
                return key;
220
            }
221
            String alias = aliases.get(key);
222
            if (alias != null) {
223
                return alias;
224
            }
225
            return null;
226
        }
227

    
228
        public Item get(Object key) {
229
            Item item = super.get(key);
230
            if (item != null) {
231
                return item;
232
            }
233
            String alias = aliases.get(key);
234
            if (alias != null) {
235
                return super.get(alias);
236
            }
237
            return null;
238
        }
239

    
240
        public boolean containsKey(Object key) {
241
            boolean contains = super.containsKey(key);
242
            if (contains) {
243
                return true;
244
            }
245
            String alias = aliases.get(key);
246
            return super.containsKey(alias);
247
        }
248

    
249
        public Item put(String key, Item value) {
250
            super.put(key, value);
251
            String[] aliases = getAliases(value);
252
            if (aliases == null) {
253
                return value;
254
            }
255
            for (int n = 0; n < aliases.length; n++) {
256
                this.aliases.put(aliases[n].trim(), key);
257
            }
258
            return value;
259
        }
260

    
261
        public void putAll(Map<? extends String, ? extends Item> m) {
262
            Iterator<?> it = m.entrySet().iterator();
263
            while (it.hasNext()) {
264
                Map.Entry<String, Item> x = (Map.Entry<String, Item>) it.next();
265
                this.put(x.getKey(), x.getValue());
266
            }
267
        }
268

    
269
        public Item remove(Object key) {
270
            Item item = super.get(key);
271
            if (item == null) {
272
                String alias = aliases.get(key);
273
                if (alias == null) {
274
                    return null;
275
                }
276
                item = super.get(alias);
277
                super.remove(alias);
278
            } else {
279
                super.remove(key);
280
            }
281
            String[] aliases = getAliases(item);
282
            if (aliases == null) {
283
                return item;
284
            }
285
            // Rebuild the alias list
286
            this.aliases = new HashMap<String, String>();
287
            Iterator<java.util.Map.Entry<String, Item>> it = this.entrySet().iterator();
288
            while (it.hasNext()) {
289
                java.util.Map.Entry<String, Item> entry = it.next();
290
                aliases = getAliases(entry.getValue());
291
                if (aliases == null) {
292
                    continue;
293
                }
294
                for (int n = 0; n < aliases.length; n++) {
295
                    this.aliases.put(aliases[n].trim(), entry.getKey());
296
                }
297
            }
298

    
299
            return item;
300
        }
301

    
302
    }
303

    
304
    public static class PluginsConfig extends MapWithAlias<org.gvsig.andami.plugins.config.generate.PluginConfig> {
305

    
306
        public String[] getAliases(
307
                org.gvsig.andami.plugins.config.generate.PluginConfig item) {
308
            return getAlternativeNames(item);
309
        }
310

    
311
        static String[] getAlternativeNames(org.gvsig.andami.plugins.config.generate.PluginConfig item) {
312
            AlternativeNames[] x = item.getAlternativeNames();
313
            if (x == null) {
314
                return null;
315
            }
316
            String[] r = new String[x.length];
317
            for (int i = 0; i < x.length; i++) {
318
                r[i] = x[i].getName();
319
            }
320
            return r;
321
        }
322

    
323
    }
324

    
325
    public static class PluginsServices extends MapWithAlias<org.gvsig.andami.PluginServices> {
326

    
327
        public String[] getAliases(org.gvsig.andami.PluginServices item) {
328
            return item.getAlternativeNames();
329
        }
330
    }
331

    
332
    protected static Logger logger = LoggerFactory.getLogger(Launcher.class
333
            .getName());
334
    protected static Preferences prefs = Preferences.userRoot().node(
335
            "gvsig.connection");
336
    protected static AndamiConfig andamiConfig;
337
    protected static MultiSplashWindow splashWindow;
338
    protected static String appName;
339
    protected static Locale locale;
340
    protected static PluginsConfig pluginsConfig = new PluginsConfig();
341
    protected static PluginsServices pluginsServices = new PluginsServices();
342
    protected static MDIFrame frame;
343
    protected static HashMap<Class<? extends IExtension>, ExtensionDecorator> classesExtensions = new HashMap<Class<? extends IExtension>, ExtensionDecorator>();
344
    protected static String andamiConfigPath;
345
    protected static final String nonWinDefaultLookAndFeel = "com.jgoodies.looks.plastic.PlasticXPLookAndFeel";
346

    
347
    protected static List<String> pluginsOrdered = new ArrayList<String>();
348
    protected static List<IExtension> extensions = new ArrayList<IExtension>();
349
    protected static String appHomeDir = null;
350
    // it seems castor uses this encoding
351
    protected static final String CASTORENCODING = "UTF8";
352

    
353
    protected static ListBaseException launcherrors = null;
354

    
355
    protected static Theme theme = null;
356

    
357
    private List<String> deprecatedPluginNames = null;
358

    
359
    private static final class ProxyAuth extends Authenticator {
360

    
361
        private PasswordAuthentication auth;
362

    
363
        private ProxyAuth(String user, String pass) {
364
            auth = new PasswordAuthentication(user, pass.toCharArray());
365
        }
366

    
367
        protected PasswordAuthentication getPasswordAuthentication() {
368
            return auth;
369
        }
370
    }
371

    
372
    private static Launcher launcherInstance;
373

    
374
    public static Launcher getInstance() {
375
        if (launcherInstance == null) {
376
            launcherInstance = new Launcher();
377
        }
378
        return launcherInstance;
379
    }
380

    
381
    public static void main(String[] args) throws Exception {
382
        Launcher launcher = getInstance();
383
        boolean install = false;
384
        for (int i = 0; i < args.length; i++) {
385
            if (args[i].equalsIgnoreCase("--install")) {
386
                install = true;
387
            }
388
        }
389

    
390
        try {
391
            if (install) {
392
                launcher.doInstall(args);
393
            } else {
394
                launcher.doMain(args);
395
            }
396
        } catch (Exception e) {
397
            logger.error("excepci?n al arrancar", e);
398
            System.exit(-1);
399
        }
400
    }
401

    
402
    protected void downloadExtensions(String extDir) {
403
        // do nothing
404
    }
405

    
406
    public static class LaunchException extends ListBaseException {
407

    
408
        private static final long serialVersionUID = 4541192746962684705L;
409

    
410
        public LaunchException() {
411
            super("Errors in initialization of application.",
412
                    "_errors_in_initialization_of_application",
413
                    serialVersionUID);
414
        }
415

    
416
    }
417

    
418
    protected void addError(Throwable ex) {
419
        if (launcherrors == null) {
420
            launcherrors = new LaunchException();
421
        }
422
        launcherrors.add(ex);
423
    }
424

    
425
    protected void addError(String msg, Throwable cause) {
426
        logger.error(msg, cause);
427
        this.addError(new RuntimeException(msg, cause));
428
    }
429

    
430
    protected void addError(String msg) {
431
        this.addError(msg, null);
432
    }
433

    
434
    private String translate(String msg) {
435
        return PluginServices.getText(Launcher.class, msg);
436
    }
437

    
438
    private List<String> getDeprecatedPluginNames() {
439
        if (deprecatedPluginNames == null) {
440
            String[] ss = new String[]{
441
                "org.gvsig.app",
442
                "org.gvsig.coreplugin",
443
                "org.gvsig.editing",
444
                "org.gvsig.installer.app.extension",
445
                "org.gvsig.exportto.app.extension"
446
            };
447
            deprecatedPluginNames = Arrays.asList(ss);
448
        }
449
        return deprecatedPluginNames;
450
    }
451

    
452
    public void doMain(String[] args) throws Exception {
453

    
454
        if (args.length < 1) {
455
            System.err.println("Usage: Launcher appName plugins-directory [language=locale]");
456
            System.err.println("No arguments specified.");
457
            System.err.println("Use default arguments 'gvSIG gvSIG/extensiones'");
458
            args = new String[]{"gvSIG", "gvSIG/extensiones"};
459
        }
460

    
461
        initializeApp(args, null);
462

    
463
                // Solucionamos el problema de permisos que se produc?do con Java
464
        // Web Start con este codigo.
465
        // System.setSecurityManager(null);
466
        Policy.setPolicy(new Policy() {
467

    
468
            public PermissionCollection getPermissions(CodeSource codesource) {
469
                Permissions perms = new Permissions();
470
                perms.add(new AllPermission());
471
                return (perms);
472
            }
473

    
474
            public void refresh() {
475
            }
476
        });
477

    
478
        new DefaultLibrariesInitializer().fullInitialize(true);
479
        InstallerLocator.getInstallerManager().setDownloadBaseURL(
480
                new URL("http://downloads.gvsig.org/download/gvsig-desktop/"));
481

    
482
        try {
483
            initIconThemes();
484
        } catch (Exception ex) {
485
            this.addError("Can't initialize icon theme", ex);
486
        }
487
        // Registramos los iconos base
488
        try {
489
            registerIcons();
490
        } catch (Exception ex) {
491
            this.addError("Can't register icons", ex);
492
        }
493

    
494
        // Obtener la personalizaci?n de la aplicacion.
495
        try {
496
            logger.info("Initialize andami theme");
497
            theme = getTheme(andamiConfig.getPluginsDirectory());
498
        } catch (Exception ex) {
499
            this.addError("Can't get personalized theme for the application",
500
                    ex);
501
        }
502
        UIManager.put("Desktop.background", theme.getBackgroundColor());
503

    
504
        // Mostrar la ventana de inicio
505
        Frame f = new Frame();
506
        splashWindow = new MultiSplashWindow(f, theme, 27);
507

    
508
        // Ponemos los datos del proxy
509
        splashWindow.process(translate("SplashWindow.configuring_proxy"));
510
        logger.info("Configute http proxy");
511
        configureProxy();
512

    
513
        // Buscar actualizaciones de los plugins
514
        splashWindow.process(translate("SplashWindow.looking_for_updates"));
515
        try {
516
//                        this.downloadExtensions(andamiConfig.getPluginsDirectory());
517
        } catch (Exception ex) {
518
            this.addError("Can't downloads plugins", ex);
519
        }
520

    
521
        splashWindow.process(translate("SplashWindow.initialize_install_manager"));
522
        initializeInstallerManager();
523

    
524
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
525
        PackageInfo[] installedPackages = null;
526
        try {
527
            installedPackages = installerManager.getInstalledPackages();
528
        } catch (MakePluginPackageServiceException e) {
529
            // Do nothing, ignore errors
530
        }
531
        logger.info("Dump system information");
532
        logger_info(getInformation(installedPackages));
533
        saveEnvironInformation(installedPackages);
534

    
535
        // Se leen los config.xml de los plugins
536
        splashWindow.process(translate("SplashWindow.load_plugins_configuration"));
537
        try {
538
            logger.info("Load plugins information");
539
            this.loadPluginConfigs();
540
            if (pluginsConfig.isEmpty()) {
541
                logger.warn("No valid plugin was found.");
542
                System.exit(-1);
543
            }
544
        } catch (Throwable ex) {
545
            this.addError("Can't load plugins", ex);
546
        }
547

    
548
        splashWindow.process(translate("SplashWindow.check_incompatible_plugins"));
549
        fixIncompatiblePlugins(installedPackages);
550

    
551
        // Se configura el classloader del plugin
552
        splashWindow.process(translate("SplashWindow.setup_plugins_configuration"));
553
        try {
554
            logger.info("Configure plugins class loader");
555
            this.loadPluginServices();
556
        } catch (Throwable ex) {
557
            logger.warn("Can't initialize plugin's classloaders  ", ex);
558
        }
559
        try {
560
            registerActions();
561
        } catch (Throwable ex) {
562
            logger.warn("Can't register actions of plugins", ex);
563
        }
564

    
565
        initializeIdentityManagement(new File(andamiConfig.getPluginsDirectory()).getAbsoluteFile());
566

    
567
        // Initialize libraries
568
        splashWindow.process(translate("SplashWindow.initialize_plugins_libraries"));
569
        initializeLibraries();
570

    
571
        // Se carga un Skin si alguno ide los plugins trae informacion para ello
572
        splashWindow.process(translate("SplashWindow.looking_for_a_skin"));
573
        logger.info("Initialize skin");
574
        skinPlugin(null);
575

    
576
        // Se configura la cola de eventos
577
        splashWindow.process(translate("setting_up_event_queue"));
578
        EventQueue waitQueue = new AndamiEventQueue();
579
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue);
580

    
581
        // Se configura la internacionalizacion del plugin
582
        splashWindow.process(translate("SplashWindow.starting_plugin_internationalization_system"));
583
        pluginsMessages();
584

    
585
        // Se modifica el andami-config con los plugins nuevos
586
        splashWindow.process(translate("SplashWindow.update_framework_configuration"));
587
        updateAndamiConfig();
588

    
589
        frame = MDIFrame.getInstance();
590
        // Se configura el nombre e icono de la aplicacion
591
        splashWindow.process(translate("SplashWindow.setting_up_applications_name_and_icons"));
592
        frameIcon(theme);
593

    
594
        // Se prepara el MainFrame para albergar las extensiones
595
        splashWindow.process(translate("SplashWindow.preparing_workbench"));
596
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
597
        SwingUtilities.invokeAndWait(new Runnable() {
598
            public void run() {
599
                frame.init();
600
            }
601
        });
602
        ToolsSwingLocator.registerWindowManager(ToolsWindowManager.class);
603

    
604
        // Leer el fichero de persistencia de los plugins
605
        splashWindow.process(translate("SplashWindow.loading_plugin_settings"));
606
        loadPluginsPersistence();
607

    
608
                // Se instalan los controles del skin
609
        // Se inicializan todas las extensiones de todos los plugins
610
        splashWindow.process(translate("SplashWindow.initializing_extensions"));
611
        SwingUtilities.invokeAndWait(new Runnable() {
612
            public void run() {
613
                initializeExtensions();
614
            }
615
        });
616

    
617
        // Se inicializan la extension exclusiva
618
        splashWindow.process(translate("SplashWindow.setting_up_master_extension"));
619
        SwingUtilities.invokeAndWait(new Runnable() {
620
            public void run() {
621
                initializeExclusiveUIExtension();
622
            }
623
        });
624
        frame.setClassesExtensions(classesExtensions);
625

    
626
        // Se instalan los controles de las extensiones de los plugins
627
        message(translate("SplashWindow.installing_extensions_controls"));
628
        SwingUtilities.invokeAndWait(new Runnable() {
629
            public void run() {
630
                installPluginsControls();
631
            }
632
        });
633

    
634
        // Se instalan los menus de las extensiones de los plugins
635
        message(translate("SplashWindow.installing_extensions_menus"));
636
        SwingUtilities.invokeAndWait(new Runnable() {
637
            public void run() {
638
                installPluginsMenus();
639
            }
640
        });
641

    
642
        message(translate("SplashWindow.initializing_server_data_persistence"));
643
        ServerDataPersistence.registerPersistence();
644

    
645
        // Se instalan las etiquetas de las extensiones de los plugins
646
        message(translate("SplashWindow.installing_extensions_labels"));
647
        SwingUtilities.invokeAndWait(new Runnable() {
648
            public void run() {
649
                installPluginsLabels();
650
            }
651
        });
652

    
653
        // Se muestra el frame principal
654
        message(translate("creating_main_window"));
655
        frame.setVisible(true);
656
        frame.setCursor(Cursor.WAIT_CURSOR);
657

    
658
                // Definimos un KeyEventDispatcher global para que las extensiones
659
        // puedan registrar sus "teclas rapidas".
660
        message(translate("SplashWindow.initializing_accelerator_keys"));
661
        GlobalKeyEventDispatcher keyDispatcher = GlobalKeyEventDispatcher.getInstance();
662
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keyDispatcher);
663

    
664
        message(translate("SplashWindow.enable_controls"));
665
        SwingUtilities.invokeAndWait(new Runnable() {
666
            public void run() {
667
                try {
668
                    frame.enableControls();
669
                } catch (Throwable th) {
670
                    logger.warn("Problems enabling controls", th);
671
                }
672
            }
673
        });
674

    
675
        // Se ejecuta el postInitialize
676
        message(translate("SplashWindow.post_initializing_extensions"));
677
        SwingUtilities.invokeAndWait(new Runnable() {
678
            public void run() {
679
                postInitializeExtensions();
680
            }
681
        });
682

    
683
        message(translate("SplashWindow.enable_controls"));
684
        SwingUtilities.invokeAndWait(new Runnable() {
685
            public void run() {
686
                try {
687
                    frame.enableControls();
688
                    message(translate("StatusBar.Aplicacion_iniciada"));
689
                } catch (Throwable th) {
690
                    logger.warn("Problems enabling controls", th);
691
                }
692
            }
693
        });
694

    
695
        splashWindow.close();
696

    
697
        frame.setCursor(Cursor.DEFAULT_CURSOR);
698

    
699
        if (launcherrors != null) {
700
            NotificationManager.addError(launcherrors);
701
        }
702
        org.apache.log4j.Logger.getRootLogger().addAppender(
703
                new NotificationAppender());
704

    
705
        /*
706
         * Executes additional tasks required by plugins
707
         */
708
        PluginsLocator.getManager().executeStartupTasks();
709

    
710
    }
711

    
712
    private void initializeInstallerManager() {
713
        PluginsManager pluginmgr = PluginsLocator.getManager();
714
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
715

    
716
            //
717
        // Configure repository of plugins
718
        //
719
        List<File> folders = pluginmgr.getPluginsFolders();
720
        for (File folder : folders) {
721
            installerManager.addLocalAddonRepository(folder, "plugin");
722
        }
723
        installerManager.setDefaultLocalAddonRepository(folders.get(0), "plugin");
724

    
725
            //
726
        // Configure repository of iconsets
727
        //
728
        IconThemeManager iconManager = ToolsSwingLocator.getIconThemeManager();
729
        FolderSet fset = iconManager.getRepository();
730
        Iterator<FolderSet.FolderEntry> it = fset.iterator();
731
        boolean first = true;
732
        while (it.hasNext()) {
733
            FolderEntry entry = it.next();
734
            installerManager.addLocalAddonRepository(entry.getFolder(), "iconset");
735
            if (first) {
736
                first = false;
737
                installerManager.setDefaultLocalAddonRepository(entry.getFolder(), "iconset");
738
            }
739
        }
740

    
741
    }
742

    
743
    private void message(final String msg) {
744
        if (!SwingUtilities.isEventDispatchThread()) {
745
            try {
746
                SwingUtilities.invokeAndWait(new Runnable() {
747
                    public void run() {
748
                        message(msg);
749
                    }
750
                });
751
            } catch (Exception e) {
752
                logger.info(msg);
753
                logger.warn("Error showing message.", e);
754
            }
755
            return;
756
        }
757
        if (splashWindow.isVisible()) {
758
            splashWindow.process(msg);
759
        }
760
        if (frame.isVisible()) {
761
            frame.message(msg, JOptionPane.INFORMATION_MESSAGE);
762
        }
763
    }
764

    
765
    private void initializeLibraries() {
766
        List<ClassLoader> classLoaders = new ArrayList<ClassLoader>(
767
                pluginsOrdered.size() + 1);
768
        classLoaders.add(getClass().getClassLoader());
769
        Iterator<String> iter = pluginsOrdered.iterator();
770

    
771
        logger.info("Initializing plugins libraries: ");
772
        while (iter.hasNext()) {
773
            String pName = (String) iter.next();
774
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
775
            logger.info("Initializing plugin libraries (" + pName + ")");
776
            classLoaders.add(ps.getClassLoader());
777
        }
778

    
779
                // Create the libraries initializer and
780
        // initialize the plugin libraries
781
        new DefaultLibrariesInitializer(classLoaders
782
                .toArray(new ClassLoader[classLoaders.size()]))
783
                .fullInitialize(true);
784

    
785
        // Remove them all, we don't need them anymore
786
        classLoaders.clear();
787
        classLoaders = null;
788
    }
789

    
790
    /**
791
     * @param args
792
     * @throws IOException
793
     * @throws ConfigurationException
794
     */
795
    private void initializeApp(String[] args, String applicationClasifier) throws IOException, ConfigurationException {
796
        if (args.length < 1) {
797
            appName = "gvSIG"; // Nombre de aplicacion por defecto es "gvSIG"
798
        } else {
799
            appName = args[0];
800
        }
801
        getOrCreateConfigFolder();
802
        configureLogging(appName, applicationClasifier);
803
        if (!validJVM()) {
804
            logger.error("Not a valid JRE. Exit application.");
805
            System.exit(-1);
806
        }
807
        // Clean temporal files
808
        Utilities.cleanUpTempFiles();
809

    
810
        if (args.length < 2) {
811
            loadAndamiConfig("gvSIG/extensiones"); // Valor por defecto
812
        } else {
813
            loadAndamiConfig(args[1]);
814
        }
815

    
816
                // Hacemos visibles los argumentos como una propiedad est?tica
817
        // de plugin services para quien lo quiera usar (por ejemplo, para
818
        // cargar un proyecto por l?nea de comandos)
819
        PluginServices.setArguments(args);
820

    
821
        configureLocales(args);
822

    
823
        logger.info("Configure LookAndFeel");
824
        configureLookAndFeel();
825
    }
826

    
827
    /**
828
     *
829
     */
830
    private void configureLookAndFeel() {
831
        // Se pone el lookAndFeel
832
        try {
833
            String lookAndFeel = getAndamiConfig().getLookAndFeel();
834
            if (lookAndFeel == null) {
835
                lookAndFeel = getDefaultLookAndFeel();
836
            }
837
            UIManager.setLookAndFeel(lookAndFeel);
838
        } catch (Exception e) {
839
            logger.warn(Messages.getString("Launcher.look_and_feel"), e);
840
        }
841
        FontUtils.initFonts();
842
    }
843

    
844
    /**
845
     * @param args
846
     * @throws ConfigurationException
847
     */
848
    private void loadAndamiConfig(String pluginFolder)
849
            throws ConfigurationException {
850
        andamiConfigPath = appHomeDir + File.separator + "andami-config.xml";
851
        andamiConfigFromXML(andamiConfigPath);
852
        andamiConfig.setPluginsDirectory(pluginFolder);
853
    }
854

    
855
    /**
856
     *
857
     */
858
    private void getOrCreateConfigFolder() {
859
        // Create application configuration folder
860
        appHomeDir = System.getProperty(appName + ".home");
861
        if (appHomeDir == null) {
862
            appHomeDir = System.getProperty("user.home");
863
        }
864

    
865
        appHomeDir += File.separator + appName;
866
        File parent = new File(appHomeDir);
867
        parent.mkdirs();
868
    }
869

    
870
    /**
871
     * @param args
872
     * @throws IOException
873
     */
874
    private void configureLogging(String appName, String applicationClasifier) throws IOException {
875
        // Configurar el log4j
876

    
877
        String pathname;
878
        if (StringUtils.isBlank(applicationClasifier)) {
879
            pathname = appHomeDir + File.separator + appName + ".log";
880
        } else {
881
            pathname = appHomeDir + File.separator + appName + "-" + applicationClasifier + ".log";
882
        }
883
        URL config = Launcher.class.getClassLoader().getResource("log4j.properties");
884
        if (config == null) {
885
            config = Launcher.class.getClassLoader().getResource("default-log4j/log4j.properties");
886
        }
887
        PropertyConfigurator.configure(config);
888
        PatternLayout l = new PatternLayout("%p %t %C - %m%n");
889
        RollingFileAppender fa = new RollingFileAppender(l, pathname, false);
890
        fa.setMaxFileSize("512KB");
891
        fa.setMaxBackupIndex(3);
892
        org.apache.log4j.Logger.getRootLogger().addAppender(fa);
893
        logger.info("Loadded log4j.properties from " + config.toString());
894
        if (StringUtils.isBlank(applicationClasifier)) {
895
            logger.info("Application " + appName);
896
        } else {
897
            logger.info("Application " + appName + "-" + applicationClasifier);
898
        }
899
    }
900

    
901
    private class NotificationAppender extends AppenderSkeleton {
902

    
903
        @Override
904
        protected void append(LoggingEvent event) {
905
            if (event.getLevel() == org.apache.log4j.Level.ERROR
906
                    || event.getLevel() == org.apache.log4j.Level.FATAL) {
907

    
908
                Throwable th = null;
909
                ThrowableInformation thi = event.getThrowableInformation();
910
                if (thi != null) {
911
                    th = thi.getThrowable();
912
                }
913
                NotificationManager.dispatchError(event.getRenderedMessage(), th);
914
                return;
915
            }
916
                        // if (event.getLevel() == org.apache.log4j.Level.WARN) {
917
            // NotificationManager.dispatchWarning(event.getRenderedMessage(),
918
            // null);
919
            // return;
920
            // }
921
        }
922

    
923
        @Override
924
        public void close() {
925
            // TODO Auto-generated method stub
926

    
927
        }
928

    
929
        @Override
930
        public boolean requiresLayout() {
931
            // TODO Auto-generated method stub
932
            return false;
933
        }
934

    
935
    }
936

    
937
    /**
938
     * Return the directory applicaction is installed.
939
     */
940
    public static String getApplicationDirectory() {
941
        return getApplicationFolder().getAbsolutePath();
942
    }
943

    
944
    public static File getApplicationFolder() {
945
        // TODO: check if there is a better way to handle this
946
        return new File(System.getProperty("user.dir"));
947
    }
948

    
949
    private void registerIcons() {
950
        IconTheme theme = PluginServices.getIconTheme();
951
        ClassLoader loader = Launcher.class.getClassLoader();
952

    
953
        String[][] icons = {
954
            // MultiSplashWindow
955
            {"main", "splash-default"},
956
            // NewStatusBar
957
            {"main", "statusbar-info"},
958
            {"main", "statusbar-warning"},
959
            {"main", "statusbar-error"}
960
        };
961
        for (int i = 0; i < icons.length; i++) {
962
            try {
963
                IconThemeHelper.registerIcon(icons[i][0], icons[i][1], Launcher.class);
964
            } catch (Exception e) {
965
                logger.info("Can't register icon '" + icons[i][0] + "' (" + icons[i][1] + ").");
966
            }
967
        }
968
        theme.setDefaultIcon(loader.getResource("images/main/default-icon.png"));
969
    }
970

    
971
    private Properties loadProperties(File f) {
972
        FileInputStream fin = null;
973
        Properties p = null;
974
        try {
975
            fin = new FileInputStream(f);
976
            p = new Properties();
977
            p.load(fin);
978
        } catch (IOException ex) {
979
            // Do nothing
980
        }
981
        return p;
982
    }
983

    
984
    /**
985
     * Obtiene la personalizaci?n de los iconos, splash, fondo y el nombre de
986
     * la aplicaci?n.
987
     *
988
     * @return Theme
989
     */
990
    private Theme getTheme(String pluginsDirectory) {
991
        File infoFile = new File(Launcher.getApplicationFolder(), "package.info");
992
        File themeFile = null;
993
        List<Theme> themes = new ArrayList<Theme>();
994

    
995
        // Try to get theme from args
996
        String name = PluginServices.getArgumentByName("andamiTheme");
997
        if (name != null) {
998
            themeFile = new File(name);
999
            logger.info("search andami-theme in {}", themeFile.getAbsolutePath());
1000
            if (themeFile.exists()) {
1001
                Theme theme = new Theme(loadProperties(infoFile));
1002
                theme.readTheme(themeFile);
1003
                logger.info("andami-theme found in {}", themeFile.getAbsolutePath());
1004
                return theme;
1005
            }
1006
        }
1007

    
1008
        // Try to get theme from a plugin
1009
        File pluginsDir = new File(pluginsDirectory);
1010
        if (!pluginsDir.isAbsolute()) {
1011
            pluginsDir = new File(getApplicationFolder(), pluginsDirectory);
1012
        }
1013
        if (pluginsDir.exists()) {
1014
            logger.info("search andami-theme in plugins folder '" + pluginsDir.getAbsolutePath() + "'.");
1015
            File[] pluginDirs = pluginsDir.listFiles();
1016
            if (pluginDirs.length > 0) {
1017
                for (int i = 0; i < pluginDirs.length; i++) {
1018
                    File pluginThemeFile = new File(pluginDirs[i],
1019
                            "theme" + File.separator + "andami-theme.xml");
1020
                    if (pluginThemeFile.exists()) {
1021
                        Theme theme = new Theme(loadProperties(infoFile));
1022
                        theme.readTheme(pluginThemeFile);
1023
                        themes.add(theme);
1024
                    }
1025
                }
1026
            }
1027
        }
1028

    
1029
        // Try to get theme from dir gvSIG in user home
1030
        themeFile = new File(getAppHomeDir(), "theme" + File.separator
1031
                + "andami-theme.xml");
1032
        logger.info("search andami-theme in user's home {}", themeFile
1033
                .getAbsolutePath());
1034
        if (themeFile.exists()) {
1035
            Theme theme = new Theme(loadProperties(infoFile));
1036
            theme.readTheme(themeFile);
1037
            themes.add(theme);
1038
        }
1039

    
1040
        // Try to get theme from the instalation dir of gvSIG.
1041
        themeFile = new File(getApplicationDirectory(), "theme"
1042
                + File.separator + "andami-theme.xml");
1043
        logger.info("search andami-theme in installation folder {}", themeFile
1044
                .getAbsolutePath());
1045
        if (themeFile.exists()) {
1046
            Theme theme = new Theme(loadProperties(infoFile));
1047
            theme.readTheme(themeFile);
1048
            themes.add(theme);
1049
        }
1050

    
1051
        Collections.sort(themes, new Comparator<Theme>() {
1052
            public int compare(Theme t1, Theme t2) {
1053
                return t2.getPriority() - t1.getPriority();
1054
            }
1055
        });
1056
        if (logger.isInfoEnabled()) {
1057
            logger.info("Found andami-themes in:");
1058
            for (Theme theme : themes) {
1059
                logger.info(" - " + theme.getPriority() + ", " + theme.getSource().getAbsolutePath());
1060
            }
1061
        }
1062
        Theme theme = themes.get(0);
1063
        logger.info("Using theme '" + theme.getSource() + "'.");
1064
        return theme;
1065
    }
1066

    
1067
    /**
1068
     * Establece los datos que tengamos guardados respecto de la configuracion
1069
     * del proxy.
1070
     */
1071
    private void configureProxy() {
1072
        String host = prefs.get("firewall.http.host", "");
1073
        String port = prefs.get("firewall.http.port", "");
1074

    
1075
        System.getProperties().put("http.proxyHost", host);
1076
        System.getProperties().put("http.proxyPort", port);
1077

    
1078
        // Ponemos el usuario y clave del proxy, si existe
1079
        String proxyUser = prefs.get("firewall.http.user", null);
1080
        String proxyPassword = prefs.get("firewall.http.password", null);
1081
        if (proxyUser != null) {
1082
            System.getProperties().put("http.proxyUserName", proxyUser);
1083
            System.getProperties().put("http.proxyPassword", proxyPassword);
1084

    
1085
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
1086
        } else {
1087
            Authenticator.setDefault(new ProxyAuth("", ""));
1088
        }
1089
    }
1090

    
1091
    /**
1092
     * Recupera la geometr?a (tama?o, posic?n y estado) de la ventana
1093
     * principal de Andami. TODO Pendiente de ver como se asigna un
1094
     * pluginServices para el launcher.
1095
     *
1096
     * @author LWS
1097
     */
1098
    private void restoreMDIStatus(XMLEntity xml) {
1099
        if (xml == null) {
1100
            xml = new XMLEntity();
1101
        }
1102
        // ====================================
1103
        // restore frame size
1104
        Dimension sz = new Dimension(
1105
                MainFrame.MAIN_FRAME_SIZE_DEFAULT[0],
1106
                MainFrame.MAIN_FRAME_SIZE_DEFAULT[1]);
1107
        if (xml.contains(MainFrame.MAIN_FRAME_SIZE)) {
1108
            int[] wh = xml.getIntArrayProperty(MainFrame.MAIN_FRAME_SIZE);
1109
            sz = new Dimension(wh[0], wh[1]);
1110
        }
1111
        frame.setSize(sz);
1112
        // ==========================================
1113
        // restore frame location
1114
        Point pos = new Point(
1115
                MainFrame.MAIN_FRAME_POS_DEFAULT[0],
1116
                MainFrame.MAIN_FRAME_POS_DEFAULT[1]);
1117
        if (xml.contains(MainFrame.MAIN_FRAME_POS)) {
1118
            int[] xy = xml.getIntArrayProperty(MainFrame.MAIN_FRAME_POS);
1119
            pos = new Point(xy[0], xy[1]);
1120
        }
1121
        frame.setLocation(pos);
1122
        // =============================================
1123
        // restore frame state (Maximized, minimized, etc);
1124
        int state = MainFrame.MAIN_FRAME_EXT_STATE_DEFAULT;
1125
        if (xml.contains(MainFrame.MAIN_FRAME_EXT_STATE)) {
1126
            state = xml.getIntProperty(MainFrame.MAIN_FRAME_EXT_STATE);
1127
        }
1128
        frame.setExtendedState(state);
1129
    }
1130

    
1131
    private XMLEntity saveMDIStatus() {
1132
        XMLEntity xml = new XMLEntity();
1133
        // save frame size
1134
        int[] wh = new int[2];
1135
        wh[0] = frame.getWidth();
1136
        wh[1] = frame.getHeight();
1137
        xml.putProperty(MainFrame.MAIN_FRAME_SIZE, wh);
1138
        // save frame location
1139
        int[] xy = new int[2];
1140
        xy[0] = frame.getX();
1141
        xy[1] = frame.getY();
1142
        xml.putProperty(MainFrame.MAIN_FRAME_POS, xy);
1143
        // save frame status
1144
        xml.putProperty(MainFrame.MAIN_FRAME_EXT_STATE,
1145
                frame.getExtendedState());
1146
        return xml;
1147
    }
1148

    
1149
    private boolean validJVM() {
1150
        if (!SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_4)) {
1151
            logger.warn("gvSIG requires Java version 1.4 or higher.");
1152
            logger.warn("The Java HOME is '" + SystemUtils.getJavaHome().getAbsolutePath() + "'.");
1153
            return false;
1154
        }
1155
        if (SystemUtils.isJavaAwtHeadless()) {
1156
            logger.warn("The java used by gvSIG does not contain the libraries for access to the graphical interface (AWT-headless)");
1157
            logger.warn("The Java HOME is '" + SystemUtils.getJavaHome().getAbsolutePath() + "'.");
1158
            return false;
1159
        }
1160
        return true;
1161
    }
1162

    
1163
    private void loadPluginsPersistence() throws ConfigurationException {
1164
        XMLEntity entity = persistenceFromXML();
1165

    
1166
        for (int i = 0; i < entity.getChildrenCount(); i++) {
1167
            XMLEntity plugin = entity.getChild(i);
1168
            String pName = plugin
1169
                    .getStringProperty("com.iver.andami.pluginName");
1170

    
1171
            if (pName.compareToIgnoreCase("com.iver.cit.gvsig") == 0) {
1172
                pName = "org.gvsig.app";
1173
            }
1174
            if (pluginsServices.get(pName) != null) {
1175
                ((PluginServices) pluginsServices.get(pName))
1176
                        .setPersistentXML(plugin);
1177
            } else {
1178
                if (pName.startsWith("Andami.Launcher")) {
1179
                    restoreMDIStatus(plugin);
1180
                }
1181
            }
1182
        }
1183
    }
1184

    
1185
    /**
1186
     * Salva la persistencia de los plugins.
1187
     *
1188
     * @author LWS
1189
     */
1190
    private void savePluginPersistence() {
1191
        Iterator<String> i = pluginsConfig.keySet().iterator();
1192

    
1193
        XMLEntity entity = new XMLEntity();
1194

    
1195
        while (i.hasNext()) {
1196
            String pName = i.next();
1197
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1198
            XMLEntity ent = ps.getPersistentXML();
1199

    
1200
            if (ent != null) {
1201
                ent.putProperty("com.iver.andami.pluginName", pName);
1202
                entity.addChild(ent);
1203
            }
1204
        }
1205
        XMLEntity ent = saveMDIStatus();
1206
        if (ent != null) {
1207
            ent.putProperty("com.iver.andami.pluginName", "Andami.Launcher");
1208
            entity.addChild(ent);
1209
        }
1210
        try {
1211
            persistenceToXML(entity);
1212
        } catch (ConfigurationException e1) {
1213
            this
1214
                    .addError(
1215
                            Messages
1216
                            .getString("Launcher.Se_produjo_un_error_guardando_la_configuracion_de_los_plugins"),
1217
                            e1);
1218
        }
1219
    }
1220

    
1221
    private void installPluginsLabels() {
1222
        Iterator<String> i = pluginsConfig.keySet().iterator();
1223

    
1224
        while (i.hasNext()) {
1225
            String name = i.next();
1226
            PluginConfig pc = pluginsConfig.get(name);
1227
            PluginServices ps = (PluginServices) pluginsServices.get(name);
1228

    
1229
            LabelSet[] ls = pc.getLabelSet();
1230

    
1231
            for (int j = 0; j < ls.length; j++) {
1232
                PluginClassLoader loader = ps.getClassLoader();
1233

    
1234
                try {
1235
                    Class clase = loader.loadClass(ls[j].getClassName());
1236
                    frame.setStatusBarLabels(clase, ls[j].getLabel());
1237
                } catch (Throwable e) {
1238
                    this.addError(
1239
                            Messages.getString("Launcher.labelset_class"), e);
1240
                }
1241
            }
1242
        }
1243
    }
1244

    
1245
    private String configureSkin(XMLEntity xml, String defaultSkin) {
1246
        if (defaultSkin == null) {
1247
            for (int i = 0; i < xml.getChildrenCount(); i++) {
1248
                if (xml.getChild(i).contains("Skin-Selected")) {
1249
                    String className = xml.getChild(i).getStringProperty(
1250
                            "Skin-Selected");
1251
                    return className;
1252
                }
1253
            }
1254
        }
1255
        // return "com.iver.core.mdiManager.NewSkin";
1256
        return defaultSkin;
1257
    }
1258

    
1259
    private void fixSkin(SkinExtension skinExtension,
1260
            PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
1261
        // now insert the skin selected.
1262
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
1263
                // MDIManagerFactory.setSkinExtension(se,
1264
        // ps.getClassLoader());
1265

    
1266
        Class<? extends IExtension> skinClass;
1267

    
1268
        try {
1269
            skinClass = (Class<? extends IExtension>) pluginClassLoader
1270
                    .loadClass(skinExtension.getClassName());
1271

    
1272
            IExtension skinInstance = skinClass.newInstance();
1273
            ExtensionDecorator newExtensionDecorator = new ExtensionDecorator(
1274
                    skinInstance, ExtensionDecorator.INACTIVE);
1275
            classesExtensions.put(skinClass, newExtensionDecorator);
1276
        } catch (ClassNotFoundException e) {
1277
            logger.error(Messages
1278
                    .getString("Launcher.No_se_encontro_la_clase_mdi_manager"),
1279
                    e);
1280
            throw new MDIManagerLoadException(e);
1281
        } catch (InstantiationException e) {
1282
            logger
1283
                    .error(
1284
                            Messages
1285
                            .getString("Launcher.No_se_pudo_instanciar_la_clase_mdi_manager"),
1286
                            e);
1287
            throw new MDIManagerLoadException(e);
1288
        } catch (IllegalAccessException e) {
1289
            logger
1290
                    .error(
1291
                            Messages
1292
                            .getString("Launcher.No_se_pudo_acceder_a_la_clase_mdi_manager"),
1293
                            e);
1294
            throw new MDIManagerLoadException(e);
1295
        }
1296

    
1297
    }
1298

    
1299
    /**
1300
     * DOCUMENT ME!
1301
     *
1302
     * @throws MDIManagerLoadException
1303
     */
1304
    private void skinPlugin(String defaultSkin) throws MDIManagerLoadException {
1305
        XMLEntity entity = null;
1306
        try {
1307
            entity = persistenceFromXML();
1308
        } catch (ConfigurationException e1) {
1309
            // TODO Auto-generated catch block
1310
            e1.printStackTrace();
1311
        }
1312
        Iterator<String> i = pluginsConfig.keySet().iterator();
1313

    
1314
        SkinExtension skinExtension = null;
1315
        PluginClassLoader pluginClassLoader = null;
1316
        List<SkinExtension> skinExtensions = new ArrayList<SkinExtension>();
1317
        while (i.hasNext()) {
1318
            String name = i.next();
1319
            PluginConfig pc = pluginsConfig.get(name);
1320
            PluginServices ps = pluginsServices.get(name);
1321

    
1322
            if (pc.getExtensions().getSkinExtension() != null) {
1323
                                // if (MDIManagerFactory.getSkinExtension() != null) {
1324
                // logger.warn(Messages.getString(
1325
                // "Launcher.Dos_skin_extension"));
1326
                // }
1327

    
1328
                SkinExtension[] se = pc.getExtensions().getSkinExtension();
1329
                for (int numExten = 0; numExten < se.length; numExten++) {
1330
                    skinExtensions.add(se[numExten]);
1331
                }
1332
                for (int j = 0; j < se.length; j++) {
1333
                    String configuredSkin = this.configureSkin(entity,
1334
                            defaultSkin);
1335
                    if ((configuredSkin != null)
1336
                            && configuredSkin.equals(se[j].getClassName())) {
1337
                        skinExtension = se[j];
1338
                        pluginClassLoader = ps.getClassLoader();
1339
                    }
1340
                }
1341
            }
1342
        }
1343

    
1344
        if ((skinExtension != null) && (pluginClassLoader != null)) {
1345
            // configured skin was found
1346
            fixSkin(skinExtension, pluginClassLoader);
1347
        } else {
1348
            if (skinExtensions.contains("com.iver.core.mdiManager.NewSkin")) {
1349
                // try first NewSkin (from CorePlugin)
1350
                skinPlugin("com.iver.core.mdiManager.NewSkin");
1351
            } else if (skinExtensions.size() > 0) {
1352
                // try to load the first skin found
1353
                SkinExtension se = (SkinExtension) skinExtensions.get(0);
1354
                skinPlugin((String) se.getClassName());
1355
            } else {
1356
                throw new MDIManagerLoadException("No Skin-Extension installed");
1357
            }
1358
        }
1359

    
1360
    }
1361

    
1362
    private static void frameIcon(Theme theme) {
1363
        Iterator<String> i = pluginsConfig.keySet().iterator();
1364

    
1365
        while (i.hasNext()) {
1366
            String pName = i.next();
1367
            PluginConfig pc = pluginsConfig.get(pName);
1368
            if (pc.getIcon() != null) {
1369
                if (theme.getIcon() != null) {
1370
                    frame.setIconImage(theme.getIcon().getImage());
1371
                } else {
1372

    
1373
                    ImageIcon icon = PluginServices.getIconTheme().get(
1374
                            pc.getIcon().getSrc());
1375
                    frame.setIconImage(icon.getImage());
1376

    
1377
                }
1378
                if (theme.getName() != null) {
1379
                    frame.setTitlePrefix(theme.getName());
1380
                } else {
1381
                    frame.setTitlePrefix(pc.getIcon().getText());
1382
                }
1383
                if (theme.getBackgroundImage() != null) {
1384

    
1385
                    PluginServices.getMDIManager().setBackgroundImage(
1386
                            theme.getBackgroundImage(), theme.getTypeDesktop());
1387
                }
1388
            }
1389
        }
1390
    }
1391

    
1392
    private void initializeExtensions() {
1393

    
1394
        List<ClassLoader> classLoaders = new ArrayList<ClassLoader>(
1395
                pluginsOrdered.size());
1396
        classLoaders.add(getClass().getClassLoader());
1397
        Iterator<String> iter = pluginsOrdered.iterator();
1398

    
1399
                // logger.debug("Initializing plugins libraries: ");
1400
        // while (iter.hasNext()) {
1401
        // String pName = (String) iter.next();
1402
        // PluginServices ps = (PluginServices) pluginsServices.get(pName);
1403
        // classLoaders.add(ps.getClassLoader());
1404
        // }
1405
        //
1406
        // // Create the libraries initializer and
1407
        // // initialize the plugin libraries
1408
        // new DefaultLibrariesInitializer(
1409
        // classLoaders.toArray(new ClassLoader[classLoaders.size()]))
1410
        // .fullInitialize();
1411
        //
1412
        // // Remove them all, we don't need them anymore
1413
        // classLoaders.clear();
1414
        // classLoaders = null;
1415
        logger.info("Initializing plugins: ");
1416
        // iter = pluginsOrdered.iterator();
1417
        while (iter.hasNext()) {
1418
            String pName = (String) iter.next();
1419
            logger.info("Initializing plugin " + pName);
1420
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1421
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1422

    
1423
            Extension[] exts = pc.getExtensions().getExtension();
1424

    
1425
            TreeSet<Extension> orderedExtensions = new TreeSet<Extension>(
1426
                    new ExtensionComparator());
1427

    
1428
            for (int j = 0; j < exts.length; j++) {
1429
                if (!exts[j].getActive()) {
1430
                    continue;
1431
                }
1432

    
1433
                if (orderedExtensions.contains(exts[j])) {
1434
                    logger.warn("Two extensions with the same priority ("
1435
                            + exts[j].getClassName() + ")");
1436
                }
1437

    
1438
                orderedExtensions.add(exts[j]);
1439
            }
1440

    
1441
            Iterator<Extension> e = orderedExtensions.iterator();
1442

    
1443
            logger.info("Initializing extensions of plugin " + pName + ": ");
1444
            while (e.hasNext()) {
1445
                Extension extension = e.next();
1446
                org.gvsig.andami.plugins.IExtension extensionInstance;
1447

    
1448
                try {
1449
                    logger.info("Initializing " + extension.getClassName()
1450
                            + "...");
1451
                    message(extension.getClassName() + "...");
1452
                    Class<? extends IExtension> extensionClass = (Class<? extends IExtension>) ps
1453
                            .getClassLoader().loadClass(
1454
                                    extension.getClassName());
1455
                    extensionInstance = extensionClass.newInstance();
1456
                    if (extensionInstance instanceof org.gvsig.andami.plugins.Extension) {
1457
                        ((org.gvsig.andami.plugins.Extension) extensionInstance).setPlugin(ps);
1458
                    } else {
1459
                        logger.warn("The extension " + extensionClass.getName() + " don't extends of Extension.");
1460
                    }
1461

    
1462
                                        // CON DECORATOR
1463
                    // ANTES: classesExtensions.put(extensionClass,
1464
                    // extensionInstance);
1465
                    // AHORA: CREAMOS UNA ExtensionDecorator y asignamos esta
1466
                    // instancia para
1467
                    // poder ampliar con nuevas propiedades (AlwaysVisible, por
1468
                    // ejemplo)
1469
                    // Para crear la nueva clase ExtensionDecorator, le pasamos
1470
                    // como par?metro
1471
                    // la extensi?n original que acabamos de crear
1472
                    // 0-> Inactivo, controla la extension
1473
                    // 1-> Siempre visible
1474
                    // 2-> Invisible
1475
                    ExtensionDecorator newExtensionDecorator = new ExtensionDecorator(
1476
                            extensionInstance, ExtensionDecorator.INACTIVE);
1477
                    classesExtensions
1478
                            .put(extensionClass, newExtensionDecorator);
1479

    
1480
                    extensionInstance.initialize();
1481
                    extensions.add(extensionInstance);
1482

    
1483
                } catch (NoClassDefFoundError e1) {
1484
                    this.addError("Can't find class extension ("
1485
                            + extension.getClassName() + ")", e1);
1486
                } catch (Throwable e1) {
1487
                    this.addError("Can't initialize extension '"
1488
                            + extension.getClassName() + "'.", e1);
1489
                }
1490
            }
1491
        }
1492
    }
1493

    
1494
    private void postInitializeExtensions() {
1495
        logger.info("PostInitializing extensions: ");
1496

    
1497
        for (int i = 0; i < extensions.size(); i++) {
1498
            org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
1499
                    .get(i);
1500
            String name = extensionInstance.getClass().getName();
1501
            logger.info("PostInitializing " + name + "...");
1502
            message(name + "...");
1503
            try {
1504
                extensionInstance.postInitialize();
1505
            } catch (Throwable ex) {
1506
                this.addError("postInitialize of extension '"
1507
                        + extensionInstance.getClass().getName() + "' failed",
1508
                        ex);
1509
            }
1510
        }
1511
    }
1512

    
1513
    private void registerActionOfExtensions(ActionInfoManager actionManager,
1514
            Enumeration<SkinExtensionType> extensiones, ClassLoader loader) {
1515
        ActionInfo actionInfo;
1516
        while (extensiones.hasMoreElements()) {
1517
            SkinExtensionType extension = extensiones.nextElement();
1518
            Class<? extends IExtension> classExtension;
1519
            try {
1520
                classExtension = (Class<? extends IExtension>) loader
1521
                        .loadClass(extension.getClassName());
1522

    
1523
                Enumeration<Action> actions = extension.enumerateAction();
1524
                while (actions.hasMoreElements()) {
1525
                    Action action = actions.nextElement();
1526
                    if (action.getName() == null) {
1527
                        logger.info("invalid action name (null) in " + extension.getClassName() + " of " + loader.toString());
1528
                    } else {
1529
                        actionInfo = actionManager.createAction(
1530
                                classExtension, action.getName(),
1531
                                action.getLabel(), action.getActionCommand(),
1532
                                action.getIcon(), action.getAccelerator(), action.getPosition(),
1533
                                action.getTooltip());
1534
                        actionManager.registerAction(actionInfo);
1535
                        if (action.getPosition() < 100000000) {
1536
                            logger.info("Invalid position in action (" + actionInfo.toString() + ").");
1537
                            action.setPosition(action.getPosition() + 1000000000);
1538
                        }
1539
                    }
1540
                }
1541

    
1542
                Enumeration<Menu> menus = extension.enumerateMenu();
1543
                while (menus.hasMoreElements()) {
1544
                    Menu menu = menus.nextElement();
1545
                    if (!menu.getIs_separator()) {
1546
                        actionInfo = actionManager.createAction(
1547
                                classExtension, menu.getName(), menu.getText(),
1548
                                menu.getActionCommand(), menu.getIcon(),
1549
                                menu.getKey(), menu.getPosition(),
1550
                                menu.getTooltip());
1551
                        actionInfo = actionManager.registerAction(actionInfo);
1552
                        if (actionInfo != null) {
1553
                            menu.setActionCommand(actionInfo.getCommand());
1554
                            menu.setTooltip(actionInfo.getTooltip());
1555
                            menu.setIcon(actionInfo.getIconName());
1556
                            menu.setPosition(actionInfo.getPosition());
1557
                            menu.setKey(actionInfo.getAccelerator());
1558
                            menu.setName(actionInfo.getName());
1559
                        }
1560
                    }
1561
                    if (menu.getPosition() < 100000000) {
1562
                        logger.info("Invalid position in menu (" + menu.getText() + ").");
1563
                        menu.setPosition(menu.getPosition() + 1000000000);
1564
                    }
1565

    
1566
                }
1567
                Enumeration<ToolBar> toolBars = extension.enumerateToolBar();
1568
                while (toolBars.hasMoreElements()) {
1569
                    ToolBar toolBar = toolBars.nextElement();
1570

    
1571
                    Enumeration<ActionTool> actionTools = toolBar
1572
                            .enumerateActionTool();
1573
                    while (actionTools.hasMoreElements()) {
1574
                        ActionTool actionTool = actionTools.nextElement();
1575
                        actionInfo = actionManager.createAction(
1576
                                classExtension, actionTool.getName(),
1577
                                actionTool.getText(),
1578
                                actionTool.getActionCommand(),
1579
                                actionTool.getIcon(),
1580
                                null,
1581
                                actionTool.getPosition(),
1582
                                actionTool.getTooltip());
1583
                        actionInfo = actionManager.registerAction(actionInfo);
1584
                        if (actionInfo != null) {
1585
                            actionTool.setActionCommand(actionInfo.getCommand());
1586
                            actionTool.setTooltip(actionInfo.getTooltip());
1587
                            actionTool.setIcon(actionInfo.getIconName());
1588
                            actionTool.setPosition(actionInfo.getPosition());
1589
                            actionTool.setName(actionInfo.getName());
1590
                        }
1591
                    }
1592

    
1593
                    Enumeration<SelectableTool> selectableTool = toolBar
1594
                            .enumerateSelectableTool();
1595
                    while (selectableTool.hasMoreElements()) {
1596
                        SelectableTool actionTool = selectableTool
1597
                                .nextElement();
1598
                        actionInfo = actionManager.createAction(
1599
                                classExtension, actionTool.getName(),
1600
                                actionTool.getText(),
1601
                                actionTool.getActionCommand(),
1602
                                actionTool.getIcon(),
1603
                                null,
1604
                                actionTool.getPosition(),
1605
                                actionTool.getTooltip());
1606
                        actionInfo = actionManager.registerAction(actionInfo);
1607
                        if (actionInfo != null) {
1608
                            actionTool.setActionCommand(actionInfo.getCommand());
1609
                            actionTool.setTooltip(actionInfo.getTooltip());
1610
                            actionTool.setIcon(actionInfo.getIconName());
1611
                            actionTool.setPosition(actionInfo.getPosition());
1612
                            actionTool.setName(actionInfo.getName());
1613
                        }
1614
                    }
1615
                }
1616
            } catch (ClassNotFoundException e) {
1617
                logger.warn(
1618
                        "Can't register actions of extension '"
1619
                        + extension.getClassName() + "'", e);
1620
            }
1621
        }
1622
    }
1623

    
1624
    @SuppressWarnings("unchecked")
1625
    private void registerActions() {
1626
        logger.info("registerActions");
1627

    
1628
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1629
        Iterator<String> it = pluginsConfig.keySet().iterator();
1630

    
1631
        while (it.hasNext()) {
1632
            String pluginName = it.next();
1633
            PluginConfig pluginConfig = pluginsConfig.get(pluginName);
1634
            PluginServices pluginService = pluginsServices.get(pluginName);
1635
            PluginClassLoader loader = pluginService.getClassLoader();
1636

    
1637
            logger.info("registerActions of plugin '" + pluginName + "'.");
1638

    
1639
            Extensions extensionConfig = pluginConfig.getExtensions();
1640

    
1641
            Enumeration<SkinExtensionType> extensiones = extensionConfig.enumerateExtension();
1642
            registerActionOfExtensions(actionManager, extensiones, loader);
1643

    
1644
            Enumeration<SkinExtensionType> skinSxtensiones = extensionConfig.enumerateSkinExtension();
1645
            registerActionOfExtensions(actionManager, skinSxtensiones, loader);
1646

    
1647
            PopupMenus pluginPopupMenus = pluginConfig.getPopupMenus();
1648
            if (pluginPopupMenus != null) {
1649
                PopupMenu[] menus1 = pluginPopupMenus.getPopupMenu();
1650
                for (int j = 0; j < menus1.length; j++) {
1651
                    PopupMenu popupMenu = menus1[j];
1652
                    Enumeration<Menu> menus2 = popupMenu.enumerateMenu();
1653
                    while (menus2.hasMoreElements()) {
1654
                        Menu menu = menus2.nextElement();
1655
                        if (!menu.getIs_separator()) {
1656
                            if (menu.getName() == null) {
1657
                                logger.info("Null name for popmenu '" + menu.getText() + "' in plugin " + pluginService.getPluginName());
1658
                            } else {
1659
                                ActionInfo actionInfo = actionManager.getAction(menu.getName());
1660
                                if (actionInfo != null) {
1661
                                    menu.setActionCommand(actionInfo.getCommand());
1662
                                    menu.setTooltip(actionInfo.getTooltip());
1663
                                    menu.setIcon(actionInfo.getIconName());
1664
                                    menu.setPosition(actionInfo.getPosition());
1665
                                    menu.setText(actionInfo.getLabel());
1666
                                    menu.setKey(actionInfo.getAccelerator());
1667
                                }
1668
                            }
1669
                        }
1670
                    }
1671
                }
1672
            }
1673

    
1674
        }
1675
    }
1676

    
1677
    private TreeSet<SortableMenu> getOrderedMenus() {
1678

    
1679
        TreeSet<SortableMenu> orderedMenus = new TreeSet<SortableMenu>(
1680
                new MenuComparator());
1681

    
1682
        Iterator<String> i = pluginsConfig.keySet().iterator();
1683

    
1684
        while (i.hasNext()) {
1685
            String pName = i.next();
1686
            try {
1687
                PluginServices ps = pluginsServices.get(pName);
1688
                PluginConfig pc = pluginsConfig.get(pName);
1689

    
1690
                Extension[] exts = pc.getExtensions().getExtension();
1691

    
1692
                for (int j = 0; j < exts.length; j++) {
1693
                    if (!exts[j].getActive()) {
1694
                        continue;
1695
                    }
1696

    
1697
                    Menu[] menus = exts[j].getMenu();
1698

    
1699
                    for (int k = 0; k < menus.length; k++) {
1700
                        SortableMenu sm = new SortableMenu(ps.getClassLoader(),
1701
                                exts[j], menus[k]);
1702

    
1703
                        if (orderedMenus.contains(sm)) {
1704
                            this
1705
                                    .addError(Messages
1706
                                            .getString("Launcher.Two_menus_with_the_same_position")
1707
                                            + " - "
1708
                                            + menus[k].getText()
1709
                                            + " - " + exts[j].getClassName());
1710
                        }
1711

    
1712
                        orderedMenus.add(sm);
1713
                    }
1714
                }
1715

    
1716
                // Se instalan las extensiones de MDI
1717
                SkinExtension[] skinExts = pc.getExtensions()
1718
                        .getSkinExtension();
1719
                for (int j = 0; j < skinExts.length; j++) {
1720

    
1721
                    if (skinExts[j] != null) {
1722
                        Menu[] menu = skinExts[j].getMenu();
1723

    
1724
                        for (int k = 0; k < menu.length; k++) {
1725
                            SortableMenu sm = new SortableMenu(ps
1726
                                    .getClassLoader(), skinExts[j], menu[k]);
1727

    
1728
                            if (orderedMenus.contains(sm)) {
1729
                                this
1730
                                        .addError(Messages
1731
                                                .getString("Launcher.Two_menus_with_the_same_position")
1732
                                                + skinExts[j].getClassName());
1733
                            }
1734

    
1735
                            orderedMenus.add(sm);
1736
                        }
1737
                    }
1738
                }
1739

    
1740
            } catch (Throwable e) {
1741
                addError("Error initializing menus of plugin '" + pName + "'",
1742
                        e);
1743
            }
1744

    
1745
        }
1746

    
1747
        return orderedMenus;
1748
    }
1749

    
1750
    private void installPluginsMenus() {
1751
        logger.info("installPluginsMenus");
1752

    
1753
        TreeSet<SortableMenu> orderedMenus = getOrderedMenus();
1754

    
1755
        // Se itera por los menus ordenados
1756
        Iterator<SortableMenu> e = orderedMenus.iterator();
1757

    
1758
        // Se ordenan los menues
1759
        while (e.hasNext()) {
1760
            try {
1761
                SortableMenu sm = e.next();
1762
                logger.debug(sm.menu.getPosition() + ":" + sm.menu.getText() + ":" + sm.loader.getPluginName() + ":" + sm.extension.getClassName());
1763
                frame.addMenu(sm.loader, sm.extension, sm.menu);
1764
            } catch (Throwable ex) {
1765
                this.addError(
1766
                        Messages.getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1767
                        ex
1768
                );
1769
            }
1770
        }
1771
    }
1772

    
1773
    public class PluginMenuItem {
1774

    
1775
        private Menu menu;
1776
        private PluginClassLoader loader;
1777
        private SkinExtensionType extension;
1778

    
1779
        PluginMenuItem(PluginClassLoader loader,
1780
                SkinExtensionType extension, Menu menu) {
1781
            this.menu = menu;
1782
            this.loader = loader;
1783
            this.extension = extension;
1784
        }
1785

    
1786
        public PluginServices getPlugin() {
1787
            String pluginName = loader.getPluginName();
1788
            return PluginServices.getPluginServices(pluginName);
1789
        }
1790

    
1791
        public String getExtensionName() {
1792
            return this.extension.getClassName();
1793
        }
1794

    
1795
        public IExtension getExtension() {
1796
            Class<?> extensionClass;
1797
            try {
1798
                extensionClass = loader.loadClass(this.extension.getClassName());
1799
            } catch (ClassNotFoundException e) {
1800
                return null;
1801
            }
1802
            return PluginServices.getExtension(extensionClass);
1803
        }
1804

    
1805
        public String getText() {
1806
            return this.menu.getText();
1807
        }
1808

    
1809
        public long getPosition() {
1810
            return this.menu.getPosition();
1811
        }
1812

    
1813
        public String getName() {
1814
            return this.menu.getName();
1815
        }
1816

    
1817
        public boolean isParent() {
1818
            return menu.getIs_separator();
1819
        }
1820

    
1821
        public String getPluginName() {
1822
            return this.loader.getPluginName();
1823
        }
1824

    
1825
        public ActionInfo getAction() {
1826
            ActionInfoManager manager = PluginsLocator.getActionInfoManager();
1827
            return manager.getAction(this.menu.getName());
1828
        }
1829
    }
1830

    
1831
    public List<PluginMenuItem> getPluginMenuItems() {
1832
        List<PluginMenuItem> menuItems = new ArrayList<Launcher.PluginMenuItem>();
1833

    
1834
        TreeSet<SortableMenu> orderedMenus = getOrderedMenus();
1835
        Iterator<SortableMenu> e = orderedMenus.iterator();
1836
        while (e.hasNext()) {
1837
            SortableMenu sm = e.next();
1838
            PluginMenuItem item = new PluginMenuItem(sm.loader, sm.extension, sm.menu);
1839
            menuItems.add(item);
1840
        }
1841
        return menuItems;
1842
    }
1843

    
1844
    /**
1845
     * Installs the menus, toolbars, actiontools, selectable toolbars and
1846
     * combos. The order in which they are shown is determined here.
1847
     */
1848
    private void installPluginsControls() {
1849
        logger.info("installPluginsControls (toolbars)");
1850

    
1851
        Iterator<String> i = pluginsConfig.keySet().iterator();
1852

    
1853
        Map<Extension, PluginServices> extensionPluginServices = new HashMap<Extension, PluginServices>();
1854
        Map<Extension, PluginConfig> extensionPluginConfig = new HashMap<Extension, PluginConfig>();
1855
        Set<Extension> orderedExtensions = new TreeSet<Extension>(
1856
                new ExtensionComparator());
1857

    
1858
                // First of all, sort the extensions.
1859
        // We need to iterate on the plugins, and iterate on each plugin's
1860
        // extensions
1861
        // (each plugin may contain one or more extensions)
1862
        while (i.hasNext()) { // iterate on the plugins
1863
            String pName = i.next();
1864
            try {
1865
                PluginConfig pc = pluginsConfig.get(pName);
1866
                PluginServices ps = pluginsServices.get(pName);
1867

    
1868
                Extension[] exts = pc.getExtensions().getExtension();
1869

    
1870
                for (int j = 0; j < exts.length; j++) { // iterate on the
1871
                    // extensions
1872
                    String cname = "unknow";
1873
                    try {
1874
                        cname = exts[j].getClassName();
1875
                        if (exts[j].getActive()
1876
                                && !cname.equals(LibraryExtension.class
1877
                                        .getName())) {
1878
                            if (orderedExtensions.contains(exts[j])) {
1879
                                this
1880
                                        .addError(Messages
1881
                                                .getString("Launcher.Two_extensions_with_the_same_priority")
1882
                                                + cname);
1883
                            }
1884

    
1885
                            orderedExtensions.add(exts[j]);
1886
                            extensionPluginServices.put(exts[j], ps);
1887
                            extensionPluginConfig.put(exts[j], pc);
1888
                        }
1889
                    } catch (Throwable e) {
1890
                        addError("Error initializing controls of plugin '"
1891
                                + pName + "' extension '" + cname + "'", e);
1892
                    }
1893
                }
1894
            } catch (Throwable e) {
1895
                addError("Error initializing controls of plugin '" + pName
1896
                        + "'", e);
1897
            }
1898
        }
1899

    
1900
        TreeSet<SortableTool> orderedTools = new TreeSet<SortableTool>(
1901
                new ToolComparator());
1902
        Iterator<Extension> e = orderedExtensions.iterator();
1903

    
1904
                // sort the toolbars and tools from 'normal' extensions (actiontools,
1905
        // selectabletools)
1906
        // and load the combo-scales and combo-buttons for the status bar
1907
        while (e.hasNext()) {
1908
            Extension ext = e.next();
1909
            String extName = "unknow";
1910
            try {
1911
                extName = ext.getClassName();
1912
                ToolBar[] toolbars = ext.getToolBar();
1913

    
1914
                // get tools from toolbars
1915
                for (int k = 0; k < toolbars.length; k++) {
1916
                    ActionTool[] tools = toolbars[k].getActionTool();
1917

    
1918
                    for (int t = 0; t < tools.length; t++) {
1919
                        SortableTool sm = new SortableTool(
1920
                                (extensionPluginServices.get(ext))
1921
                                .getClassLoader(), ext, toolbars[k],
1922
                                tools[t]);
1923
                        orderedTools.add(sm);
1924
                    }
1925

    
1926
                    SelectableTool[] sTools = toolbars[k].getSelectableTool();
1927

    
1928
                    for (int t = 0; t < sTools.length; t++) {
1929
                        SortableTool sm = new SortableTool(
1930
                                (extensionPluginServices.get(ext))
1931
                                .getClassLoader(), ext, toolbars[k],
1932
                                sTools[t]);
1933
                        orderedTools.add(sm);
1934
                    }
1935
                }
1936

    
1937
                // get controls for statusBar
1938
                PluginServices ps = extensionPluginServices.get(ext);
1939
                PluginClassLoader loader = ps.getClassLoader();
1940

    
1941
                // ArrayList componentList = new ArrayList();
1942
                ComboScale[] comboScaleArray = ext.getComboScale();
1943
                for (int k = 0; k < comboScaleArray.length; k++) {
1944
                    org.gvsig.gui.beans.controls.comboscale.ComboScale combo = new org.gvsig.gui.beans.controls.comboscale.ComboScale();
1945
                    String label = comboScaleArray[k].getLabel();
1946
                    if (label != null) {
1947
                        combo.setLabel(label);
1948
                    }
1949
                    String name = comboScaleArray[k].getName();
1950
                    if (name != null) {
1951
                        combo.setName(name);
1952
                    }
1953
                    String[] elementsString = ((String) comboScaleArray[k]
1954
                            .getElements()).split(";");
1955
                    long[] elements = new long[elementsString.length];
1956
                    for (int currentElem = 0; currentElem < elementsString.length; currentElem++) {
1957
                        try {
1958
                            elements[currentElem] = Long
1959
                                    .parseLong(elementsString[currentElem]);
1960
                        } catch (NumberFormatException nfex1) {
1961
                            this
1962
                                    .addError(ext.getClassName()
1963
                                            + " -- "
1964
                                            + Messages
1965
                                            .getString("error_parsing_comboscale_elements"));
1966
                            elements[currentElem] = 0;
1967
                        }
1968
                    }
1969
                    combo.setItems(elements);
1970
                    try {
1971
                        long value = Long.parseLong((String) comboScaleArray[k]
1972
                                .getValue());
1973
                        combo.setScale(value);
1974
                    } catch (NumberFormatException nfex2) {
1975
                        this
1976
                                .addError(ext.getClassName()
1977
                                        + " -- "
1978
                                        + Messages
1979
                                        .getString("error_parsing_comboscale_value"));
1980
                    }
1981
                    try {
1982
                        frame.addStatusBarControl(loader.loadClass(ext
1983
                                .getClassName()), combo);
1984
                    } catch (ClassNotFoundException e1) {
1985
                        this
1986
                                .addError(
1987
                                        Messages
1988
                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
1989
                                        e1);
1990
                    }
1991
                }
1992

    
1993
                ComboButton[] comboButtonArray = ext.getComboButton();
1994
                for (int k = 0; k < comboButtonArray.length; k++) {
1995
                    ComboButtonElement[] elementList = comboButtonArray[k]
1996
                            .getComboButtonElement();
1997
                    org.gvsig.gui.beans.controls.combobutton.ComboButton combo = new org.gvsig.gui.beans.controls.combobutton.ComboButton();
1998
                    String name = comboButtonArray[k].getName();
1999
                    if (name != null) {
2000
                        combo.setName(name);
2001
                    }
2002
                    for (int currentElement = 0; currentElement < elementList.length; currentElement++) {
2003
                        ComboButtonElement element = elementList[currentElement];
2004
                        ImageIcon icon;
2005
                        URL iconLocation = loader
2006
                                .getResource(element.getIcon());
2007
                        if (iconLocation == null) {
2008
                            this.addError(Messages.getString("Icon_not_found_")
2009
                                    + element.getIcon());
2010
                        } else {
2011
                            icon = new ImageIcon(iconLocation);
2012
                            JButton button = new JButton(icon);
2013
                            combo.addButton(button);
2014
                            button.setActionCommand(element.getActionCommand());
2015
                        }
2016
                    }
2017
                    try {
2018
                        frame.addStatusBarControl(loader.loadClass(ext
2019
                                .getClassName()), combo);
2020
                    } catch (ClassNotFoundException e1) {
2021
                        this
2022
                                .addError(
2023
                                        Messages
2024
                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
2025
                                        e1);
2026
                    }
2027
                }
2028
            } catch (Throwable e2) {
2029
                addError(
2030
                        "Error initializing tools and status bars of extension '"
2031
                        + extName + "'", e2);
2032
            }
2033
        }
2034

    
2035
                // Add the tools from MDI extensions to the ordered tool-list, so that
2036
        // we get a sorted list containing all the tools
2037
        i = pluginsConfig.keySet().iterator();
2038
        while (i.hasNext()) {
2039
            String pName = (String) i.next();
2040
            try {
2041
                PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
2042
                PluginServices ps = (PluginServices) pluginsServices.get(pName);
2043

    
2044
                SkinExtension[] skinExts = pc.getExtensions()
2045
                        .getSkinExtension();
2046
                for (int j = 0; j < skinExts.length; j++) {
2047

    
2048
                    if (skinExts[j] != null) {
2049
                        ToolBar[] toolbars = skinExts[j].getToolBar();
2050

    
2051
                        for (int k = 0; k < toolbars.length; k++) {
2052
                            ActionTool[] tools = toolbars[k].getActionTool();
2053

    
2054
                            for (int t = 0; t < tools.length; t++) {
2055
                                SortableTool stb = new SortableTool(ps
2056
                                        .getClassLoader(), skinExts[j],
2057
                                        toolbars[k], tools[t]);
2058
                                orderedTools.add(stb);
2059
                            }
2060

    
2061
                            SelectableTool[] sTools = toolbars[k]
2062
                                    .getSelectableTool();
2063

    
2064
                            for (int t = 0; t < sTools.length; t++) {
2065
                                SortableTool stb = new SortableTool(ps
2066
                                        .getClassLoader(), skinExts[j],
2067
                                        toolbars[k], sTools[t]);
2068
                                orderedTools.add(stb);
2069
                            }
2070
                        }
2071
                    }
2072
                }
2073
                // Install popup menus
2074
                PopupMenus pus = pc.getPopupMenus();
2075
                if (pus != null) {
2076
                    PopupMenu[] menus = pus.getPopupMenu();
2077
                    for (int j = 0; j < menus.length; j++) {
2078
                        String menuName = "(unknow)";
2079
                        try {
2080
                            menuName = menus[j].getName();
2081
                            frame.addPopupMenu(ps.getClassLoader(), menus[j]);
2082
                        } catch (Throwable ex) {
2083
                            addError("Error adding popup menu' " + menuName + "' in plugin '" + pName + "'.");
2084
                        }
2085
                    }
2086
                }
2087
            } catch (Throwable e3) {
2088
                addError("Error initializing skins of the plugin '" + pName
2089
                        + "'", e3);
2090
            }
2091
        }
2092

    
2093
                // loop on the ordered extension list, to add them to the interface in
2094
        // an ordered way
2095
        Iterator<SortableTool> t = orderedTools.iterator();
2096
        while (t.hasNext()) {
2097
            SortableTool stb = t.next();
2098
            try {
2099
                if (stb.actiontool != null) {
2100
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
2101
                            stb.actiontool);
2102
                } else {
2103
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
2104
                            stb.selectabletool);
2105
                }
2106
            } catch (ClassNotFoundException ex) {
2107
                this
2108
                        .addError(
2109
                                Messages
2110
                                .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
2111
                                ex);
2112
            } catch (Throwable e2) {
2113
                addError("Error adding tools to the interface of extension '"
2114
                        + stb.extension.getClassName() + "'", e2);
2115
            }
2116
        }
2117
    }
2118

    
2119
    /**
2120
     * Adds new plugins to the the andami-config file.
2121
     */
2122
    private void updateAndamiConfig() {
2123
        Set<String> olds = new HashSet<String>();
2124

    
2125
        Plugin[] plugins = andamiConfig.getPlugin();
2126

    
2127
        for (int i = 0; i < plugins.length; i++) {
2128
            olds.add(plugins[i].getName());
2129
        }
2130

    
2131
        Iterator<PluginServices> i = pluginsServices.values().iterator();
2132

    
2133
        while (i.hasNext()) {
2134
            PluginServices ps = i.next();
2135

    
2136
            if (!olds.contains(ps.getPluginName())) {
2137
                Plugin p = new Plugin();
2138
                p.setName(ps.getPluginName());
2139
                p.setUpdate(false);
2140

    
2141
                andamiConfig.addPlugin(p);
2142
            }
2143
        }
2144
    }
2145

    
2146
    private URL[] getPluginClasspathURLs(PluginConfig pluginConfig) {
2147
        URL[] urls = null;
2148

    
2149
        String libfolderPath = pluginConfig.getLibraries().getLibraryDir();
2150
        File libFolderFile = new File(pluginConfig.getPluginFolder(), libfolderPath);
2151

    
2152
        File[] files = libFolderFile.listFiles(new FileFilter() {
2153

    
2154
            public boolean accept(File pathname) {
2155
                return (pathname.getName().toUpperCase().endsWith(".JAR")
2156
                        || pathname.getName().toUpperCase().endsWith(".ZIP"));
2157
            }
2158
        });
2159
        if (files == null) {
2160
            urls = new URL[0];
2161
        } else {
2162
            urls = new URL[files.length];
2163
            for (int j = 0; j < files.length; j++) {
2164
                try {
2165
                    urls[j] = new URL("file:" + files[j]);
2166
                } catch (MalformedURLException e) {
2167
                    logger.warn("Can't add file '" + files[j] + "' to the classpath of plugin '" + pluginConfig.getPluginName() + "'.");
2168
                }
2169
            }
2170
        }
2171
        return urls;
2172
    }
2173

    
2174
    private static class OrderedPlugins extends ArrayList<String> {
2175
        
2176
        private List<String> problems = new ArrayList<String>();
2177
        private int retries = 0;
2178
        private PluginsConfig pluginsConfig = null;
2179
        private List<String> deprcatedPluginNames = null;
2180
        
2181
        OrderedPlugins(PluginsConfig pluginsConfig, List<String>deprcatedPluginNames) {
2182
            super();
2183
            this.pluginsConfig = pluginsConfig;
2184
            this.deprcatedPluginNames = deprcatedPluginNames;
2185
            List<String> pluginNames = new ArrayList<String>();
2186
            for (String pluginName : pluginsConfig.keySet()) {
2187
                pluginNames.add(pluginName);
2188
            }
2189
            Collections.sort(pluginNames);
2190
            for (String pluginName : pluginNames) {
2191
                this.add(pluginName);
2192
            }
2193
        }
2194
        
2195
        public List<String> getProblems() {
2196
            return this.problems;
2197
        }
2198
 
2199
        private void addProblem(String msg) {
2200
           this.problems.add(msg);
2201
        }
2202
    
2203
        public boolean add(String pluginName) {
2204
            return this.add(pluginName,new ArrayList<String>());
2205
        }
2206
        
2207
        private boolean add(String pluginName, List<String>processing) {
2208
            pluginName = this.pluginsConfig.getMainKey(pluginName);
2209
            if( this.contains(pluginName) ) {
2210
                return true;
2211
            }
2212
            if( processing.contains(pluginName) ) {
2213
                this.addProblem("Dependencias ciclicas procesando '"+pluginName+"'.");
2214
                return true;
2215
            }
2216
            PluginConfig pluginConfig = this.pluginsConfig.get(pluginName);
2217
            Depends[] dependencies = pluginConfig.getDepends();
2218
            if( dependencies.length==0 ) {
2219
               super.add(pluginName);
2220
               return true;
2221
            }
2222
            if( this.retries > 100 ) {
2223
               this.addProblem("Posible dependencias ciclicas procesando '"+pluginName+"'." );
2224
               return false;
2225
            }
2226
            processing.add(pluginName);
2227
            boolean dependenciesAvailables = true;
2228
            for (Depends dependency : dependencies) {
2229
                String dependencyName = dependency.getPluginName();
2230
                if (deprcatedPluginNames.contains(dependencyName)) {
2231
                    this.addProblem("Plugin '" + pluginName + "' use a deprecated plugin name '" + dependencyName + "' as dependency. Must use '" + pluginsConfig.getMainKey(dependencyName) + "'.");
2232
                }                
2233
                PluginConfig dependencyConfig = this.pluginsConfig.get(dependencyName);
2234
                if( dependencyConfig == null) {
2235
                  if( dependency.getOptional() ) {
2236
                    this.addProblem("Plugin '" + pluginName + "', declare an optional dependency '" + dependencyName + "' that not found.");
2237
                    continue;
2238
                  }
2239
                  dependenciesAvailables = false;
2240
                  this.addProblem("Plugin '"+pluginName+"' declara a dependency '"+dependencyName+"' that not found.");
2241
                  continue;
2242
                }
2243
                this.retries++;
2244
                if( ! (this.add(dependencyName, processing)) ) {
2245
                  dependenciesAvailables = false;
2246
                }
2247
                this.retries--;
2248
            }
2249
            if( dependenciesAvailables ) {
2250
                super.add(pluginName);
2251
            } else {
2252
              this.addProblem("Plugin '"+pluginName+"' no disponible, alguna dependencia no resuelta.");
2253
              return false;
2254
            }
2255
            return true;
2256
        }      
2257
    }
2258
            
2259
    private void loadPluginServices() {
2260
        OrderedPlugins orderedPlugins = new OrderedPlugins(pluginsConfig, getDeprecatedPluginNames());
2261
        
2262
        if( !orderedPlugins.getProblems().isEmpty() ) {
2263
            for (String problem : orderedPlugins.getProblems()) {
2264
                logger.warn(problem);
2265
            }
2266
        }
2267

    
2268
        for (String pluginName : orderedPlugins) {
2269
            PluginConfig config = pluginsConfig.get(pluginName);
2270

    
2271
            URL[] urls = getPluginClasspathURLs(config);
2272
            
2273
            List<PluginClassLoader> loaders = new ArrayList<PluginClassLoader>();
2274
            for (Depends dependency : config.getDepends()) {
2275
                String dependencyName = dependency.getPluginName();
2276
                PluginServices dependencyPluginService = pluginsServices.get(dependencyName);
2277
                if( dependencyPluginService == null ) {
2278
                    if( dependency.getOptional() ) {
2279
                        logger.info("Procesing plugin '"+pluginName+", optional dependency not found ("+dependencyName+").");
2280
                    } else {
2281
                        logger.warn("Procesing plugin '"+pluginName+", dependency not found ("+dependencyName+").");
2282
                    }
2283
                    continue;
2284
                }
2285
                loaders.add(dependencyPluginService.getClassLoader());
2286
            }
2287
            try {
2288
                PluginClassLoader loader = new PluginClassLoader(
2289
                        urls,
2290
                        config.getPluginFolder().getAbsolutePath(),
2291
                        Launcher.class.getClassLoader(),
2292
                        loaders
2293
                );
2294
                PluginServices ps = new PluginServices(
2295
                        loader,
2296
                        PluginsConfig.getAlternativeNames(config)
2297
                );
2298
                logger.info("Plugin '" + pluginName + "' created");
2299
                pluginsServices.put(ps.getPluginName(), ps);
2300
                pluginsOrdered.add(pluginName);
2301
            } catch (IOException ex) {
2302
                logger.warn("Can't create PluginServices for '" + pluginName + "'.", ex);
2303
            }
2304
        }
2305
        
2306
        // Se eliminan los plugins que no fueron instalados
2307
        List<String> pluginsToRemove = new ArrayList<String>();
2308
        for (String pluginName : pluginsConfig.keySet()) {
2309
            PluginServices pluginService = pluginsServices.get(pluginName);
2310
            if( pluginService == null ) {
2311
                pluginsToRemove.add(pluginName);
2312
            } 
2313
        }
2314
        for (String pluginName : pluginsToRemove) {
2315
            logger.warn("Removed plugin "+pluginName+".");
2316
            pluginsConfig.remove(pluginName);
2317
       }
2318
    }
2319
 
2320
    /*
2321
    private void dumpPluginsDependencyInformation() {
2322
        logger.info("Plugin dependency information");
2323
        Iterator<String> i = pluginsConfig.keySet().iterator();
2324
        while (i.hasNext()) {
2325
            String pluginName = i.next();
2326
            PluginConfig config = (PluginConfig) pluginsConfig.get(pluginName);
2327
            logger.info("  Plugin " + pluginName);
2328
            Depends[] dependencies = config.getDepends();
2329
            for (int j = 0; j < dependencies.length; j++) {
2330
                Depends dependency = dependencies[j];
2331
                String dependencyName = dependency.getPluginName();
2332
                logger.info("    Dependency " + dependencyName);
2333
            }
2334
        }
2335
    }
2336
    */
2337
    private void pluginsMessages() {
2338
        Iterator<String> iterator = pluginsOrdered.iterator();
2339
        PluginConfig config;
2340
        PluginServices ps;
2341

    
2342
        while (iterator.hasNext()) {
2343
            String pluginName = iterator.next();
2344
            config = pluginsConfig.get(pluginName);
2345
            ps = pluginsServices.get(pluginName);
2346

    
2347
            if ((config.getResourceBundle() != null)
2348
                    && !config.getResourceBundle().getName().equals("")) {
2349
                // add the locale files associated with the plugin
2350
                org.gvsig.i18n.Messages.addResourceFamily(config
2351
                        .getResourceBundle().getName(), ps.getClassLoader(),
2352
                        pluginName);
2353
                org.gvsig.i18n.Messages.addResourceFamily("i18n." + config
2354
                        .getResourceBundle().getName(), ps.getClassLoader(),
2355
                        pluginName);
2356
            }
2357
        }
2358
    }
2359

    
2360
    static public PluginServices getPluginServices(String name) {
2361
        return (PluginServices) pluginsServices.get(name);
2362
    }
2363

    
2364
    static String getPluginsDir() {
2365
        return andamiConfig.getPluginsDirectory();
2366
    }
2367

    
2368
    static File getPluginFolder(String pluginName) {
2369
        return pluginsConfig.get(pluginName).getPluginFolder();
2370
    }
2371

    
2372
    static void setPluginsDir(String s) {
2373
        andamiConfig.setPluginsDirectory(s);
2374
    }
2375

    
2376
    static MDIFrame getMDIFrame() {
2377
        return frame;
2378
    }
2379

    
2380
    private PluginsConfig loadPluginConfigs() {
2381
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
2382
        List<File> repositoriesFolders = installerManager.getLocalAddonRepositories("plugin");
2383
        for (File repositoryFolder : repositoriesFolders) {
2384
            logger.info("Loading plugins configuration from repository folder " + repositoryFolder.getAbsolutePath() + ".");
2385

    
2386
            if (!repositoryFolder.exists()) {
2387
                logger.warn("Plugins repository folder not found '" + repositoryFolder.getAbsolutePath() + "'.");
2388
                continue;
2389
            }
2390

    
2391
            File[] pluginsFolders = repositoryFolder.listFiles();
2392
            if (pluginsFolders.length == 0) {
2393
                logger.info("Plugins repository folder is empty '" + repositoryFolder.getAbsolutePath() + "'.");
2394
                continue;
2395
            }
2396

    
2397
            for (int i = 0; i < pluginsFolders.length; i++) {
2398
                File pluginFolder = pluginsFolders[i];
2399
                if (!pluginFolder.isDirectory()) {
2400
                    continue;
2401
                }
2402
                String pluginName = pluginFolder.getName();
2403
                File pluginConfigFile = new File(pluginFolder, "config.xml");
2404
                if (!pluginConfigFile.exists()) {
2405
                    logger.info("Plugin '" + pluginName + "' not has a config.xml file (" + pluginConfigFile.getAbsolutePath() + ".");
2406
                    continue;
2407
                }
2408
                try {
2409
                    FileInputStream is = new FileInputStream(pluginConfigFile);
2410
                    Reader xml = org.gvsig.utils.xml.XMLEncodingUtils.getReader(is);
2411
                    if (xml == null) {
2412
                        // the encoding was not correctly detected, use system default
2413
                        xml = new FileReader(pluginConfigFile);
2414
                    } else {
2415
                        // use a buffered reader to improve performance
2416
                        xml = new BufferedReader(xml);
2417
                    }
2418
                    PluginConfig pluginConfig = (PluginConfig) PluginConfig.unmarshal(xml);
2419
                    pluginConfig.setPluginName(pluginName);
2420
                    pluginConfig.setPluginFolder(pluginFolder);
2421
                    pluginsConfig.put(pluginName, pluginConfig);
2422

    
2423
                } catch (FileNotFoundException e) {
2424
                    logger.info("Can't read plugin config file from plugin '" + pluginName + "' ('" + pluginConfigFile.getAbsolutePath() + ").");
2425

    
2426
                } catch (MarshalException e) {
2427
                    logger.warn("Can't load plugin the config file from plugin '" + pluginName + "' is incorect. " + e.getMessage() + " ('" + pluginConfigFile.getAbsolutePath() + ").", e);
2428

    
2429
                } catch (ValidationException e) {
2430
                    logger.warn("Can't load plugin the config file from plugin '" + pluginName + "' is invalid. " + e.getMessage() + " ('" + pluginConfigFile.getAbsolutePath() + ").", e);
2431

    
2432
                }
2433
            }
2434
        }
2435
        return pluginsConfig;
2436
    }
2437

    
2438
    private static Locale getLocale(String language, String country,
2439
            String variant) {
2440
        if (variant != null) {
2441
            return new Locale(language, country, variant);
2442
        } else if (country != null) {
2443
            return new Locale(language, country);
2444
        } else if (language != null) {
2445
            return new Locale(language);
2446
        } else {
2447
            return new Locale("es");
2448
        }
2449
    }
2450

    
2451
    private static void andamiConfigToXML(String file) throws IOException,
2452
            MarshalException, ValidationException {
2453
                // write on a temporary file in order to not destroy current file if
2454
        // there is some problem while marshaling
2455
        File tmpFile = new File(file + "-"
2456
                + DateTime.getCurrentDate().getTime());
2457
        File xml = new File(file);
2458
        File parent = xml.getParentFile();
2459
        parent.mkdirs();
2460

    
2461
        BufferedOutputStream os = new BufferedOutputStream(
2462
                new FileOutputStream(tmpFile));
2463
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
2464
        andamiConfig.marshal(writer);
2465
        writer.close();
2466

    
2467
                // if marshaling process finished correctly, move the file to the
2468
        // correct one
2469
        xml.delete();
2470
        if (!tmpFile.renameTo(xml)) {
2471
            // if rename was not succesful, try copying it
2472
            FileChannel sourceChannel = new FileInputStream(tmpFile)
2473
                    .getChannel();
2474
            FileChannel destinationChannel = new FileOutputStream(xml)
2475
                    .getChannel();
2476
            sourceChannel.transferTo(0, sourceChannel.size(),
2477
                    destinationChannel);
2478
            sourceChannel.close();
2479
            destinationChannel.close();
2480
        }
2481
    }
2482

    
2483
    private static void andamiConfigFromXML(String file)
2484
            throws ConfigurationException {
2485
        File xml = new File(file);
2486

    
2487
        InputStreamReader reader = null;
2488
        try {
2489
            // Se lee la configuraci?n
2490
            reader = XMLEncodingUtils.getReader(xml);
2491
            andamiConfig = (AndamiConfig) AndamiConfig.unmarshal(reader);
2492
        } catch (FileNotFoundException e) {
2493
            // Si no existe se ponen los valores por defecto
2494
            andamiConfig = getDefaultAndamiConfig();
2495
        } catch (MarshalException e) {
2496
            // try to close the stream, maybe it remains open
2497
            if (reader != null) {
2498
                try {
2499
                    reader.close();
2500
                } catch (IOException e1) {
2501
                }
2502
            }
2503
                        // if there was a problem reading the file, backup it and create a
2504
            // new one with default values
2505
            String backupFile = file + "-"
2506
                    + DateTime.getCurrentDate().getTime();
2507
            NotificationManager
2508
                    .addError(
2509
                            Messages
2510
                            .getString("Error_reading_andami_config_New_file_created_A_backup_was_made_on_")
2511
                            + backupFile, new ConfigurationException(e));
2512
            xml.renameTo(new File(backupFile));
2513
            andamiConfig = getDefaultAndamiConfig();
2514
        } catch (ValidationException e) {
2515
            throw new ConfigurationException(e);
2516
        }
2517
    }
2518

    
2519
    private static AndamiConfig getDefaultAndamiConfig() {
2520
        AndamiConfig andamiConfig = new AndamiConfig();
2521

    
2522
        Andami andami = new Andami();
2523
        andami.setUpdate(true);
2524
        andamiConfig.setAndami(andami);
2525
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
2526
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
2527
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
2528

    
2529
        if (System.getProperty("javawebstart.version") != null) // Es java web
2530
        // start)
2531
        {
2532
            andamiConfig
2533
                    .setPluginsDirectory(new File(appHomeDir, "extensiones")
2534
                            .getAbsolutePath());
2535
        } else {
2536
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
2537
                    .getAbsolutePath());
2538
        }
2539

    
2540
        andamiConfig.setPlugin(new Plugin[0]);
2541
        return andamiConfig;
2542
    }
2543

    
2544
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
2545
        File xml = getPluginsPersistenceFile(true);
2546

    
2547
        if (xml.exists()) {
2548
            InputStreamReader reader = null;
2549

    
2550
            try {
2551
                reader = XMLEncodingUtils.getReader(xml);
2552
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2553
                return new XMLEntity(tag);
2554
            } catch (FileNotFoundException e) {
2555
                throw new ConfigurationException(e);
2556
            } catch (MarshalException e) {
2557

    
2558
                                // try to reopen with default encoding (for backward
2559
                // compatibility)
2560
                try {
2561
                    reader = new FileReader(xml);
2562
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2563
                    return new XMLEntity(tag);
2564

    
2565
                } catch (MarshalException ex) {
2566
                    // try to close the stream, maybe it remains open
2567
                    if (reader != null) {
2568
                        try {
2569
                            reader.close();
2570
                        } catch (IOException e1) {
2571
                        }
2572
                    }
2573
                    // backup the old file
2574
                    String backupFile = getPluginsPersistenceFile(true)
2575
                            .getPath()
2576
                            + "-" + DateTime.getCurrentDate().getTime();
2577
                    NotificationManager
2578
                            .addError(
2579
                                    Messages
2580
                                    .getString("Error_reading_plugin_persinstence_New_file_created_A_backup_was_made_on_")
2581
                                    + backupFile,
2582
                                    new ConfigurationException(e));
2583
                    xml.renameTo(new File(backupFile));
2584
                    // create a new, empty configuration
2585
                    return new XMLEntity();
2586
                } catch (FileNotFoundException ex) {
2587
                    return new XMLEntity();
2588
                } catch (ValidationException ex) {
2589
                    throw new ConfigurationException(e);
2590
                }
2591
            } catch (ValidationException e) {
2592
                throw new ConfigurationException(e);
2593
            }
2594
        } else {
2595
            return new XMLEntity();
2596
        }
2597
    }
2598

    
2599
    private static File getPluginsPersistenceFile(boolean read) {
2600
        if (read) {
2601
            File pluginsPersistenceFile = new File(getAppHomeDir(),
2602
                    "plugins-persistence-2_0.xml");
2603
            if (pluginsPersistenceFile.exists()) {
2604
                return pluginsPersistenceFile;
2605
            }
2606
            pluginsPersistenceFile = new File(getAppHomeDir(),
2607
                    "plugins-persistence.xml");
2608
            if (pluginsPersistenceFile.exists()) {
2609
                return pluginsPersistenceFile;
2610
            }
2611
        }
2612
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2613

    
2614
    }
2615

    
2616
    private static void persistenceToXML(XMLEntity entity)
2617
            throws ConfigurationException {
2618
                // write on a temporary file in order to not destroy current file if
2619
        // there is some problem while marshaling
2620
        File tmpFile = new File(getPluginsPersistenceFile(false).getPath()
2621
                + "-" + DateTime.getCurrentDate().getTime());
2622

    
2623
        File xml = getPluginsPersistenceFile(false);
2624
        OutputStreamWriter writer = null;
2625

    
2626
        try {
2627
            writer = new OutputStreamWriter(new FileOutputStream(tmpFile),
2628
                    CASTORENCODING);
2629
            entity.getXmlTag().marshal(writer);
2630
            writer.close();
2631

    
2632
                        // if marshaling process finished correctly, move the file to the
2633
            // correct one
2634
            xml.delete();
2635
            if (!tmpFile.renameTo(xml)) {
2636
                // if rename was not succesful, try copying it
2637
                FileChannel sourceChannel = new FileInputStream(tmpFile)
2638
                        .getChannel();
2639
                FileChannel destinationChannel = new FileOutputStream(xml)
2640
                        .getChannel();
2641
                sourceChannel.transferTo(0, sourceChannel.size(),
2642
                        destinationChannel);
2643
                sourceChannel.close();
2644
                destinationChannel.close();
2645

    
2646
            }
2647
        } catch (FileNotFoundException e) {
2648
            throw new ConfigurationException(e);
2649
        } catch (MarshalException e) {
2650
            // try to close the stream, maybe it remains open
2651
            if (writer != null) {
2652
                try {
2653
                    writer.close();
2654
                } catch (IOException e1) {
2655
                }
2656
            }
2657
        } catch (ValidationException e) {
2658
            throw new ConfigurationException(e);
2659
        } catch (IOException e) {
2660
            throw new ConfigurationException(e);
2661
        }
2662
    }
2663

    
2664
    static MDIFrame getFrame() {
2665
        return frame;
2666
    }
2667

    
2668
    /**
2669
     * Gracefully closes the application. It shows dialogs to save data, finish
2670
     * processes, etc, then it terminates the extensions, removes temporal files
2671
     * and finally exits.
2672
     */
2673
    public synchronized static void closeApplication() {
2674
        TerminationProcess terminationProcess = (new Launcher()).new TerminationProcess();
2675
        terminationProcess.run();
2676
    }
2677

    
2678
    static HashMap getClassesExtensions() {
2679
        return classesExtensions;
2680
    }
2681

    
2682
    private static Extensions[] getExtensions() {
2683
        List<Extensions> array = new ArrayList<Extensions>();
2684
        Iterator<PluginConfig> iter = pluginsConfig.values().iterator();
2685

    
2686
        while (iter.hasNext()) {
2687
            array.add(iter.next().getExtensions());
2688
        }
2689

    
2690
        return array.toArray(new Extensions[array.size()]);
2691
    }
2692

    
2693
    public static Iterator getExtensionIterator() {
2694
        return extensions.iterator();
2695
    }
2696

    
2697
    public static HashMap getPluginConfig() {
2698
        return pluginsConfig;
2699
    }
2700

    
2701
    public static Extension getExtension(String s) {
2702
        Extensions[] exts = getExtensions();
2703

    
2704
        for (int i = 0; i < exts.length; i++) {
2705
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2706
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2707
                    return exts[i].getExtension(j);
2708
                }
2709
            }
2710
        }
2711

    
2712
        return null;
2713
    }
2714

    
2715
    public static AndamiConfig getAndamiConfig() {
2716
        return andamiConfig;
2717
    }
2718

    
2719
    private static class ExtensionComparator implements Comparator {
2720

    
2721
        public int compare(Object o1, Object o2) {
2722
            Extension e1 = (Extension) o1;
2723
            Extension e2 = (Extension) o2;
2724

    
2725
            if (!e1.hasPriority() && !e2.hasPriority()) {
2726
                return -1;
2727
            }
2728

    
2729
            if (e1.hasPriority() && !e2.hasPriority()) {
2730
                return Integer.MIN_VALUE;
2731
            }
2732

    
2733
            if (e2.hasPriority() && !e1.hasPriority()) {
2734
                return Integer.MAX_VALUE;
2735
            }
2736

    
2737
            if (e1.getPriority() != e2.getPriority()) {
2738
                return e2.getPriority() - e1.getPriority();
2739
            } else {
2740
                return (e2.toString().compareTo(e1.toString()));
2741
            }
2742
        }
2743
    }
2744

    
2745
    private static class MenuComparator implements Comparator<SortableMenu> {
2746

    
2747
        private static ExtensionComparator extComp = new ExtensionComparator();
2748

    
2749
        public int compare(SortableMenu e1, SortableMenu e2) {
2750

    
2751
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2752
                if (e1.extension instanceof SkinExtensionType) {
2753
                    return 1;
2754
                } else if (e2.extension instanceof SkinExtensionType) {
2755
                    return -1;
2756
                } else {
2757
                    return extComp.compare(e1.extension, e2.extension);
2758
                }
2759
            }
2760

    
2761
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2762
                return Integer.MIN_VALUE;
2763
            }
2764

    
2765
            if (e2.menu.hasPosition() && !e1.menu.hasPosition()) {
2766
                return Integer.MAX_VALUE;
2767
            }
2768

    
2769
            if (e1.menu.getPosition() == e2.menu.getPosition()) {
2770
                                // we don't return 0 unless both objects are the same, otherwise
2771
                // the objects get overwritten in the treemap
2772
                return (e1.toString().compareTo(e2.toString()));
2773
            }
2774
            if (e1.menu.getPosition() > e2.menu.getPosition()) {
2775
                return Integer.MAX_VALUE;
2776
            }
2777
            return Integer.MIN_VALUE;
2778

    
2779
        }
2780
    }
2781

    
2782
    private static class SortableMenu {
2783

    
2784
        public PluginClassLoader loader;
2785
        public Menu menu;
2786
        public SkinExtensionType extension;
2787

    
2788
        public SortableMenu(PluginClassLoader loader,
2789
                SkinExtensionType skinExt, Menu menu2) {
2790
            extension = skinExt;
2791
            menu = menu2;
2792
            this.loader = loader;
2793
        }
2794

    
2795
    }
2796

    
2797
    private static class SortableTool {
2798

    
2799
        public PluginClassLoader loader;
2800
        public ToolBar toolbar;
2801
        public ActionTool actiontool;
2802
        public SelectableTool selectabletool;
2803
        public SkinExtensionType extension;
2804

    
2805
        public SortableTool(PluginClassLoader loader,
2806
                SkinExtensionType skinExt, ToolBar toolbar2,
2807
                ActionTool actiontool2) {
2808
            extension = skinExt;
2809
            toolbar = toolbar2;
2810
            actiontool = actiontool2;
2811
            this.loader = loader;
2812
        }
2813

    
2814
        public SortableTool(PluginClassLoader loader,
2815
                SkinExtensionType skinExt, ToolBar toolbar2,
2816
                SelectableTool selectabletool2) {
2817
            extension = skinExt;
2818
            toolbar = toolbar2;
2819
            selectabletool = selectabletool2;
2820
            this.loader = loader;
2821
        }
2822
    }
2823

    
2824
    private static class ToolBarComparator implements Comparator<SortableTool> {
2825

    
2826
        private static ExtensionComparator extComp = new ExtensionComparator();
2827

    
2828
        public int compare(SortableTool e1, SortableTool e2) {
2829

    
2830
                        // if the toolbars have the same name, they are considered to be
2831
            // the same toolbar, so we don't need to do further comparing
2832
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2833
                return 0;
2834
            }
2835

    
2836
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2837
                if (e1.extension instanceof SkinExtensionType) {
2838
                    return 1;
2839
                } else if (e2.extension instanceof SkinExtensionType) {
2840
                    return -1;
2841
                } else {
2842
                    return extComp.compare(e1.extension, e2.extension);
2843
                }
2844
            }
2845

    
2846
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2847
                return Integer.MIN_VALUE;
2848
            }
2849

    
2850
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2851
                return Integer.MAX_VALUE;
2852
            }
2853
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2854
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2855
            }
2856

    
2857
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2858
                    && e1.toolbar.getSelectableTool().equals(
2859
                            e2.toolbar.getSelectableTool())) {
2860
                return 0;
2861
            }
2862
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2863
        }
2864
    }
2865

    
2866
    /**
2867
     * <p>
2868
     * This class is used to compare tools (selectabletool and actiontool),
2869
     * using the "position" attribute.
2870
     * </p>
2871
     * <p>
2872
     * The ordering criteria are:
2873
     * </p>
2874
     * <ul>
2875
     * <li>If the tools are placed in different toolbars, they use the toolbars'
2876
     * order. (using the ToolBarComparator).</li>
2877
     * <li></li>
2878
     * <li>If any of the tools has not 'position' attribute, the tool which
2879
     * <strong>has</strong> the attribute will be placed first.</li>
2880
     * <li>If both tools have the same position (or they don't have a 'position'
2881
     * attribute), the priority of the extensions where the tool is
2882
     * defined.</li>
2883
     * </ul>
2884
     *
2885
     * @author cesar
2886
     * @version $Revision: 40305 $
2887
     */
2888
    private static class ToolComparator implements Comparator<SortableTool> {
2889

    
2890
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2891

    
2892
        public int compare(SortableTool e1, SortableTool e2) {
2893
            // compare the toolbars which contain the tools
2894
            long result = toolBarComp.compare(e1, e2);
2895
            if (result != 0) { // if the toolbars are different, use their order
2896
                return result > 0 ? 1 : -1;
2897
            }
2898
            // otherwise, compare the tools
2899
            long e1Position = -1, e2Position = -1;
2900

    
2901
            if (e1.actiontool != null) {
2902
                if (e1.actiontool.hasPosition()) {
2903
                    e1Position = e1.actiontool.getPosition();
2904
                }
2905
            } else if (e1.selectabletool != null) {
2906
                if (e1.selectabletool.hasPosition()) {
2907
                    e1Position = e1.selectabletool.getPosition();
2908
                }
2909
            }
2910

    
2911
            if (e2.actiontool != null) {
2912
                if (e2.actiontool.hasPosition()) {
2913
                    e2Position = e2.actiontool.getPosition();
2914
                }
2915
            } else if (e2.selectabletool != null) {
2916
                if (e2.selectabletool.hasPosition()) {
2917
                    e2Position = e2.selectabletool.getPosition();
2918
                }
2919
            }
2920

    
2921
            if ((e1Position == -1) && (e2Position != -1)) {
2922
                return 1;
2923
            }
2924
            if ((e1Position != -1) && (e2Position == -1)) {
2925
                return -1;
2926
            }
2927
            if ((e1Position != -1) && (e2Position != -1)) {
2928
                result = e1Position - e2Position;
2929
                                // we don't return 0 unless both objects are the same, otherwise
2930
                // the objects get overwritten in the treemap
2931
                if (result != 0) {
2932
                    return result > 0 ? 1 : -1;
2933
                }
2934
            }
2935
            return e1.toString().compareTo(e2.toString());
2936
        }
2937
    }
2938

    
2939
    public static String getDefaultLookAndFeel() {
2940
        String osName = (String) System.getProperty("os.name");
2941

    
2942
        if ((osName.length() > 4)
2943
                && osName.substring(0, 5).toLowerCase().equals("linux")) {
2944
            return nonWinDefaultLookAndFeel;
2945
        }
2946
        if (osName.toLowerCase().startsWith("mac os x")) {
2947
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
2948
        }
2949

    
2950
        return UIManager.getSystemLookAndFeelClassName();
2951
    }
2952

    
2953
    /**
2954
     * Gets the ISO 839 two-characters-long language code matching the provided
2955
     * language code (which may be an ISO 839-2/T three-characters-long code or
2956
     * an ISO 839-1 two-characters-long code).
2957
     *
2958
     * If the provided parameter is already two characters long, it returns the
2959
     * parameter without any modification.
2960
     *
2961
     * @param langCode A language code representing either an ISO 839-2/T
2962
     * language code or an ISO 839-1 code.
2963
     * @return A two-characters-long code specifying an ISO 839 language code.
2964
     */
2965
    private static String normalizeLanguageCode(String langCode) {
2966
        final String fileName = "iso_639.tab";
2967
        if (langCode.length() == 2) {
2968
            return langCode;
2969
        } else if (langCode.length() == 3) {
2970
            if (langCode.equals("va") || langCode.equals("val")) { // special
2971
                // case
2972
                // for
2973
                // Valencian
2974
                return "ca";
2975
            }
2976
            URL isoCodes = Launcher.class.getClassLoader()
2977
                    .getResource(fileName);
2978
            if (isoCodes != null) {
2979
                try {
2980
                    BufferedReader reader = new BufferedReader(
2981
                            new InputStreamReader(isoCodes.openStream(),
2982
                                    "ISO-8859-1"));
2983
                    String line;
2984

    
2985
                    while ((line = reader.readLine()) != null) {
2986
                        String[] language = line.split("\t");
2987
                        if (language[0].equals(langCode)) {
2988
                                                        // the three
2989
                            // characters code
2990
                            return language[2]; // third column i the two
2991
                            // characters code
2992
                        }
2993
                    }
2994
                } catch (IOException ex) {
2995
                    logger.error(Messages
2996
                            .getString("Error_reading_isocodes_file"), ex);
2997
                    return "es";
2998
                }
2999
            } else {
3000
                logger.error(Messages.getString("Error_reading_isocodes_file"));
3001
                return "es";
3002
            }
3003
        }
3004
        return "es";
3005
    }
3006

    
3007
    /**
3008
     * Configures the locales (languages and local resources) to be used by the
3009
     * application.
3010
     *
3011
     * First it tries to get the locale from the command line parameters, then
3012
     * the andami-config file is checked.
3013
     *
3014
     * The locale name is normalized to get a two characters language code as
3015
     * defined by ISO-639-1 (although ISO-639-2/T three characters codes are
3016
     * also accepted from the command line or the configuration file).
3017
     *
3018
     * Finally, the gvsig-i18n library and the default locales for Java and
3019
     * Swing are configured.
3020
     *
3021
     */
3022
    private static void configureLocales(String[] args) {
3023
        // Configurar el locale
3024
        String localeStr = null;
3025

    
3026
        localeStr = PluginServices.getArgumentByName("language");
3027
        if (localeStr == null) {
3028
            localeStr = andamiConfig.getLocaleLanguage();
3029
        }
3030
        localeStr = normalizeLanguageCode(localeStr);
3031
        locale = getLocale(
3032
                localeStr,
3033
                andamiConfig.getLocaleCountry(),
3034
                andamiConfig.getLocaleVariant()
3035
        );
3036
        org.gvsig.i18n.Messages.setCurrentLocale(locale);
3037
        JComponent.setDefaultLocale(locale);
3038
        /*
3039
         org.gvsig.i18n.Messages.addLocale(locale);
3040
         // add english and spanish as fallback languages
3041
         if ( localeStr.equals("es") || localeStr.equals("ca")
3042
         || localeStr.equals("gl") || localeStr.equals("eu")
3043
         || localeStr.equals("va") ) {
3044
         // prefer Spanish for languages spoken in Spain
3045
         org.gvsig.i18n.Messages.addLocale(new Locale("es"));
3046
         org.gvsig.i18n.Messages.addLocale(new Locale("en"));
3047
         } else {
3048
         // prefer English for the rest
3049
         org.gvsig.i18n.Messages.addLocale(new Locale("en"));
3050
         org.gvsig.i18n.Messages.addLocale(new Locale("es"));
3051
         }
3052
         */
3053
        // Create classloader for the i18n resources in the
3054
        // andami and user i18n folder. Those values will have
3055
        // precedence over any other values added afterwards
3056
        File appI18nFolder = new File(getApplicationFolder(), "i18n");
3057
        File userI18nFolder = new File(getAppHomeDir(), "i18n");
3058
        if (!userI18nFolder.exists()) {
3059
            try {
3060
                FileUtils.forceMkdir(userI18nFolder);
3061
            } catch (IOException e) {
3062
                logger.info("Can't create i18n folder in gvSIG home (" + userI18nFolder + ").", e);
3063
            }
3064
        }
3065
//        logger.info("Loading i18n resources from the application and user "
3066
//                + "folders: {}, {}", appI18nFolder, userI18nFolder);
3067

    
3068
        URL[] i18nURLs = getURLsFromI18nFolders(userI18nFolder, appI18nFolder);
3069
        ClassLoader i18nClassLoader = URLClassLoader.newInstance(i18nURLs, null);
3070
        logger.info("loading resources from classloader " + i18nClassLoader.toString() + ".");
3071
        org.gvsig.i18n.Messages.addResourceFamily("text", i18nClassLoader,
3072
                "Andami Launcher");
3073

    
3074
        // Finally load the andami own i18n resources
3075
        org.gvsig.i18n.Messages.addResourceFamily("org.gvsig.andami.text",
3076
                "Andami Launcher");
3077
    }
3078

    
3079
    private static URL[] getURLsFromI18nFolders(File userFolder, File appFolder) {
3080
        List<URL> urls = new ArrayList<URL>();
3081
        File[] files = new File[]{userFolder, appFolder};
3082
        for (int n1 = 0; n1 < files.length; n1++) {
3083
            File folder = files[n1];
3084
//                try {
3085
//                    urls.add(folder.toURI().toURL());
3086
//                } catch (MalformedURLException ex) {
3087
//                    logger.warn("Can't convert file to url (file="+userFolder.getAbsolutePath()+").", ex);
3088
//                    return null;
3089
//                }
3090
            File[] subFiles = folder.listFiles();
3091
            for (int n2 = 0; n2 < subFiles.length; n2++) {
3092
                File subFolder = subFiles[n2];
3093
                if ("andami".equalsIgnoreCase(subFolder.getName())) {
3094
                    // Skip andami and add the last.
3095
                    continue;
3096
                }
3097
                if (subFolder.isDirectory()) {
3098
                    try {
3099
                        urls.add(subFolder.toURI().toURL());
3100
                    } catch (MalformedURLException ex) {
3101
                        logger.warn("Can't convert file to url (file=" + subFolder.getAbsolutePath() + ").", ex);
3102
                        return null;
3103
                    }
3104
                }
3105
            }
3106
        }
3107
        File folder = new File(appFolder, "andami");
3108
        try {
3109
            urls.add(folder.toURI().toURL());
3110
        } catch (MalformedURLException ex) {
3111
            logger.warn("Can't convert file to url (file=" + folder.getAbsolutePath() + ").", ex);
3112
            return null;
3113
        }
3114
        return urls.toArray(new URL[urls.size()]);
3115
    }
3116

    
3117
    /**
3118
     * Gets Home Directory location of the application into users home folder.
3119
     *
3120
     * May be set from outside the aplication by means of
3121
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name of the application
3122
     *
3123
     * @return
3124
     */
3125
    public static String getAppHomeDir() {
3126
        return appHomeDir;
3127
    }
3128

    
3129
    public static File getApplicationHomeFolder() {
3130
        return new File(getAppHomeDir());
3131
    }
3132

    
3133
    /**
3134
     * Sets Home Directory location of the application. May be set from outside
3135
     * the aplication by means of -DgvSIG.home=C:/data/gvSIG, where gvSIG its
3136
     * the name of the application
3137
     *
3138
     * @param appHomeDir
3139
     */
3140
    public static void setAppHomeDir(String appHomeDir) {
3141
        Launcher.appHomeDir = appHomeDir;
3142
    }
3143

    
3144
    /**
3145
     * Initialize the extesion that have to take the control of the state of
3146
     * action controls of the UI of all extensions. <br>
3147
     * <br>
3148
     * For use this option you have to add an argument to the command line like
3149
     * this: <br>
3150
     * <br>
3151
     * -exclusiveUI={pathToExtensionClass} <br>
3152
     *
3153
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
3154
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
3155
     */
3156
    private static void initializeExclusiveUIExtension() {
3157
        String name = PluginServices.getArgumentByName("exclusiveUI");
3158
        if (name == null) {
3159
            return;
3160
        }
3161

    
3162
        Iterator<Class<? extends IExtension>> iter = classesExtensions.keySet()
3163
                .iterator();
3164
        int charIndex;
3165
        Class<? extends IExtension> key;
3166
        while (iter.hasNext()) {
3167
            key = iter.next();
3168
            charIndex = key.getName().indexOf(name);
3169
            // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex);
3170
            if (charIndex == 0) {
3171
                IExtension ext = classesExtensions.get(key);
3172
                if (ext instanceof ExtensionDecorator) {
3173
                    ext = ((ExtensionDecorator) ext).getExtension();
3174
                }
3175
                if (ext instanceof ExclusiveUIExtension) {
3176
                    PluginServices
3177
                            .setExclusiveUIExtension((ExclusiveUIExtension) ext);
3178
                }
3179
                break;
3180
            }
3181
        }
3182

    
3183
        logger
3184
                .error(Messages
3185
                        .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
3186
                        + " '" + name + "'");
3187
    }
3188

    
3189
    public static void initIconThemes() {
3190
        PluginsManager pluginsManager = PluginsLocator.getManager();
3191
        IconThemeManager iconManager = ToolsSwingLocator.getIconThemeManager();
3192

    
3193
        File f = new File(pluginsManager.getApplicationFolder(), "icon-theme");
3194
        if (!f.exists()) {
3195
            try {
3196
                f.mkdir();
3197
            } catch (Exception ex) {
3198
                // Do nothing
3199
            }
3200
        }
3201
        iconManager.getRepository().add(f, "_Global");
3202

    
3203
        f = new File(pluginsManager.getApplicationHomeFolder(), "icon-theme");
3204
        if (!f.exists()) {
3205
            try {
3206
                f.mkdir();
3207
            } catch (Exception ex) {
3208
                // Do nothing
3209
            }
3210
        }
3211
        iconManager.getRepository().add(f, "_User");
3212

    
3213
        Preferences prefs = Preferences.userRoot().node("gvsig.icontheme");
3214
        String defaultThemeID = prefs.get("default-theme", null);
3215
        if (defaultThemeID != null) {
3216
            IconTheme iconTheme = iconManager.get(defaultThemeID);
3217
            if (iconTheme != null) {
3218
                iconManager.setCurrent(iconTheme);
3219
            }
3220
        }
3221
    }
3222

    
3223
    public static void manageUnsavedData(String prompt) throws Exception {
3224
        final UnsavedDataPanel panel = new UnsavedDataPanel(prompt);
3225
        final List<IUnsavedData> unsavedData = PluginsLocator.getManager().getUnsavedData();
3226
        panel.setUnsavedData(unsavedData);
3227

    
3228
        panel.addActionListener(panel.new UnsavedDataPanelListener() {
3229

    
3230
            public void cancel(UnsavedDataPanel panel) {
3231
                panel.setVisible(false);
3232
            }
3233

    
3234
            public void discard(UnsavedDataPanel panel) {
3235
                panel.setVisible(false);
3236
            }
3237

    
3238
            public void accept(UnsavedDataPanel panel) {
3239
                panel.setVisible(false);
3240

    
3241
                try {
3242
                    PluginsLocator.getManager().saveUnsavedData(panel.getSelectedsUnsavedDataList());
3243
                } catch (UnsavedDataException e) {
3244
                    StringBuilder msg = new StringBuilder();
3245
                    msg.append(PluginServices.getText(this, "The_following_resources_could_not_be_saved"));
3246
                    msg.append("\n");
3247
                    for (Iterator iterator = e.getUnsavedData().iterator(); iterator.hasNext();) {
3248
                        IUnsavedData unsavedData = (IUnsavedData) iterator.next();
3249
                        msg.append(unsavedData.getResourceName());
3250
                        msg.append(" -- ");
3251
                        msg.append(unsavedData.getDescription());
3252
                        msg.append("\n");
3253
                    }
3254
                    JOptionPane.showMessageDialog(panel, msg, PluginServices.getText(this, "Resources_was_not_saved"), JOptionPane.ERROR_MESSAGE);
3255
                }
3256
            }
3257
        });
3258

    
3259
        //TODO: mostrar panel WindowManager
3260
        ToolsSwingLocator.getWindowManager().showWindow(
3261
                panel,
3262
                PluginServices.getText(panel, "Resource_was_not_saved"),
3263
                MODE.DIALOG);
3264

    
3265
    }
3266

    
3267
    /**
3268
     * Manages Andami termination process
3269
     *
3270
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
3271
     */
3272
    public class TerminationProcess {
3273

    
3274
        private boolean proceed = false;
3275
        private UnsavedDataPanel panel = null;
3276

    
3277
        public void run() {
3278
            try {
3279
                int exit = manageUnsavedData();
3280
                if ((exit == JOptionPane.NO_OPTION)
3281
                        || (exit == JOptionPane.CLOSED_OPTION)) {
3282
                    // the user doesn't want to exit
3283
                    return;
3284
                }
3285
                closeAndami();
3286
            } catch (Exception e) {
3287
                logger.warn("It is not possible to close the application", e);
3288
                                // It is not possible to close the application.
3289
                // this exception has been registered before
3290
            }
3291
        }
3292

    
3293
        /**
3294
         * Finishes the application without asking user if want or not to save
3295
         * unsaved data.
3296
         */
3297
        public void closeAndami() {
3298
            PluginsManager pluginsManager = PluginsLocator.getManager();
3299
            pluginsManager.executeShutdownTasks();
3300

    
3301
            try {
3302
                saveAndamiConfig();
3303
            } catch (Exception ex) {
3304
                logger.error(
3305
                        "There was an error exiting application, can't save andami-config.xml",
3306
                        ex
3307
                );
3308
            }
3309

    
3310
            try {
3311
                // Persistencia de los plugins
3312
                savePluginPersistence();
3313
                savePluginsProperties();
3314
            } catch (Exception ex) {
3315
                logger.error(
3316
                        "There was an error exiting application, can't save plugins properties",
3317
                        ex
3318
                );
3319
            }
3320

    
3321
            // Finalize all the extensions
3322
            finalizeExtensions();
3323

    
3324
            try {
3325
                // Clean any temp data created
3326
                Utilities.cleanUpTempFiles();
3327
            } catch (Exception ex) {
3328
                logger.error(
3329
                        "There was an error exiting application, can't remove temporary files",
3330
                        ex
3331
                );
3332
            }
3333

    
3334
            logger.info("Quiting application.");
3335

    
3336
            // Para la depuraci?n de memory leaks
3337
            System.gc();
3338

    
3339
            System.exit(0);
3340
        }
3341

    
3342
        public void saveAndamiConfig() {
3343
            // Configuraci?n de Andami
3344
            try {
3345
                andamiConfigToXML(andamiConfigPath);
3346
            } catch (MarshalException e) {
3347
                logger
3348
                        .error(
3349
                                Messages
3350
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3351
                                e);
3352
            } catch (ValidationException e) {
3353
                logger
3354
                        .error(
3355
                                Messages
3356
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3357
                                e);
3358
            } catch (IOException e) {
3359
                logger
3360
                        .error(
3361
                                Messages
3362
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3363
                                e);
3364
            }
3365
        }
3366

    
3367
        private void savePluginsProperties() {
3368
            PluginsManager manager = PluginsLocator.getManager();
3369
            List<PluginServices> plugins = manager.getPlugins();
3370
            for (PluginServices plugin : plugins) {
3371
                if (plugin != null) {
3372
                    plugin.savePluginProperties();
3373
                }
3374
            }
3375
        }
3376

    
3377
        /**
3378
         * Exectutes the terminate method for all the extensions, in the reverse
3379
         * order they were initialized
3380
         *
3381
         */
3382
        private void finalizeExtensions() {
3383
            for (int i = extensions.size() - 1; i >= 0; i--) {
3384
                org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
3385
                        .get(i);
3386
                String extensionName = "(unknow)";
3387
                try {
3388
                    extensionName = extensionInstance.getClass().getName();
3389
                    extensionInstance.terminate();
3390
                } catch (Exception ex) {
3391
                    logger.error(MessageFormat.format(
3392
                            "There was an error extension ending {0}",
3393
                            extensionName), ex);
3394
                }
3395
            }
3396
        }
3397

    
3398
        private IUnsavedData[] getUnsavedData() throws Exception {
3399
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
3400
            IExtension exclusiveExtension = PluginServices
3401
                    .getExclusiveUIExtension();
3402

    
3403
            for (int i = extensions.size() - 1; i >= 0; i--) {
3404
                org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
3405
                        .get(i);
3406
                IExtensionStatus status = null;
3407
                if (exclusiveExtension != null) {
3408
                    status = exclusiveExtension.getStatus(extensionInstance);
3409
                } else {
3410
                    status = extensionInstance.getStatus();
3411
                }
3412
                if (status != null) {
3413
                    try {
3414
                        if (status.hasUnsavedData()) {
3415
                            IUnsavedData[] array = status.getUnsavedData();
3416
                            for (int element = 0; element < array.length; element++) {
3417
                                unsavedDataList.add(array[element]);
3418
                            }
3419
                        }
3420
                    } catch (Exception e) {
3421
                        logger.info("Error calling the hasUnsavedData method",
3422
                                new Exception());
3423
                        int option = JOptionPane
3424
                                .showConfirmDialog(
3425
                                        frame,
3426
                                        Messages
3427
                                        .getString("error_getting_unsaved_data"),
3428
                                        Messages.getString("MDIFrame.salir"),
3429
                                        JOptionPane.YES_NO_OPTION);
3430
                        if (option == JOptionPane.NO_OPTION) {
3431
                            throw e;
3432
                        }
3433
                    }
3434
                }
3435
            }
3436
            return unsavedDataList.toArray(new IUnsavedData[unsavedDataList
3437
                    .size()]);
3438
        }
3439

    
3440
        public UnsavedDataPanel getUnsavedDataPanel() {
3441
            if (panel == null) {
3442
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
3443
            }
3444
            return panel;
3445
        }
3446

    
3447
        /**
3448
         * Checks if the extensions have some unsaved data, and shows a dialog
3449
         * to allow saving it. This dialog also allows to don't exit Andami.
3450
         *
3451
         * @return true if the user confirmed he wishes to exit, false otherwise
3452
         * @throws Exception
3453
         */
3454
        public int manageUnsavedData() throws Exception {
3455
            IUnsavedData[] unsavedData = getUnsavedData();
3456

    
3457
            // there was no unsaved data
3458
            if (unsavedData.length == 0) {
3459
                int option = JOptionPane
3460
                        .showConfirmDialog(frame, Messages
3461
                                .getString("MDIFrame.quiere_salir"), Messages
3462
                                .getString("MDIFrame.salir"),
3463
                                JOptionPane.YES_NO_OPTION);
3464
                return option;
3465
            }
3466

    
3467
            UnsavedDataPanel panel = getUnsavedDataPanel();
3468
            panel.setUnsavedDataArray(unsavedData);
3469

    
3470
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
3471

    
3472
                public void cancel(UnsavedDataPanel panel) {
3473
                    proceed(false);
3474
                    PluginServices.getMDIManager().closeWindow(panel);
3475

    
3476
                }
3477

    
3478
                public void discard(UnsavedDataPanel panel) {
3479
                    proceed(true);
3480
                    PluginServices.getMDIManager().closeWindow(panel);
3481

    
3482
                }
3483

    
3484
                public void accept(UnsavedDataPanel panel) {
3485
                    IUnsavedData[] unsavedDataArray = panel
3486
                            .getSelectedsUnsavedData();
3487
                    boolean saved;
3488
                    for (int i = 0; i < unsavedDataArray.length; i++) {
3489
                        try {
3490
                            saved = unsavedDataArray[i].saveData();
3491
                        } catch (Exception ex) {
3492
                            PluginServices.getLogger().error(
3493
                                    "Error saving"
3494
                                    + unsavedDataArray[i]
3495
                                    .getResourceName(), ex);
3496
                            saved = false;
3497
                        }
3498
                        if (!saved) {
3499
                            JOptionPane
3500
                                    .showMessageDialog(
3501
                                            panel,
3502
                                            PluginServices
3503
                                            .getText(this,
3504
                                                    "The_following_resource_could_not_be_saved_")
3505
                                            + "\n"
3506
                                            + unsavedDataArray[i]
3507
                                            .getResourceName()
3508
                                            + " -- "
3509
                                            + unsavedDataArray[i]
3510
                                            .getDescription(),
3511
                                            PluginServices.getText(this,
3512
                                                    "unsaved_resources"),
3513
                                            JOptionPane.ERROR_MESSAGE);
3514

    
3515
                            try {
3516
                                unsavedDataArray = getUnsavedData();
3517
                            } catch (Exception e) {
3518
                                // This exception has been registered before
3519
                            }
3520
                            panel.setUnsavedDataArray(unsavedDataArray);
3521
                            return;
3522
                        }
3523
                    }
3524
                    proceed(true);
3525
                    PluginServices.getMDIManager().closeWindow(panel);
3526
                }
3527
            });
3528

    
3529
            PluginServices.getMDIManager().addWindow(panel);
3530
            if (proceed) {
3531
                return JOptionPane.YES_OPTION;
3532
            } else {
3533
                return JOptionPane.NO_OPTION;
3534
            }
3535
        }
3536

    
3537
        private void proceed(boolean proceed) {
3538
            this.proceed = proceed;
3539
        }
3540

    
3541
    }
3542

    
3543
    public static TerminationProcess getTerminationProcess() {
3544
        return (new Launcher()).new TerminationProcess();
3545
    }
3546

    
3547
    private PackageInfo getPackageInfo(String pluginsFolder) {
3548
        try {
3549
            PluginsManager pm = PluginsLocator.getManager();
3550
            return pm.getPackageInfo();
3551
        } catch (Exception e) {
3552
            logger.info("Can't locate PackageInfo from plugin org.gvsig.app", e);
3553
            return null;
3554
        }
3555
    }
3556

    
3557
    /**
3558
     * Launch the gvSIG package installer.
3559
     *
3560
     * @throws Exception if there is any error
3561
     */
3562
    private void doInstall(String[] args) throws Exception {
3563
        String installURL = null;
3564
        String installURLFile = null;
3565
        String gvSIGVersion = null;
3566
        String[] myArgs = new String[3];
3567
        PackageInfo packageInfo = null;
3568

    
3569
        Options options = new Options();
3570
        options.addOption("i", "install", false, "install");
3571
        options.addOption("u", "installURL", true, "installURL");
3572
        options.addOption("f", "installURLFile", true, "installURLFile");
3573
        options.addOption("v", "installVersion", true, "installVersion");
3574
        options.addOption("A", "applicationName", true, "application name, default is gvSIG");
3575
        options.addOption("P", "pluginsFolder", true, "pluginsFolder");
3576
        options.addOption("l", "language", true, "language");
3577

    
3578
        // This options are managed by the gvSIG.sh but need to be declared here to avoid
3579
        // errors.
3580
        options.addOption(null, "debug", false, "Activate the JVM remote debug");
3581
        options.addOption(null, "pause", false, "Pause when activate JVM debug");
3582

    
3583
        /*
3584
         * Los parametros que deberian pasarse en el instalador oficial de gvSIG serian:
3585
         *
3586
         * --install
3587
         * --applicationName=gvSIG
3588
         * --language=es
3589
         * --pluginsFolder=gvSIG/extensiones
3590
         *
3591
         * Opcionales (casi mejor que dejar los de por defecto y no pasarselos):
3592
         * --installVersion=2.0.0
3593
         * --installURL=http://downloads.gvsig.org/download/gvsig-desktop/dists
3594
         * --installURLFile=gvSIG/extensiones/org.gvsig.installer.app.extension/defaultDownloadsURLs
3595
         *
3596
         */
3597
        CommandLineParser parser = new PosixParser();
3598
        CommandLine line = null;
3599
        try {
3600
            line = parser.parse(options, args);
3601
            boolean hasAllMandatoryOptions = true;
3602
            if (!line.hasOption("install")) {
3603
                hasAllMandatoryOptions = false;
3604
            }
3605

    
3606
            if (line.hasOption("installVersion")) {
3607
                gvSIGVersion = line.getOptionValue("installVersion");
3608
            }
3609
            if (line.hasOption("applicationName")) {
3610
                myArgs[0] = line.getOptionValue("applicationName");
3611
            } else {
3612
                myArgs[0] = "gvSIG";
3613
            }
3614
            if (line.hasOption("pluginsFolder")) {
3615
                myArgs[1] = line.getOptionValue("pluginsFolder");
3616
            } else {
3617
                myArgs[1] = "gvSIG/extensiones";
3618
            }
3619
            if (line.hasOption("language")) {
3620
                myArgs[2] = "language=" + line.getOptionValue("language");
3621
            } else {
3622
                // prevent null
3623
                myArgs[2] = Locale.getDefault().toString();
3624
            }
3625

    
3626
            if (line.hasOption("installURL")) {
3627
                installURL = line.getOptionValue("installURL");
3628
            } else {
3629
                installURL = "http://downloads.gvsig.org/download/gvsig-desktop/";
3630
            }
3631

    
3632
            if (line.hasOption("installURLFile")) {
3633
                installURLFile = line.getOptionValue("installURLFile");
3634
            } else {
3635
                installURLFile = myArgs[1] + "/org.gvsig.installer.app.mainplugin/defaultDownloadsURLs";
3636
            }
3637

    
3638
            if (!hasAllMandatoryOptions) {
3639
                System.err.println(Messages.get("usage") + ": Launcher "
3640
                        + "--install "
3641
                        + "[--applicationName=appName] "
3642
                        + "[--pluginsFolder=plugins-directory] "
3643
                        + "[--installURLFile=File] "
3644
                        + "[--installURL=URL] "
3645
                        + "[--language=locale]"
3646
                );
3647
                return;
3648
            }
3649
        } catch (ParseException exp) {
3650
            System.err.println("Unexpected exception:" + exp.getMessage());
3651
            System.exit(-1);
3652
        }
3653

    
3654
        initializeApp(myArgs, "installer");
3655

    
3656
        new DefaultLibrariesInitializer().fullInitialize(true);
3657

    
3658
        initializeInstallerManager();
3659

    
3660
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
3661

    
3662
        try {
3663
            logger.info("Loading plugins configurations");
3664
            this.loadPluginConfigs();
3665
        } catch (Throwable ex) {
3666
            logger.warn("Can't load plugins configurations", ex);
3667
        }
3668

    
3669
        try {
3670
            logger.info("Loading plugins");
3671
            this.loadPluginServices();
3672
        } catch (Throwable ex) {
3673
            logger.warn("Can't load plugins", ex);
3674
        }
3675

    
3676
        AndamiConfig config = getAndamiConfig();
3677

    
3678
        initializeIdentityManagement(new File(config.getPluginsDirectory()).getAbsoluteFile());
3679

    
3680
        initializeLibraries();
3681

    
3682
//        config.setLocaleLanguage(locale.getLanguage());
3683
//        config.setLocaleCountry(locale.getCountry());
3684
//        config.setLocaleVariant(locale.getVariant());
3685
        packageInfo = getPackageInfo(myArgs[1]);
3686

    
3687
        // set the gvSIG version to the install manager, to compose the download URL
3688
        if (packageInfo != null) {
3689
            installerManager.setVersion(packageInfo.getVersion());
3690
        } else {
3691
            installerManager.setVersion(gvSIGVersion);
3692
        }
3693
        if (!installURL.contains(";")
3694
                && !installURL.endsWith(InstallerManager.PACKAGE_EXTENSION)
3695
                && !installURL.endsWith(InstallerManager.PACKAGE_INDEX_EXTENSION)) {
3696
            if (packageInfo != null && (packageInfo.getState().startsWith(InstallerManager.STATE.BETA)
3697
                    || packageInfo.getState().startsWith(InstallerManager.STATE.RC)
3698
                    || packageInfo.getState().equalsIgnoreCase(InstallerManager.STATE.FINAL))) {
3699
                installURL = installURL + "dists/<%Version%>/builds/<%Build%>/packages.gvspki";
3700
            }
3701
        }
3702
        // Configure default index download URL
3703
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(installURL);
3704

    
3705
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(new File(installURLFile));
3706

    
3707
        // Launch installer
3708
        PluginsManager manager = PluginsLocator.getManager();
3709

    
3710
        AbstractInstallPackageWizard installPackageWizard = SwingInstallerLocator
3711
                .getSwingInstallerManager().createInstallPackageWizard(
3712
                        manager.getApplicationFolder(),
3713
                        manager.getInstallFolder());
3714
        installPackageWizard.setWizardActionListener(new InstallerWizardActionListener() {
3715
            public void finish(InstallerWizardPanel installerWizard) {
3716
                logger.info("Finish installation.");
3717
                System.exit(0);
3718
            }
3719

    
3720
            public void cancel(InstallerWizardPanel installerWizard) {
3721
                logger.info("Cancel installation.");
3722
                System.exit(0);
3723
            }
3724
        });
3725

    
3726
        // the wizard will show the Typical or Advanced mode option.
3727
        installPackageWizard.setAskTypicalOrCustom(true);
3728
        // default packages will be selected.
3729
        installPackageWizard.setSelectDefaultPackages(true);
3730

    
3731
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
3732

    
3733
        frame.addWindowListener(new WindowListener() {
3734
            public void windowOpened(WindowEvent we) {
3735
                logger.info("Open window installation.");
3736
            }
3737

    
3738
            public void windowClosing(WindowEvent we) {
3739
                logger.info("Closing installation.");
3740
                System.exit(0);
3741
            }
3742

    
3743
            public void windowClosed(WindowEvent we) {
3744
                logger.info("Close installation.");
3745
                System.exit(0);
3746
            }
3747

    
3748
            public void windowIconified(WindowEvent we) {
3749
            }
3750

    
3751
            public void windowDeiconified(WindowEvent we) {
3752
            }
3753

    
3754
            public void windowActivated(WindowEvent we) {
3755
                logger.info("Activate window installation.");
3756
            }
3757

    
3758
            public void windowDeactivated(WindowEvent we) {
3759
                logger.info("Deactivate window installation.");
3760
            }
3761
        });
3762
        //frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
3763

    
3764
        frame.getContentPane().add(installPackageWizard, BorderLayout.CENTER);
3765

    
3766
        URL iconURL = getClass().getResource("/images/main/install-icon.png");
3767
        if( iconURL!=null ) {
3768
            ImageIcon icon = new ImageIcon(iconURL);
3769
            frame.setIconImage(icon.getImage());
3770
        }
3771
        frame.pack();
3772
        frame.setLocationRelativeTo(null);
3773

    
3774
        frame.setVisible(true);
3775
    }
3776

    
3777
    public static String getInformation() {
3778
        return getInformation(null);
3779
    }
3780

    
3781
    private static final int INFO_OS_NAME = 0;
3782
    private static final int INFO_OS_ARCH = 1;
3783
    private static final int INFO_OS_VERSION = 2;
3784
    private static final int INFO_OS_ADITIONAL = 3;
3785
    private static final int INFO_JRE_VENDOR = 4;
3786
    private static final int INFO_JRE_VERSION = 5;
3787
    private static final int INFO_JRE_HOME = 6;
3788
    private static final int INFO_PROXY_HOST = 7;
3789
    private static final int INFO_PROXY_PORT = 8;
3790
    private static final int INFO_PROXY_USER = 9;
3791
    private static final int INFO_PROXY_PASSWORD = 10;
3792
    private static final int INFO_APP_LOCALE = 11;
3793
    private static final int INFO_APP_FOLDER = 12;
3794
    private static final int INFO_APP_HOME = 13;
3795
    private static final int INFO_APP_INSTALL_FOLDER = 14;
3796
    private static final int INFO_APP_PLUGINS_FOLDER = 15;
3797
    private static final int INFO_APP_THEME = 16;
3798
    private static final int INFO_APP_SKIN = 17;
3799
    private static final int INFO_PACKAGES = 18;
3800

    
3801
    public static String getInformation(PackageInfo[] pkgs) {
3802

    
3803
        String template = "OS\n"
3804
                + "    name    : {" + INFO_OS_NAME + "}\n"
3805
                + "    arch    : {" + INFO_OS_ARCH + "}\n"
3806
                + "    version : {" + INFO_OS_VERSION + "} \n"
3807
                + "{" + INFO_OS_ADITIONAL + "}"
3808
                + "JRE\n"
3809
                + "    vendor  : {" + INFO_JRE_VENDOR + "}\n"
3810
                + "    version : {" + INFO_JRE_VERSION + "}\n"
3811
                + "    home    : {" + INFO_JRE_HOME + "}\n"
3812
                + "HTTP Proxy\n"
3813
                + "    http.proxyHost     : {" + INFO_PROXY_HOST + "}\n"
3814
                + "    http.proxyPort     : {" + INFO_PROXY_PORT + "}\n"
3815
                + "    http.proxyUserName : {" + INFO_PROXY_USER + "}\n"
3816
                + "    http.proxyPassword : {" + INFO_PROXY_PASSWORD + "}\n"
3817
                + "Application\n"
3818
                + "    locale language         : {" + INFO_APP_LOCALE + "}\n"
3819
                + "    application forlder     : {" + INFO_APP_FOLDER + "}\n"
3820
                + "    application home forlder: {" + INFO_APP_HOME + "}\n"
3821
                + "    install forlder         : {" + INFO_APP_INSTALL_FOLDER + "}\n"
3822
                + "    plugins forlder         : {" + INFO_APP_PLUGINS_FOLDER + "}\n"
3823
                + "    theme                   : {" + INFO_APP_THEME + "}\n"
3824
                + "    Skin                    : {" + INFO_APP_SKIN + "}\n"
3825
                + "Installed packages\n"
3826
                + "{" + INFO_PACKAGES + "}";
3827

    
3828
        String values[] = new String[INFO_PACKAGES + 1];
3829

    
3830
        PluginsManager pluginmgr = PluginsLocator.getManager();
3831
        LocaleManager localemgr = PluginsLocator.getLocaleManager();
3832

    
3833
        Properties props = System.getProperties();
3834

    
3835
        // OS information
3836
        values[INFO_OS_NAME] = props.getProperty("os.name");
3837
        values[INFO_OS_ARCH] = props.getProperty("os.arch");
3838
        values[INFO_OS_VERSION] = props.getProperty("os.version");
3839

    
3840
        if (values[INFO_OS_NAME].startsWith("Linux")) {
3841
            try {
3842
                StringWriter writer = new StringWriter();
3843

    
3844
                String[] command = {"lsb_release", "-a"};
3845
                Process p = Runtime.getRuntime().exec(command);
3846
                InputStream is = p.getInputStream();
3847
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
3848
                String line;
3849
                while ((line = reader.readLine()) != null) {
3850
                    writer.write("    " + line + "\n");
3851
                }
3852
                values[INFO_OS_ADITIONAL] = writer.toString();
3853
            } catch (Exception ex) {
3854
                logger.warn("Can't get detailled os information (lsb_release -a).", ex);
3855
            }
3856
        }
3857

    
3858
        values[INFO_JRE_VENDOR] = props.getProperty("java.vendor");
3859
        values[INFO_JRE_VERSION] = props.getProperty("java.version");
3860
        values[INFO_JRE_HOME] = props.getProperty("java.home");
3861
        values[INFO_PROXY_HOST] = props.getProperty("http.proxyHost");
3862
        values[INFO_PROXY_PORT] = props.getProperty("http.proxyPort");
3863
        values[INFO_PROXY_USER] = props.getProperty("http.proxyUserName");
3864

    
3865
        if (props.get("http.proxyPassword") == null) {
3866
            values[INFO_PROXY_PASSWORD] = "(null)";
3867
        } else {
3868
            values[INFO_PROXY_PASSWORD] = "***********";
3869
        }
3870

    
3871
        try {
3872
            values[INFO_APP_SKIN] = MDIManagerFactory.getSkinExtension().getClassName();
3873
        } catch (Throwable e) {
3874
            values[INFO_APP_SKIN] = "(unknow)";
3875
        }
3876
        values[INFO_APP_LOCALE] = localemgr.getCurrentLocale().toString();
3877
        values[INFO_APP_FOLDER] = pluginmgr.getApplicationFolder().getAbsolutePath();
3878
        values[INFO_APP_HOME] = pluginmgr.getApplicationHomeFolder().getAbsolutePath();
3879
        values[INFO_APP_INSTALL_FOLDER] = pluginmgr.getInstallFolder().getAbsolutePath();
3880
        values[INFO_APP_PLUGINS_FOLDER] = StringUtils.join(pluginmgr.getPluginsFolders());
3881
        values[INFO_APP_THEME] = Launcher.theme.getSource().getAbsolutePath();
3882

    
3883
        try {
3884
            if (pkgs == null) {
3885
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
3886
                pkgs = installmgr.getInstalledPackages();
3887
            }
3888
            StringWriter writer = new StringWriter();
3889
            for (int i = 0; i < pkgs.length; i++) {
3890
                writer.write("    ");
3891
                writer.write(pkgs[i].toStringCompact());
3892
                writer.write("\n");
3893
            }
3894
            values[INFO_PACKAGES] = writer.toString();
3895

    
3896
        } catch (Throwable e) {
3897
            logger.warn("Can't get installed package information.", e);
3898
        }
3899

    
3900
        String s = MessageFormat.format(template, values);
3901
        return s;
3902
    }
3903

    
3904
    private void logger_info(String msg) {
3905
        String info[] = msg.split("\n");
3906
        for (int i = 0; i < info.length; i++) {
3907
            logger.info(info[i]);
3908
        }
3909
    }
3910

    
3911
    private void saveEnvironInformation(PackageInfo[] pkgs) {
3912
        PluginsManager manager = PluginsLocator.getManager();
3913
        File fout = new File(manager.getApplicationHomeFolder(), "gvSIG-environ.info");
3914
        try {
3915
            FileUtils.write(fout, getInformation(pkgs));
3916
        } catch (IOException e) {
3917
            logger.info("Can't create '" + fout.getAbsolutePath() + "'");
3918
        }
3919
    }
3920

    
3921
    private void fixIncompatiblePlugins(PackageInfo[] installedPackages) {
3922
        final Set<String> incompatiblePlugins = new HashSet<String>();
3923

    
3924
        // Add installed packages to a Map to optimize searchs
3925
        final Map<String, PackageInfo> packages = new HashMap<String, PackageInfo>();
3926
        for (int i = 0; i < installedPackages.length; i++) {
3927
            packages.put(installedPackages[i].getCode(), installedPackages[i]);
3928
        }
3929
        Iterator<Entry<String, PluginConfig>> it = pluginsConfig.entrySet().iterator();
3930
        while (it.hasNext()) {
3931
            List<String> pluginNames = new ArrayList<String>();
3932
            Entry<String, PluginConfig> entry = it.next();
3933
            PluginConfig pluginConfig = entry.getValue();
3934
            pluginNames.add(entry.getKey());
3935

    
3936
                        // Locate the package for this plugin.
3937
            // Be care whith alias
3938
            String[] aliases = pluginsConfig.getAliases(pluginConfig);
3939
            if (aliases != null) {
3940
                for (int i = 0; i < aliases.length; i++) {
3941
                    pluginNames.add(aliases[i]);
3942
                }
3943
            }
3944
            PackageInfo pkg = null;
3945
            for (int n = 0; n < pluginNames.size(); n++) {
3946
                pkg = packages.get(pluginNames.get(n));
3947
                if (pkg != null) {
3948
                    break;
3949
                }
3950
            }
3951

    
3952
            // If package is found verify dependencies
3953
            if (pkg != null) {
3954
                Dependencies dependencies = pkg.getDependencies();
3955
                for (int i = 0; i < dependencies.size(); i++) {
3956
                    Dependency dependency = (Dependency) dependencies.get(i);
3957
                    if (Dependency.CONFLICT.equalsIgnoreCase(dependency.getType())) {
3958
                        String code = dependency.getCode();
3959
                        if (pluginsConfig.get(code) != null) {
3960
                            incompatiblePlugins.add(pkg.getCode());
3961
                            incompatiblePlugins.add(code);
3962
                        }
3963
                    }
3964
                }
3965
            }
3966
        }
3967
        if (incompatiblePlugins.isEmpty()) {
3968
            return;
3969
        }
3970
        splashWindow.toBack();
3971
        DisablePluginsConflictingDialog dlg = new DisablePluginsConflictingDialog(packages, incompatiblePlugins);
3972
        dlg.setVisible(true);
3973
        splashWindow.toFront();
3974
        switch (dlg.getAction()) {
3975
            case DisablePluginsConflictingDialog.CLOSE:
3976
                System.exit(0);
3977
                break;
3978
            case DisablePluginsConflictingDialog.CONTINUE:
3979
                break;
3980
        }
3981
        List<String> pluginsToDissable = dlg.getPluginNamesToDisable();
3982
        if (pluginsToDissable == null) {
3983
            return;
3984
        }
3985

    
3986
        Iterator<String> it2 = pluginsToDissable.iterator();
3987
        while (it2.hasNext()) {
3988
            String pluginName = it2.next();
3989
            logger.info("Dissabling plugin '" + pluginName + "' by user action.");
3990
            pluginsConfig.remove(pluginName);
3991
        }
3992
    }
3993

    
3994
    private class DisablePluginsConflictingDialog extends JDialog {
3995

    
3996
        public static final int CONTINUE = 0;
3997
        public static final int CLOSE = 1;
3998

    
3999
        private DisablePluginsConflictingLayoutPanel contents;
4000
        private int action = 0;
4001
        private List<Item> incompatiblePlugins = null;
4002
        private Map<String, PackageInfo> packages;
4003

    
4004
        private class Item {
4005

    
4006
            private String code;
4007
            private PackageInfo pkg;
4008

    
4009
            public Item(String code, PackageInfo pkg) {
4010
                this.code = code;
4011
                this.pkg = pkg;
4012
            }
4013

    
4014
            public String toString() {
4015
                if (this.pkg == null) {
4016
                    return code;
4017
                }
4018
                return this.pkg.getName() + " (" + this.pkg.getCode() + ")";
4019
            }
4020

    
4021
            public String getCode() {
4022
                if (pkg == null) {
4023
                    return code;
4024
                }
4025
                return pkg.getCode();
4026
            }
4027
        }
4028

    
4029
        DisablePluginsConflictingDialog(Map<String, PackageInfo> packages, Set<String> incompatiblePlugins) {
4030
            super((Frame) null, "", true);
4031
            this.setTitle(translate("_Conflicting_plugins"));
4032

    
4033
            this.packages = packages;
4034

    
4035
            this.incompatiblePlugins = new ArrayList<Item>();
4036
            Item item = null;
4037
            Iterator<String> it = incompatiblePlugins.iterator();
4038
            while (it.hasNext()) {
4039
                String code = it.next();
4040
                item = new Item(code, packages.get(code));
4041
                this.incompatiblePlugins.add(item);
4042
                logger.info("Found plugin '" + item.getCode() + "' incopatibles with each other.");
4043
            }
4044
            initComponents();
4045
        }
4046

    
4047
        private void initComponents() {
4048
            this.contents = new DisablePluginsConflictingLayoutPanel();
4049

    
4050
            doTranslations();
4051

    
4052
            this.contents.buttonClose.addActionListener(new ActionListener() {
4053
                public void actionPerformed(ActionEvent arg0) {
4054
                    doClose();
4055
                }
4056
            });
4057
            this.contents.buttonContinue.addActionListener(new ActionListener() {
4058
                public void actionPerformed(ActionEvent arg0) {
4059
                    doContinue();
4060
                }
4061
            });
4062
            this.contents.pluginList.setModel(new DefaultListModel(this.incompatiblePlugins));
4063
            ListSelectionModel sm = this.contents.pluginList.getSelectionModel();
4064
            sm.setSelectionMode(sm.MULTIPLE_INTERVAL_SELECTION);
4065
            this.setContentPane(this.contents);
4066
            this.pack();
4067

    
4068
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
4069
            setLocation((screenSize.width / 2) - (this.getWidth() / 2),
4070
                    (screenSize.height / 2) - (this.getHeight() / 2));
4071
        }
4072

    
4073
        private void doTranslations() {
4074
            DisablePluginsConflictingLayoutPanel c = this.contents;
4075
            c.lblConflict.setText(translate("_Some_of_plugins_installed_conflict_with_each_other"));
4076
            c.lblSelectPluginToDisable.setText(translate("_Select_the_plugins_that_you_want_to_disable_and_click_the_continue_button"));
4077
            c.lblClickContinue.setText(translate("_You_can_click_on_continue_button_directly_if_you_dont_want_to_disable_any_plugins"));
4078
            c.lblClickClose.setText(translate("_Or_click_the_close_button_to_close_the_application"));
4079
            c.buttonClose.setText(translate("_Close"));
4080
            c.buttonContinue.setText(translate("_Continue"));
4081
        }
4082

    
4083
        private String translate(String msg) {
4084
            return PluginServices.getText(this, msg);
4085
        }
4086

    
4087
        private void doClose() {
4088
            this.action = CLOSE;
4089
            this.setVisible(false);
4090
        }
4091

    
4092
        private void doContinue() {
4093
            this.action = CONTINUE;
4094
            this.setVisible(false);
4095
        }
4096

    
4097
        public int getAction() {
4098
            return this.action;
4099
        }
4100

    
4101
        public List<String> getPluginNamesToDisable() {
4102
            if (this.action == CLOSE) {
4103
                return null;
4104
            }
4105
            Object[] selecteds = null;
4106
            selecteds = (Object[]) this.contents.pluginList.getSelectedValues();
4107
            if (selecteds == null || selecteds.length < 1) {
4108
                return null;
4109
            }
4110
            List<String> values = new ArrayList<String>();
4111
            for (int i = 0; i < selecteds.length; i++) {
4112
                values.add(((Item) selecteds[i]).getCode());
4113
            }
4114
            return values;
4115
        }
4116
    }
4117

    
4118
    private void initializeIdentityManagement(File pluginsFolder) {
4119
        File identityManagementConfigFile = null;
4120
        PluginServices plugin = null;
4121
        Iterator<Entry<String, PluginConfig>> it = pluginsConfig.entrySet().iterator();
4122
        while (it.hasNext()) {
4123
            Entry<String, PluginConfig> entry = it.next();
4124
            File pluginFolder = new File(pluginsFolder, entry.getKey());
4125
            File f = new File(pluginFolder, "identity-management.ini");
4126
            if (f.exists()) {
4127
                if (identityManagementConfigFile != null) {
4128
                    logger.warn("Too many identity-managemnt plugins. Disable all.");
4129
                } else {
4130
                    identityManagementConfigFile = f;
4131
                    plugin = PluginServices.getPluginServices(entry.getKey());
4132
                }
4133
            }
4134
        }
4135
        if (identityManagementConfigFile == null || plugin == null) {
4136
            return;
4137
        }
4138
        if (!identityManagementConfigFile.canRead()) {
4139
            return;
4140
        }
4141
        PropertiesConfiguration identityManagementConfig = null;
4142
        try {
4143
            identityManagementConfig = new PropertiesConfiguration(identityManagementConfigFile);
4144
        } catch (Exception ex) {
4145
            logger.warn("Can't open identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.", ex);
4146
            return;
4147
        }
4148
        String identityManagerClassName = identityManagementConfig.getString("IdentityManager", null);
4149
        String identityManagementInitializerClassName = identityManagementConfig.getString("IdentityManagementInitializer", null);
4150
        try {
4151
            if (identityManagerClassName != null) {
4152
                Class identityManagerClass = plugin.getClassLoader().loadClass(identityManagerClassName);
4153
                ToolsLocator.registerIdentityManager(identityManagerClass);
4154
            } else {
4155
                logger.info("Entry IdentityManager not found in identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.");
4156
            }
4157

    
4158
            if (identityManagementInitializerClassName != null) {
4159
                Class identityManagerInitializerClass = plugin.getClassLoader().loadClass(identityManagementInitializerClassName);
4160
                Runnable identityManagerInitializer = (Runnable) identityManagerInitializerClass.newInstance();
4161
                identityManagerInitializer.run();
4162
            } else {
4163
                logger.info("Entry IdentityManagementInitializer not found in identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.");
4164
            }
4165

    
4166
        } catch (Exception ex) {
4167
            logger.warn("Can't initialize the identity manager from '" + identityManagementConfigFile.getAbsolutePath() + ".", ex);
4168
            return;
4169
        }
4170
        logger.info("Loaded an identity manager from plugin '" + plugin.getPluginName() + ".");
4171
    }
4172

    
4173
}