Statistics
| Revision:

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

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.WindowAdapter;
36
import java.awt.event.WindowEvent;
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.prefs.Preferences;
79

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

    
91

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

    
111
import org.gvsig.andami.actioninfo.ActionInfo;
112
import org.gvsig.andami.actioninfo.ActionInfoManager;
113
import org.gvsig.andami.config.generate.Andami;
114
import org.gvsig.andami.config.generate.AndamiConfig;
115
import org.gvsig.andami.config.generate.Plugin;
116
import org.gvsig.andami.impl.DefaultArguments;
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.InstallWizardPanel;
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
 */
202
public class Launcher {
203

    
204
    private static Arguments arguments;
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(final String[] args) throws Exception {
382
        arguments = new DefaultArguments(args);
383

    
384
        final Launcher launcher = getInstance();
385
        try {
386
            if (arguments.contains("install")) {
387
                launcher.doInstall(args);
388
            } else {
389
                launcher.doMain(args);
390
            }
391
        } catch (Exception e) {
392
            logger.error("excepcion al arrancar", e);
393
            System.exit(-1);
394
        }
395
    }
396

    
397
    protected void downloadExtensions(String extDir) {
398
        // do nothing
399
    }
400

    
401
    public static class LaunchException extends ListBaseException {
402

    
403
        private static final long serialVersionUID = 4541192746962684705L;
404

    
405
        public LaunchException() {
406
            super("Errors in initialization of application.",
407
                    "_errors_in_initialization_of_application",
408
                    serialVersionUID);
409
        }
410

    
411
    }
412

    
413
    protected void addError(Throwable ex) {
414
        if (launcherrors == null) {
415
            launcherrors = new LaunchException();
416
        }
417
        launcherrors.add(ex);
418
    }
419

    
420
    protected void addError(String msg, Throwable cause) {
421
        logger.error(msg, cause);
422
        this.addError(new RuntimeException(msg, cause));
423
    }
424

    
425
    protected void addError(String msg) {
426
        this.addError(msg, null);
427
    }
428

    
429
    private String translate(String msg) {
430
        return PluginServices.getText(Launcher.class, msg);
431
    }
432

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

    
447
    public static Arguments getArguments() {
448
        return arguments;
449
    }
450

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

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

    
460
        initializeApp(args, null);
461

    
462
        // Solucionamos el problema de permisos que se produc?do con Java
463
        // Web Start con este codigo.
464
        Policy.setPolicy(new Policy() {
465

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

    
472
            public void refresh() {
473
            }
474
        });
475

    
476
        new DefaultLibrariesInitializer().fullInitialize(true);
477

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
693
        splashWindow.close();
694

    
695
        frame.setCursor(Cursor.DEFAULT_CURSOR);
696

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

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

    
708
    }
709

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

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

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

    
739
    }
740

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

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

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

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

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

    
788
    /**
789
     * @param args
790
     * @throws IOException
791
     * @throws ConfigurationException
792
     */
793
    private void initializeApp(String[] args, String applicationClasifier) throws IOException, ConfigurationException {
794
        if (args.length < 1) {
795
            appName = "gvSIG"; // Nombre de aplicacion por defecto es "gvSIG"
796
        } else {
797
            appName = args[0];
798
        }
799
        // Hacemos visibles los argumentos como una propiedad est?tica
800
        // de plugin services para quien lo quiera usar (por ejemplo, para
801
        // cargar un proyecto por l?nea de comandos)
802
        PluginServices.setArguments(args);
803

    
804
        getOrCreateConfigFolder();
805
        configureLogging(appName, applicationClasifier);
806
        if (!validJVM()) {
807
            logger.error("Not a valid JRE. Exit application.");
808
            System.exit(-1);
809
        }
810

    
811
        ToolsLocator.registerDefaultToolsLibraries();
812

    
813
        ToolsLocator.getFoldersManager().cleanTemporaryFiles();
814

    
815
        if (args.length < 2) {
816
            loadAndamiConfig("gvSIG/extensiones"); // Valor por defecto
817
        } else {
818
            loadAndamiConfig(args[1]);
819
        }
820

    
821
        configureLocales();
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 %r %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
    public static String getApplicationName() {
902
        return appName;
903
    }
904

    
905
    private class NotificationAppender extends AppenderSkeleton {
906

    
907
        @Override
908
        protected void append(LoggingEvent event) {
909
            if (event.getLevel() == org.apache.log4j.Level.ERROR
910
                    || event.getLevel() == org.apache.log4j.Level.FATAL) {
911

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

    
927
        @Override
928
        public void close() {
929
            // TODO Auto-generated method stub
930

    
931
        }
932

    
933
        @Override
934
        public boolean requiresLayout() {
935
            // TODO Auto-generated method stub
936
            return false;
937
        }
938

    
939
    }
940

    
941
    /**
942
     * Return the directory applicaction is installed.
943
     */
944
    public static String getApplicationDirectory() {
945
        return getApplicationFolder().getAbsolutePath();
946
    }
947

    
948
    public static File getApplicationFolder() {
949
        // TODO: check if there is a better way to handle this
950
        return new File(System.getProperty("user.dir"));
951
    }
952

    
953
    private void registerIcons() {
954
        IconTheme theme = PluginServices.getIconTheme();
955
        ClassLoader loader = Launcher.class.getClassLoader();
956

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

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

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

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

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

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

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

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

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

    
1079
        System.getProperties().put("http.proxyHost", host);
1080
        System.getProperties().put("http.proxyPort", port);
1081

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

    
1089
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
1090
        } else {
1091
            Authenticator.setDefault(new ProxyAuth("", ""));
1092
        }
1093
    }
1094

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

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

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

    
1167
    private void loadPluginsPersistence() throws ConfigurationException {
1168
        XMLEntity entity = persistenceFromXML();
1169

    
1170
        for (int i = 0; i < entity.getChildrenCount(); i++) {
1171
            XMLEntity plugin = entity.getChild(i);
1172
            String pName = plugin
1173
                    .getStringProperty("com.iver.andami.pluginName");
1174

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

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

    
1197
        XMLEntity entity = new XMLEntity();
1198

    
1199
        while (i.hasNext()) {
1200
            String pName = i.next();
1201
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1202
            XMLEntity ent = ps.getPersistentXML();
1203

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

    
1225
    private void installPluginsLabels() {
1226
        Iterator<String> i = pluginsConfig.keySet().iterator();
1227

    
1228
        while (i.hasNext()) {
1229
            String name = i.next();
1230
            PluginConfig pc = pluginsConfig.get(name);
1231
            PluginServices ps = (PluginServices) pluginsServices.get(name);
1232

    
1233
            LabelSet[] ls = pc.getLabelSet();
1234

    
1235
            for (int j = 0; j < ls.length; j++) {
1236
                PluginClassLoader loader = ps.getClassLoader();
1237

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

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

    
1263
    private void fixSkin(SkinExtension skinExtension,
1264
            PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
1265
        // now insert the skin selected.
1266
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
1267
                // MDIManagerFactory.setSkinExtension(se,
1268
        // ps.getClassLoader());
1269

    
1270
        Class<? extends IExtension> skinClass;
1271

    
1272
        try {
1273
            skinClass = (Class<? extends IExtension>) pluginClassLoader
1274
                    .loadClass(skinExtension.getClassName());
1275

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

    
1301
    }
1302

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

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

    
1326
            if (pc.getExtensions().getSkinExtension() != null) {
1327
                                // if (MDIManagerFactory.getSkinExtension() != null) {
1328
                // logger.warn(Messages.getString(
1329
                // "Launcher.Dos_skin_extension"));
1330
                // }
1331

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

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

    
1364
    }
1365

    
1366
    private static void frameIcon(Theme theme) {
1367
        Iterator<String> i = pluginsConfig.keySet().iterator();
1368

    
1369
        while (i.hasNext()) {
1370
            String pName = i.next();
1371
            PluginConfig pc = pluginsConfig.get(pName);
1372
            if (pc.getIcon() != null) {
1373
                if (theme.getIcon() != null) {
1374
                    frame.setIconImage(theme.getIcon().getImage());
1375
                } else {
1376

    
1377
                    ImageIcon icon = PluginServices.getIconTheme().get(
1378
                            pc.getIcon().getSrc());
1379
                    frame.setIconImage(icon.getImage());
1380

    
1381
                }
1382
                if (theme.getName() != null) {
1383
                    frame.setTitlePrefix(theme.getName());
1384
                } else {
1385
                    frame.setTitlePrefix(pc.getIcon().getText());
1386
                }
1387
                if (theme.getBackgroundImage() != null) {
1388

    
1389
                    PluginServices.getMDIManager().setBackgroundImage(
1390
                            theme.getBackgroundImage(), theme.getTypeDesktop());
1391
                }
1392
            }
1393
        }
1394
    }
1395

    
1396
    private void initializeExtensions() {
1397

    
1398
        List<ClassLoader> classLoaders = new ArrayList<ClassLoader>(
1399
                pluginsOrdered.size());
1400
        classLoaders.add(getClass().getClassLoader());
1401
        Iterator<String> iter = pluginsOrdered.iterator();
1402

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

    
1427
            Extension[] exts = pc.getExtensions().getExtension();
1428

    
1429
            TreeSet<Extension> orderedExtensions = new TreeSet<Extension>(
1430
                    new ExtensionComparator());
1431

    
1432
            for (int j = 0; j < exts.length; j++) {
1433
                if (!exts[j].getActive()) {
1434
                    continue;
1435
                }
1436

    
1437
                if (orderedExtensions.contains(exts[j])) {
1438
                    logger.warn("Two extensions with the same priority ("
1439
                            + exts[j].getClassName() + ")");
1440
                }
1441

    
1442
                orderedExtensions.add(exts[j]);
1443
            }
1444

    
1445
            Iterator<Extension> e = orderedExtensions.iterator();
1446

    
1447
            logger.info("Initializing extensions of plugin " + pName + ": ");
1448
            while (e.hasNext()) {
1449
                Extension extension = e.next();
1450
                org.gvsig.andami.plugins.IExtension extensionInstance;
1451

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

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

    
1484
                    extensionInstance.initialize();
1485
                    extensions.add(extensionInstance);
1486

    
1487
                } catch (NoClassDefFoundError e1) {
1488
                    this.addError("Can't find class extension ("
1489
                            + extension.getClassName() + ")", e1);
1490
                } catch (Throwable e1) {
1491
                    this.addError("Can't initialize extension '"
1492
                            + extension.getClassName() + "'.", e1);
1493
                }
1494
            }
1495
        }
1496
    }
1497

    
1498
    private void postInitializeExtensions() {
1499
        logger.info("PostInitializing extensions: ");
1500

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

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

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

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

    
1570
                }
1571
                Enumeration<ToolBar> toolBars = extension.enumerateToolBar();
1572
                while (toolBars.hasMoreElements()) {
1573
                    ToolBar toolBar = toolBars.nextElement();
1574

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

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

    
1628
    @SuppressWarnings("unchecked")
1629
    private void registerActions() {
1630
        logger.info("registerActions");
1631

    
1632
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1633
        Iterator<String> it = pluginsConfig.keySet().iterator();
1634

    
1635
        while (it.hasNext()) {
1636
            String pluginName = it.next();
1637
            PluginConfig pluginConfig = pluginsConfig.get(pluginName);
1638
            PluginServices pluginService = pluginsServices.get(pluginName);
1639
            PluginClassLoader loader = pluginService.getClassLoader();
1640

    
1641
            logger.info("registerActions of plugin '" + pluginName + "'.");
1642

    
1643
            Extensions extensionConfig = pluginConfig.getExtensions();
1644

    
1645
            Enumeration<SkinExtensionType> extensiones = extensionConfig.enumerateExtension();
1646
            registerActionOfExtensions(actionManager, extensiones, loader);
1647

    
1648
            Enumeration<SkinExtensionType> skinSxtensiones = extensionConfig.enumerateSkinExtension();
1649
            registerActionOfExtensions(actionManager, skinSxtensiones, loader);
1650

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

    
1678
        }
1679
    }
1680

    
1681
    private TreeSet<SortableMenu> getOrderedMenus() {
1682

    
1683
        TreeSet<SortableMenu> orderedMenus = new TreeSet<SortableMenu>(
1684
                new MenuComparator());
1685

    
1686
        Iterator<String> i = pluginsConfig.keySet().iterator();
1687

    
1688
        while (i.hasNext()) {
1689
            String pName = i.next();
1690
            try {
1691
                PluginServices ps = pluginsServices.get(pName);
1692
                PluginConfig pc = pluginsConfig.get(pName);
1693

    
1694
                Extension[] exts = pc.getExtensions().getExtension();
1695

    
1696
                for (int j = 0; j < exts.length; j++) {
1697
                    if (!exts[j].getActive()) {
1698
                        continue;
1699
                    }
1700

    
1701
                    Menu[] menus = exts[j].getMenu();
1702

    
1703
                    for (int k = 0; k < menus.length; k++) {
1704
                        SortableMenu sm = new SortableMenu(ps.getClassLoader(),
1705
                                exts[j], menus[k]);
1706

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

    
1716
                        orderedMenus.add(sm);
1717
                    }
1718
                }
1719

    
1720
                // Se instalan las extensiones de MDI
1721
                SkinExtension[] skinExts = pc.getExtensions()
1722
                        .getSkinExtension();
1723
                for (int j = 0; j < skinExts.length; j++) {
1724

    
1725
                    if (skinExts[j] != null) {
1726
                        Menu[] menu = skinExts[j].getMenu();
1727

    
1728
                        for (int k = 0; k < menu.length; k++) {
1729
                            SortableMenu sm = new SortableMenu(ps
1730
                                    .getClassLoader(), skinExts[j], menu[k]);
1731

    
1732
                            if (orderedMenus.contains(sm)) {
1733
                                this
1734
                                        .addError(Messages
1735
                                                .getString("Launcher.Two_menus_with_the_same_position")
1736
                                                + skinExts[j].getClassName());
1737
                            }
1738

    
1739
                            orderedMenus.add(sm);
1740
                        }
1741
                    }
1742
                }
1743

    
1744
            } catch (Throwable e) {
1745
                addError("Error initializing menus of plugin '" + pName + "'",
1746
                        e);
1747
            }
1748

    
1749
        }
1750

    
1751
        return orderedMenus;
1752
    }
1753

    
1754
    private void installPluginsMenus() {
1755
        logger.info("installPluginsMenus");
1756

    
1757
        TreeSet<SortableMenu> orderedMenus = getOrderedMenus();
1758

    
1759
        // Se itera por los menus ordenados
1760
        Iterator<SortableMenu> e = orderedMenus.iterator();
1761

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

    
1777
    public class PluginMenuItem {
1778

    
1779
        private Menu menu;
1780
        private PluginClassLoader loader;
1781
        private SkinExtensionType extension;
1782

    
1783
        PluginMenuItem(PluginClassLoader loader,
1784
                SkinExtensionType extension, Menu menu) {
1785
            this.menu = menu;
1786
            this.loader = loader;
1787
            this.extension = extension;
1788
        }
1789

    
1790
        public PluginServices getPlugin() {
1791
            String pluginName = loader.getPluginName();
1792
            return PluginServices.getPluginServices(pluginName);
1793
        }
1794

    
1795
        public String getExtensionName() {
1796
            return this.extension.getClassName();
1797
        }
1798

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

    
1809
        public String getText() {
1810
            return this.menu.getText();
1811
        }
1812

    
1813
        public long getPosition() {
1814
            return this.menu.getPosition();
1815
        }
1816

    
1817
        public String getName() {
1818
            return this.menu.getName();
1819
        }
1820

    
1821
        public boolean isParent() {
1822
            return menu.getIs_separator();
1823
        }
1824

    
1825
        public String getPluginName() {
1826
            return this.loader.getPluginName();
1827
        }
1828

    
1829
        public ActionInfo getAction() {
1830
            ActionInfoManager manager = PluginsLocator.getActionInfoManager();
1831
            return manager.getAction(this.menu.getName());
1832
        }
1833
    }
1834

    
1835
    public List<PluginMenuItem> getPluginMenuItems() {
1836
        List<PluginMenuItem> menuItems = new ArrayList<Launcher.PluginMenuItem>();
1837

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

    
1848
    private List<ToolBar> getOrderedToolBars() {
1849
        Map<String, ToolBar> toolbars = new HashMap<>();
1850

    
1851
        Iterator<String> pluginNames = pluginsConfig.keySet().iterator();
1852
        while (pluginNames.hasNext()) {
1853
            String pluginName = pluginNames.next();
1854
            String extensionName = "unknow";
1855
            try {
1856
                PluginConfig pc = pluginsConfig.get(pluginName);
1857
                Extension[] extensions = pc.getExtensions().getExtension();
1858
                for (Extension extension : extensions) {
1859
                    extensionName = extension.getClassName();
1860
                    ToolBar[] extensionToolbars = extension.getToolBar();
1861
                    for (ToolBar toolbar : extensionToolbars) {
1862
                        ToolBar x = toolbars.get(toolbar.getName());
1863
                        if ( x!=null ) {
1864
                            if( !x.hasPosition() && toolbar.hasPosition() ) {
1865
                                toolbars.put(toolbar.getName(), toolbar);
1866
                            }
1867
                        } else {
1868
                            toolbars.put(toolbar.getName(), toolbar);
1869
                        }
1870
                    }
1871
                }
1872
            } catch (Exception ex) {
1873
                addError("Can't process tool-bars of extension '"+extensionName+"'.", ex);
1874
            }
1875
        }
1876
        for (Entry<String, ToolBar> entrySet : toolbars.entrySet()) {
1877
            ToolBar toolBar = entrySet.getValue();
1878
            if( toolBar.hasPosition() && toolBar.getPosition()<100 ) {
1879
                toolBar.setPosition( toolBar.getPosition()+11000);
1880
            }
1881
        }
1882
        List<ToolBar> toolBarsList = new ArrayList<>(toolbars.values());
1883
        Collections.sort(toolBarsList, new Comparator<ToolBar>() {
1884

    
1885
            @Override
1886
            public int compare(ToolBar o1, ToolBar o2) {
1887
                return Integer.compare(o1.getPosition(), o2.getPosition());
1888
            }
1889
        });
1890
        return toolBarsList;
1891
    }
1892

    
1893
    /**
1894
     * Installs the menus, toolbars, actiontools, selectable toolbars and
1895
     * combos. The order in which they are shown is determined here.
1896
     */
1897
    private void installPluginsControls() {
1898
        logger.info("installPluginsControls (toolbars)");
1899
        installPluginsControlsToToolsbar();
1900
        installPluginsControlsToStatusbar();
1901
    }
1902

    
1903
    private void installPluginsControlsToToolsbar() {
1904

    
1905
        Map<String,List<SortableTool>> toolsByToolbar = new HashMap<>();
1906
        // A?ade primero las toolbars ordenadas para garantizar el orden de estas
1907
        // Y inicializa las listas del Map.
1908
        for( ToolBar toolbar : getOrderedToolBars() ) {
1909
            frame.addToolBar(toolbar.getName(), toolbar.getDescription(), toolbar.getPosition());
1910
            ArrayList<SortableTool> tools = new ArrayList<>();
1911
            toolsByToolbar.put(toolbar.getName(),tools);
1912
        }
1913
        for( Entry<String, PluginConfig> entry : pluginsConfig.entrySet() ) {
1914
            String pluginName = entry.getKey();
1915
            PluginConfig pluginConfig = entry.getValue();
1916
            PluginServices plugin = pluginsServices.get(pluginName);
1917
            PluginClassLoader loader = plugin.getClassLoader();
1918
            Extension[] pluginExtensions = pluginConfig.getExtensions().getExtension();
1919
            for( Extension pluginExtension : pluginExtensions ) {
1920
                ToolBar[] pluginToolbars = pluginExtension.getToolBar();
1921
                for( ToolBar pluginToolbar : pluginToolbars ) {
1922
                    ActionTool[] actionTools = pluginToolbar.getActionTool();
1923
                    for( ActionTool actionTool : actionTools ) {
1924
                        List<SortableTool> toolbar = toolsByToolbar.get(pluginToolbar.getName());
1925
                        toolbar.add(new SortableTool(loader, pluginExtension, pluginToolbar, actionTool));
1926
                    }
1927
                    SelectableTool[] selectableTools = pluginToolbar.getSelectableTool();
1928
                    for( SelectableTool selectableTool : selectableTools ) {
1929
                        List<SortableTool> toolbar = toolsByToolbar.get(pluginToolbar.getName());
1930
                        toolbar.add(new SortableTool(loader, pluginExtension, pluginToolbar, selectableTool));
1931
                    }
1932
                }
1933
            }
1934
        }
1935
        for( Entry<String, List<SortableTool>> entry : toolsByToolbar.entrySet() ) {
1936
            String toolbarName = entry.getKey();
1937
            List<SortableTool> tools = entry.getValue();
1938
            Collections.sort(tools, new Comparator<SortableTool>() {
1939
                @Override
1940
                public int compare(SortableTool o1, SortableTool o2) {
1941
                    return Long.compare(o1.getPosition(), o2.getPosition());
1942
                }
1943
            });
1944

    
1945
            for( SortableTool tool : tools ) {
1946
                try {
1947
                    if (tool.actiontool != null) {
1948
                        frame.addTool(tool.loader, tool.extension,
1949
                            tool.toolbar, tool.actiontool
1950
                        );
1951
                    } else {
1952
                        frame.addTool(tool.loader, tool.extension,
1953
                            tool.toolbar, tool.selectabletool
1954
                        );
1955
                    }
1956
                } catch (Exception ex) {
1957
                }
1958
            }
1959
        }
1960
    }
1961

    
1962
    private void installPluginsControlsToStatusbar() {
1963
        Iterator<String> pluginNames = pluginsConfig.keySet().iterator();
1964

    
1965
        Map<Extension, PluginServices> extensionPluginServices = new HashMap<Extension, PluginServices>();
1966
        Set<Extension> orderedExtensions = new TreeSet<Extension>(new ExtensionComparator());
1967

    
1968
        while (pluginNames.hasNext()) {
1969
            String pluginName = pluginNames.next();
1970
            try {
1971
                PluginConfig pc = pluginsConfig.get(pluginName);
1972
                PluginServices ps = pluginsServices.get(pluginName);
1973

    
1974
                Extension[] exts = pc.getExtensions().getExtension();
1975

    
1976
                for (int j = 0; j < exts.length; j++) {
1977
                    String cname = "unknow";
1978
                    try {
1979
                        cname = exts[j].getClassName();
1980
                        if (exts[j].getActive() && !cname.equals(LibraryExtension.class.getName())) {
1981
                            if (orderedExtensions.contains(exts[j])) {
1982
                                this.addError(
1983
                                    Messages.getString("Launcher.Two_extensions_with_the_same_priority")
1984
                                    + cname
1985
                                );
1986
                            }
1987

    
1988
                            orderedExtensions.add(exts[j]);
1989
                            extensionPluginServices.put(exts[j], ps);
1990
                        }
1991
                    } catch (Throwable e) {
1992
                        addError("Error initializing controls of plugin '"
1993
                                + pluginName + "' extension '" + cname + "'", e);
1994
                    }
1995
                }
1996
            } catch (Throwable e) {
1997
                addError("Error initializing controls of plugin '" + pluginName
1998
                        + "'", e);
1999
            }
2000
        }
2001

    
2002
        Iterator<Extension> e = orderedExtensions.iterator();
2003

    
2004
        // load the combo-scales and combo-buttons for the status bar
2005
        while (e.hasNext()) {
2006
            Extension ext = e.next();
2007
            String extName = "unknow";
2008
            try {
2009
                extName = ext.getClassName();
2010

    
2011
                // get controls for statusBar
2012
                PluginServices ps = extensionPluginServices.get(ext);
2013
                PluginClassLoader loader = ps.getClassLoader();
2014

    
2015
                ComboScale[] comboScaleArray = ext.getComboScale();
2016
                for (int k = 0; k < comboScaleArray.length; k++) {
2017
                    org.gvsig.gui.beans.controls.comboscale.ComboScale combo = new org.gvsig.gui.beans.controls.comboscale.ComboScale();
2018
                    String label = comboScaleArray[k].getLabel();
2019
                    if (label != null) {
2020
                        combo.setLabel(label);
2021
                    }
2022
                    String name = comboScaleArray[k].getName();
2023
                    if (name != null) {
2024
                        combo.setName(name);
2025
                    }
2026
                    String[] elementsString = ((String) comboScaleArray[k]
2027
                            .getElements()).split(";");
2028
                    long[] elements = new long[elementsString.length];
2029
                    for (int currentElem = 0; currentElem < elementsString.length; currentElem++) {
2030
                        try {
2031
                            elements[currentElem] = Long
2032
                                    .parseLong(elementsString[currentElem]);
2033
                        } catch (NumberFormatException nfex1) {
2034
                            this
2035
                                    .addError(ext.getClassName()
2036
                                            + " -- "
2037
                                            + Messages
2038
                                            .getString("error_parsing_comboscale_elements"));
2039
                            elements[currentElem] = 0;
2040
                        }
2041
                    }
2042
                    combo.setItems(elements);
2043
                    try {
2044
                        long value = Long.parseLong((String) comboScaleArray[k]
2045
                                .getValue());
2046
                        combo.setScale(value);
2047
                    } catch (NumberFormatException nfex2) {
2048
                        this
2049
                                .addError(ext.getClassName()
2050
                                        + " -- "
2051
                                        + Messages
2052
                                        .getString("error_parsing_comboscale_value"));
2053
                    }
2054
                    try {
2055
                        frame.addStatusBarControl(loader.loadClass(ext
2056
                                .getClassName()), combo);
2057
                    } catch (ClassNotFoundException e1) {
2058
                        this
2059
                                .addError(
2060
                                        Messages
2061
                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
2062
                                        e1);
2063
                    }
2064
                }
2065

    
2066
                ComboButton[] comboButtonArray = ext.getComboButton();
2067
                for (int k = 0; k < comboButtonArray.length; k++) {
2068
                    ComboButtonElement[] elementList = comboButtonArray[k]
2069
                            .getComboButtonElement();
2070
                    org.gvsig.gui.beans.controls.combobutton.ComboButton combo = new org.gvsig.gui.beans.controls.combobutton.ComboButton();
2071
                    String name = comboButtonArray[k].getName();
2072
                    if (name != null) {
2073
                        combo.setName(name);
2074
                    }
2075
                    for (int currentElement = 0; currentElement < elementList.length; currentElement++) {
2076
                        ComboButtonElement element = elementList[currentElement];
2077
                        ImageIcon icon;
2078
                        URL iconLocation = loader
2079
                                .getResource(element.getIcon());
2080
                        if (iconLocation == null) {
2081
                            this.addError(Messages.getString("Icon_not_found_")
2082
                                    + element.getIcon());
2083
                        } else {
2084
                            icon = new ImageIcon(iconLocation);
2085
                            JButton button = new JButton(icon);
2086
                            combo.addButton(button);
2087
                            button.setActionCommand(element.getActionCommand());
2088
                        }
2089
                    }
2090
                    try {
2091
                        frame.addStatusBarControl(loader.loadClass(ext
2092
                                .getClassName()), combo);
2093
                    } catch (ClassNotFoundException e1) {
2094
                        this
2095
                                .addError(
2096
                                        Messages
2097
                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
2098
                                        e1);
2099
                    }
2100
                }
2101
            } catch (Throwable e2) {
2102
                addError(
2103
                        "Error initializing tools and status bars of extension '"
2104
                        + extName + "'", e2);
2105
            }
2106
        }
2107

    
2108
    }
2109

    
2110
    /**
2111
     * Adds new plugins to the the andami-config file.
2112
     */
2113
    private void updateAndamiConfig() {
2114
        Set<String> olds = new HashSet<String>();
2115

    
2116
        Plugin[] plugins = andamiConfig.getPlugin();
2117

    
2118
        for (int i = 0; i < plugins.length; i++) {
2119
            olds.add(plugins[i].getName());
2120
        }
2121

    
2122
        Iterator<PluginServices> i = pluginsServices.values().iterator();
2123

    
2124
        while (i.hasNext()) {
2125
            PluginServices ps = i.next();
2126

    
2127
            if (!olds.contains(ps.getPluginName())) {
2128
                Plugin p = new Plugin();
2129
                p.setName(ps.getPluginName());
2130
                p.setUpdate(false);
2131

    
2132
                andamiConfig.addPlugin(p);
2133
            }
2134
        }
2135
    }
2136

    
2137
    private URL[] getPluginClasspathURLs(PluginConfig pluginConfig) {
2138
        URL[] urls = null;
2139

    
2140
        String libfolderPath = pluginConfig.getLibraries().getLibraryDir();
2141
        File libFolderFile = new File(pluginConfig.getPluginFolder(), libfolderPath);
2142

    
2143
        File[] files = libFolderFile.listFiles(new FileFilter() {
2144

    
2145
            public boolean accept(File pathname) {
2146
                return (pathname.getName().toUpperCase().endsWith(".JAR")
2147
                        || pathname.getName().toUpperCase().endsWith(".ZIP"));
2148
            }
2149
        });
2150
        if (files == null) {
2151
            urls = new URL[0];
2152
        } else {
2153
            urls = new URL[files.length];
2154
            for (int j = 0; j < files.length; j++) {
2155
                try {
2156
                    urls[j] = new URL("file:" + files[j]);
2157
                } catch (MalformedURLException e) {
2158
                    logger.warn("Can't add file '" + files[j] + "' to the classpath of plugin '" + pluginConfig.getPluginName() + "'.");
2159
                }
2160
            }
2161
        }
2162
        return urls;
2163
    }
2164

    
2165
    private static class OrderedPlugins extends ArrayList<String> {
2166

    
2167
        private List<String> problems = new ArrayList<String>();
2168
        private int retries = 0;
2169
        private PluginsConfig pluginsConfig = null;
2170
        private List<String> deprcatedPluginNames = null;
2171

    
2172
        OrderedPlugins(PluginsConfig pluginsConfig, List<String>deprcatedPluginNames) {
2173
            super();
2174
            this.pluginsConfig = pluginsConfig;
2175
            this.deprcatedPluginNames = deprcatedPluginNames;
2176
            List<String> pluginNames = new ArrayList<String>();
2177
            for (String pluginName : pluginsConfig.keySet()) {
2178
                pluginNames.add(pluginName);
2179
            }
2180
            Collections.sort(pluginNames);
2181
            for (String pluginName : pluginNames) {
2182
                this.add(pluginName);
2183
            }
2184
        }
2185

    
2186
        public List<String> getProblems() {
2187
            return this.problems;
2188
        }
2189

    
2190
        private void addProblem(String msg) {
2191
           this.problems.add(msg);
2192
        }
2193

    
2194
        public boolean add(String pluginName) {
2195
            return this.add(pluginName,new ArrayList<String>());
2196
        }
2197

    
2198
        private boolean add(String pluginName, List<String>processing) {
2199
            pluginName = this.pluginsConfig.getMainKey(pluginName);
2200
            if( this.contains(pluginName) ) {
2201
                return true;
2202
            }
2203
            if( processing.contains(pluginName) ) {
2204
                this.addProblem("Dependencias ciclicas procesando '"+pluginName+"'.");
2205
                return true;
2206
            }
2207
            PluginConfig pluginConfig = this.pluginsConfig.get(pluginName);
2208
            Depends[] dependencies = pluginConfig.getDepends();
2209
            if( dependencies.length==0 ) {
2210
               super.add(pluginName);
2211
               return true;
2212
            }
2213
            if( this.retries > 100 ) {
2214
               this.addProblem("Posible dependencias ciclicas procesando '"+pluginName+"'." );
2215
               return false;
2216
            }
2217
            processing.add(pluginName);
2218
            boolean dependenciesAvailables = true;
2219
            for (Depends dependency : dependencies) {
2220
                String dependencyName = dependency.getPluginName();
2221
                if (deprcatedPluginNames.contains(dependencyName)) {
2222
                    this.addProblem("Plugin '" + pluginName + "' use a deprecated plugin name '" + dependencyName + "' as dependency. Must use '" + pluginsConfig.getMainKey(dependencyName) + "'.");
2223
                }
2224
                PluginConfig dependencyConfig = this.pluginsConfig.get(dependencyName);
2225
                if( dependencyConfig == null) {
2226
                  if( dependency.getOptional() ) {
2227
                    this.addProblem("Plugin '" + pluginName + "', declare an optional dependency '" + dependencyName + "' that not found.");
2228
                    continue;
2229
                  }
2230
                  dependenciesAvailables = false;
2231
                  this.addProblem("Plugin '"+pluginName+"' declara a dependency '"+dependencyName+"' that not found.");
2232
                  continue;
2233
                }
2234
                this.retries++;
2235
                if( ! (this.add(dependencyName, processing)) ) {
2236
                  dependenciesAvailables = false;
2237
                }
2238
                this.retries--;
2239
            }
2240
            if( dependenciesAvailables ) {
2241
                super.add(pluginName);
2242
            } else {
2243
              this.addProblem("Plugin '"+pluginName+"' no disponible, alguna dependencia no resuelta.");
2244
              return false;
2245
            }
2246
            return true;
2247
        }
2248
    }
2249

    
2250
    private void loadPluginServices() {
2251
        OrderedPlugins orderedPlugins = new OrderedPlugins(pluginsConfig, getDeprecatedPluginNames());
2252

    
2253
        if( !orderedPlugins.getProblems().isEmpty() ) {
2254
            for (String problem : orderedPlugins.getProblems()) {
2255
                logger.warn(problem);
2256
            }
2257
        }
2258

    
2259
        for (String pluginName : orderedPlugins) {
2260
            PluginConfig config = pluginsConfig.get(pluginName);
2261

    
2262
            URL[] urls = getPluginClasspathURLs(config);
2263

    
2264
            List<PluginClassLoader> loaders = new ArrayList<PluginClassLoader>();
2265
            for (Depends dependency : config.getDepends()) {
2266
                String dependencyName = dependency.getPluginName();
2267
                PluginServices dependencyPluginService = pluginsServices.get(dependencyName);
2268
                if( dependencyPluginService == null ) {
2269
                    if( dependency.getOptional() ) {
2270
                        logger.info("Procesing plugin '"+pluginName+", optional dependency not found ("+dependencyName+").");
2271
                    } else {
2272
                        logger.warn("Procesing plugin '"+pluginName+", dependency not found ("+dependencyName+").");
2273
                    }
2274
                    continue;
2275
                }
2276
                loaders.add(dependencyPluginService.getClassLoader());
2277
            }
2278
            try {
2279
                PluginClassLoader loader = new PluginClassLoader(
2280
                        urls,
2281
                        config.getPluginFolder().getAbsolutePath(),
2282
                        Launcher.class.getClassLoader(),
2283
                        loaders
2284
                );
2285
                PluginServices ps = new PluginServices(
2286
                        loader,
2287
                        PluginsConfig.getAlternativeNames(config)
2288
                );
2289
                logger.info("Plugin '" + pluginName + "' created");
2290
                pluginsServices.put(ps.getPluginName(), ps);
2291
                pluginsOrdered.add(pluginName);
2292
            } catch (IOException ex) {
2293
                logger.warn("Can't create PluginServices for '" + pluginName + "'.", ex);
2294
            }
2295
        }
2296

    
2297
        // Se eliminan los plugins que no fueron instalados
2298
        List<String> pluginsToRemove = new ArrayList<String>();
2299
        for (String pluginName : pluginsConfig.keySet()) {
2300
            PluginServices pluginService = pluginsServices.get(pluginName);
2301
            if( pluginService == null ) {
2302
                pluginsToRemove.add(pluginName);
2303
            }
2304
        }
2305
        for (String pluginName : pluginsToRemove) {
2306
            logger.warn("Removed plugin "+pluginName+".");
2307
            pluginsConfig.remove(pluginName);
2308
       }
2309
    }
2310

    
2311
    /*
2312
    private void dumpPluginsDependencyInformation() {
2313
        logger.info("Plugin dependency information");
2314
        Iterator<String> i = pluginsConfig.keySet().iterator();
2315
        while (i.hasNext()) {
2316
            String pluginName = i.next();
2317
            PluginConfig config = (PluginConfig) pluginsConfig.get(pluginName);
2318
            logger.info("  Plugin " + pluginName);
2319
            Depends[] dependencies = config.getDepends();
2320
            for (int j = 0; j < dependencies.length; j++) {
2321
                Depends dependency = dependencies[j];
2322
                String dependencyName = dependency.getPluginName();
2323
                logger.info("    Dependency " + dependencyName);
2324
            }
2325
        }
2326
    }
2327
    */
2328
    private void pluginsMessages() {
2329
        Iterator<String> iterator = pluginsOrdered.iterator();
2330
        PluginConfig config;
2331
        PluginServices ps;
2332

    
2333
        while (iterator.hasNext()) {
2334
            String pluginName = iterator.next();
2335
            config = pluginsConfig.get(pluginName);
2336
            ps = pluginsServices.get(pluginName);
2337

    
2338
            if ((config.getResourceBundle() != null)
2339
                    && !config.getResourceBundle().getName().equals("")) {
2340
                // add the locale files associated with the plugin
2341
                org.gvsig.i18n.Messages.addResourceFamily(config
2342
                        .getResourceBundle().getName(), ps.getClassLoader(),
2343
                        pluginName);
2344
                org.gvsig.i18n.Messages.addResourceFamily("i18n." + config
2345
                        .getResourceBundle().getName(), ps.getClassLoader(),
2346
                        pluginName);
2347
            }
2348
        }
2349
    }
2350

    
2351
    static public PluginServices getPluginServices(String name) {
2352
        return (PluginServices) pluginsServices.get(name);
2353
    }
2354

    
2355
    static String getPluginsDir() {
2356
        return andamiConfig.getPluginsDirectory();
2357
    }
2358

    
2359
    static File getPluginFolder(String pluginName) {
2360
        return pluginsConfig.get(pluginName).getPluginFolder();
2361
    }
2362

    
2363
    static void setPluginsDir(String s) {
2364
        andamiConfig.setPluginsDirectory(s);
2365
    }
2366

    
2367
    static MDIFrame getMDIFrame() {
2368
        return frame;
2369
    }
2370

    
2371
    private PluginsConfig loadPluginConfigs() {
2372
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
2373
        List<File> repositoriesFolders = installerManager.getLocalAddonRepositories("plugin");
2374
        for (File repositoryFolder : repositoriesFolders) {
2375
            logger.info("Loading plugins configuration from repository folder " + repositoryFolder.getAbsolutePath() + ".");
2376

    
2377
            if (!repositoryFolder.exists()) {
2378
                logger.warn("Plugins repository folder not found '" + repositoryFolder.getAbsolutePath() + "'.");
2379
                continue;
2380
            }
2381

    
2382
            File[] pluginsFolders = repositoryFolder.listFiles();
2383
            if (pluginsFolders.length == 0) {
2384
                logger.info("Plugins repository folder is empty '" + repositoryFolder.getAbsolutePath() + "'.");
2385
                continue;
2386
            }
2387

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

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

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

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

    
2423
                }
2424
            }
2425
        }
2426
        return pluginsConfig;
2427
    }
2428

    
2429
    private static Locale getLocale(String language, String country,
2430
            String variant) {
2431
        if (variant != null) {
2432
            return new Locale(language, country, variant);
2433
        } else if (country != null) {
2434
            return new Locale(language, country);
2435
        } else if (language != null) {
2436
            return new Locale(language);
2437
        } else {
2438
            return new Locale("es");
2439
        }
2440
    }
2441

    
2442
    private static void andamiConfigToXML(String file) throws IOException,
2443
            MarshalException, ValidationException {
2444
                // write on a temporary file in order to not destroy current file if
2445
        // there is some problem while marshaling
2446
        File tmpFile = new File(file + "-"
2447
                + DateTime.getCurrentDate().getTime());
2448
        File xml = new File(file);
2449
        File parent = xml.getParentFile();
2450
        parent.mkdirs();
2451

    
2452
        BufferedOutputStream os = new BufferedOutputStream(
2453
                new FileOutputStream(tmpFile));
2454
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
2455
        andamiConfig.marshal(writer);
2456
        writer.close();
2457

    
2458
                // if marshaling process finished correctly, move the file to the
2459
        // correct one
2460
        xml.delete();
2461
        if (!tmpFile.renameTo(xml)) {
2462
            // if rename was not succesful, try copying it
2463
            FileChannel sourceChannel = new FileInputStream(tmpFile)
2464
                    .getChannel();
2465
            FileChannel destinationChannel = new FileOutputStream(xml)
2466
                    .getChannel();
2467
            sourceChannel.transferTo(0, sourceChannel.size(),
2468
                    destinationChannel);
2469
            sourceChannel.close();
2470
            destinationChannel.close();
2471
        }
2472
    }
2473

    
2474
    private static void andamiConfigFromXML(String file)
2475
            throws ConfigurationException {
2476
        File xml = new File(file);
2477

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

    
2510
    private static AndamiConfig getDefaultAndamiConfig() {
2511
        AndamiConfig andamiConfig = new AndamiConfig();
2512

    
2513
        Andami andami = new Andami();
2514
        andami.setUpdate(true);
2515
        andamiConfig.setAndami(andami);
2516
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
2517
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
2518
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
2519

    
2520
        if (System.getProperty("javawebstart.version") != null) // Es java web
2521
        // start)
2522
        {
2523
            andamiConfig
2524
                    .setPluginsDirectory(new File(appHomeDir, "extensiones")
2525
                            .getAbsolutePath());
2526
        } else {
2527
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
2528
                    .getAbsolutePath());
2529
        }
2530

    
2531
        andamiConfig.setPlugin(new Plugin[0]);
2532
        return andamiConfig;
2533
    }
2534

    
2535
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
2536
        File xml = getPluginsPersistenceFile(true);
2537

    
2538
        if (xml.exists()) {
2539
            InputStreamReader reader = null;
2540

    
2541
            try {
2542
                reader = XMLEncodingUtils.getReader(xml);
2543
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2544
                return new XMLEntity(tag);
2545
            } catch (FileNotFoundException e) {
2546
                throw new ConfigurationException(e);
2547
            } catch (MarshalException e) {
2548

    
2549
                                // try to reopen with default encoding (for backward
2550
                // compatibility)
2551
                try {
2552
                    reader = new FileReader(xml);
2553
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2554
                    return new XMLEntity(tag);
2555

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

    
2590
    private static File getPluginsPersistenceFile(boolean read) {
2591
        if (read) {
2592
            File pluginsPersistenceFile = new File(getAppHomeDir(),
2593
                    "plugins-persistence-2_0.xml");
2594
            if (pluginsPersistenceFile.exists()) {
2595
                return pluginsPersistenceFile;
2596
            }
2597
            pluginsPersistenceFile = new File(getAppHomeDir(),
2598
                    "plugins-persistence.xml");
2599
            if (pluginsPersistenceFile.exists()) {
2600
                return pluginsPersistenceFile;
2601
            }
2602
        }
2603
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2604

    
2605
    }
2606

    
2607
    private static void persistenceToXML(XMLEntity entity)
2608
            throws ConfigurationException {
2609
                // write on a temporary file in order to not destroy current file if
2610
        // there is some problem while marshaling
2611
        File tmpFile = new File(getPluginsPersistenceFile(false).getPath()
2612
                + "-" + DateTime.getCurrentDate().getTime());
2613

    
2614
        File xml = getPluginsPersistenceFile(false);
2615
        OutputStreamWriter writer = null;
2616

    
2617
        try {
2618
            writer = new OutputStreamWriter(new FileOutputStream(tmpFile),
2619
                    CASTORENCODING);
2620
            entity.getXmlTag().marshal(writer);
2621
            writer.close();
2622

    
2623
                        // if marshaling process finished correctly, move the file to the
2624
            // correct one
2625
            xml.delete();
2626
            if (!tmpFile.renameTo(xml)) {
2627
                // if rename was not succesful, try copying it
2628
                FileChannel sourceChannel = new FileInputStream(tmpFile)
2629
                        .getChannel();
2630
                FileChannel destinationChannel = new FileOutputStream(xml)
2631
                        .getChannel();
2632
                sourceChannel.transferTo(0, sourceChannel.size(),
2633
                        destinationChannel);
2634
                sourceChannel.close();
2635
                destinationChannel.close();
2636

    
2637
            }
2638
        } catch (FileNotFoundException e) {
2639
            throw new ConfigurationException(e);
2640
        } catch (MarshalException e) {
2641
            // try to close the stream, maybe it remains open
2642
            if (writer != null) {
2643
                try {
2644
                    writer.close();
2645
                } catch (IOException e1) {
2646
                }
2647
            }
2648
        } catch (ValidationException e) {
2649
            throw new ConfigurationException(e);
2650
        } catch (IOException e) {
2651
            throw new ConfigurationException(e);
2652
        }
2653
    }
2654

    
2655
    static MDIFrame getFrame() {
2656
        return frame;
2657
    }
2658

    
2659
    /**
2660
     * Gracefully closes the application. It shows dialogs to save data, finish
2661
     * processes, etc, then it terminates the extensions, removes temporal files
2662
     * and finally exits.
2663
     */
2664
    public synchronized static void closeApplication() {
2665
        TerminationProcess terminationProcess = (new Launcher()).new TerminationProcess();
2666
        terminationProcess.run();
2667
    }
2668

    
2669
    static HashMap getClassesExtensions() {
2670
        return classesExtensions;
2671
    }
2672

    
2673
    public static IExtension getExtensionByName(String extensionName) {
2674
        if( StringUtils.isEmpty(extensionName) ) {
2675
            return null;
2676
        }
2677
        for (Entry<Class<? extends IExtension>, ExtensionDecorator> entry : classesExtensions.entrySet()) {
2678
            Class<? extends IExtension> extensionClass = entry.getKey();
2679
            IExtension extension = entry.getValue();
2680
            if( extensionName.equals(extensionClass.getName()) ) {
2681
                while( extension instanceof ExtensionDecorator ) {
2682
                    extension = ((ExtensionDecorator)extension).getExtension();
2683
                }
2684
                return extension;
2685
            }
2686
        }
2687
        return null;
2688
    }
2689

    
2690
    private static Extensions[] getExtensions() {
2691
        List<Extensions> array = new ArrayList<Extensions>();
2692
        Iterator<PluginConfig> iter = pluginsConfig.values().iterator();
2693

    
2694
        while (iter.hasNext()) {
2695
            array.add(iter.next().getExtensions());
2696
        }
2697

    
2698
        return array.toArray(new Extensions[array.size()]);
2699
    }
2700

    
2701
    public static Iterator getExtensionIterator() {
2702
        return extensions.iterator();
2703
    }
2704

    
2705
    public static HashMap getPluginConfig() {
2706
        return pluginsConfig;
2707
    }
2708

    
2709
    public static Extension getExtension(String s) {
2710
        Extensions[] exts = getExtensions();
2711

    
2712
        for (int i = 0; i < exts.length; i++) {
2713
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2714
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2715
                    return exts[i].getExtension(j);
2716
                }
2717
            }
2718
        }
2719

    
2720
        return null;
2721
    }
2722

    
2723
    public static AndamiConfig getAndamiConfig() {
2724
        return andamiConfig;
2725
    }
2726

    
2727
    private static class ExtensionComparator implements Comparator {
2728

    
2729
        public int compare(Object o1, Object o2) {
2730
            Extension e1 = (Extension) o1;
2731
            Extension e2 = (Extension) o2;
2732

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

    
2737
            if (e1.hasPriority() && !e2.hasPriority()) {
2738
                return Integer.MIN_VALUE;
2739
            }
2740

    
2741
            if (e2.hasPriority() && !e1.hasPriority()) {
2742
                return Integer.MAX_VALUE;
2743
            }
2744

    
2745
            if (e1.getPriority() != e2.getPriority()) {
2746
                return e2.getPriority() - e1.getPriority();
2747
            } else {
2748
                return (e2.toString().compareTo(e1.toString()));
2749
            }
2750
        }
2751
    }
2752

    
2753
    private static class MenuComparator implements Comparator<SortableMenu> {
2754

    
2755
        private static ExtensionComparator extComp = new ExtensionComparator();
2756

    
2757
        public int compare(SortableMenu e1, SortableMenu e2) {
2758

    
2759
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2760
                if (e1.extension instanceof SkinExtensionType) {
2761
                    return 1;
2762
                } else if (e2.extension instanceof SkinExtensionType) {
2763
                    return -1;
2764
                } else {
2765
                    return extComp.compare(e1.extension, e2.extension);
2766
                }
2767
            }
2768

    
2769
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2770
                return Integer.MIN_VALUE;
2771
            }
2772

    
2773
            if (e2.menu.hasPosition() && !e1.menu.hasPosition()) {
2774
                return Integer.MAX_VALUE;
2775
            }
2776

    
2777
            if (e1.menu.getPosition() == e2.menu.getPosition()) {
2778
                                // we don't return 0 unless both objects are the same, otherwise
2779
                // the objects get overwritten in the treemap
2780
                return (e1.toString().compareTo(e2.toString()));
2781
            }
2782
            if (e1.menu.getPosition() > e2.menu.getPosition()) {
2783
                return Integer.MAX_VALUE;
2784
            }
2785
            return Integer.MIN_VALUE;
2786

    
2787
        }
2788
    }
2789

    
2790
    private static class SortableMenu {
2791

    
2792
        public PluginClassLoader loader;
2793
        public Menu menu;
2794
        public SkinExtensionType extension;
2795

    
2796
        public SortableMenu(PluginClassLoader loader,
2797
                SkinExtensionType skinExt, Menu menu2) {
2798
            extension = skinExt;
2799
            menu = menu2;
2800
            this.loader = loader;
2801
        }
2802

    
2803
    }
2804

    
2805
    private static class SortableTool {
2806

    
2807
        public PluginClassLoader loader;
2808
        public ToolBar toolbar;
2809
        public ActionTool actiontool;
2810
        public SelectableTool selectabletool;
2811
        public SkinExtensionType extension;
2812

    
2813
        public SortableTool(PluginClassLoader loader,
2814
                SkinExtensionType skinExt, ToolBar toolbar2,
2815
                ActionTool actiontool2) {
2816
            extension = skinExt;
2817
            toolbar = toolbar2;
2818
            actiontool = actiontool2;
2819
            this.loader = loader;
2820
        }
2821

    
2822
        public SortableTool(PluginClassLoader loader,
2823
                SkinExtensionType skinExt, ToolBar toolbar2,
2824
                SelectableTool selectabletool2) {
2825
            extension = skinExt;
2826
            toolbar = toolbar2;
2827
            selectabletool = selectabletool2;
2828
            this.loader = loader;
2829
        }
2830

    
2831
        public long getPosition() {
2832
            if( this.actiontool!=null ) {
2833
                return this.actiontool.getPosition();
2834
            }
2835
            if( this.selectabletool!=null ) {
2836
                return this.selectabletool.getPosition();
2837
            }
2838
            return 0;
2839
        }
2840
    }
2841

    
2842
    private static class ToolBarComparator implements Comparator<SortableTool> {
2843

    
2844
        private static ExtensionComparator extComp = new ExtensionComparator();
2845

    
2846
        public int compare(SortableTool e1, SortableTool e2) {
2847

    
2848
                        // if the toolbars have the same name, they are considered to be
2849
            // the same toolbar, so we don't need to do further comparing
2850
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2851
                return 0;
2852
            }
2853

    
2854
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2855
                if (e1.extension instanceof SkinExtensionType) {
2856
                    return 1;
2857
                } else if (e2.extension instanceof SkinExtensionType) {
2858
                    return -1;
2859
                } else {
2860
                    return extComp.compare(e1.extension, e2.extension);
2861
                }
2862
            }
2863

    
2864
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2865
                return Integer.MIN_VALUE;
2866
            }
2867

    
2868
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2869
                return Integer.MAX_VALUE;
2870
            }
2871
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2872
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2873
            }
2874

    
2875
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2876
                    && e1.toolbar.getSelectableTool().equals(
2877
                            e2.toolbar.getSelectableTool())) {
2878
                return 0;
2879
            }
2880
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2881
        }
2882
    }
2883

    
2884
    /**
2885
     * <p>
2886
     * This class is used to compare tools (selectabletool and actiontool),
2887
     * using the "position" attribute.
2888
     * </p>
2889
     * <p>
2890
     * The ordering criteria are:
2891
     * </p>
2892
     * <ul>
2893
     * <li>If the tools are placed in different toolbars, they use the toolbars'
2894
     * order. (using the ToolBarComparator).</li>
2895
     * <li></li>
2896
     * <li>If any of the tools has not 'position' attribute, the tool which
2897
     * <strong>has</strong> the attribute will be placed first.</li>
2898
     * <li>If both tools have the same position (or they don't have a 'position'
2899
     * attribute), the priority of the extensions where the tool is
2900
     * defined.</li>
2901
     * </ul>
2902
     *
2903
     */
2904
    private static class ToolComparator implements Comparator<SortableTool> {
2905

    
2906
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2907

    
2908
        public int compare(SortableTool e1, SortableTool e2) {
2909
            // compare the toolbars which contain the tools
2910
            long result = toolBarComp.compare(e1, e2);
2911
            if (result != 0) { // if the toolbars are different, use their order
2912
                return result > 0 ? 1 : -1;
2913
            }
2914
            // otherwise, compare the tools
2915
            long e1Position = -1, e2Position = -1;
2916

    
2917
            if (e1.actiontool != null) {
2918
                if (e1.actiontool.hasPosition()) {
2919
                    e1Position = e1.actiontool.getPosition();
2920
                }
2921
            } else if (e1.selectabletool != null) {
2922
                if (e1.selectabletool.hasPosition()) {
2923
                    e1Position = e1.selectabletool.getPosition();
2924
                }
2925
            }
2926

    
2927
            if (e2.actiontool != null) {
2928
                if (e2.actiontool.hasPosition()) {
2929
                    e2Position = e2.actiontool.getPosition();
2930
                }
2931
            } else if (e2.selectabletool != null) {
2932
                if (e2.selectabletool.hasPosition()) {
2933
                    e2Position = e2.selectabletool.getPosition();
2934
                }
2935
            }
2936

    
2937
            if ((e1Position == -1) && (e2Position != -1)) {
2938
                return 1;
2939
            }
2940
            if ((e1Position != -1) && (e2Position == -1)) {
2941
                return -1;
2942
            }
2943
            if ((e1Position != -1) && (e2Position != -1)) {
2944
                result = e1Position - e2Position;
2945
                                // we don't return 0 unless both objects are the same, otherwise
2946
                // the objects get overwritten in the treemap
2947
                if (result != 0) {
2948
                    return result > 0 ? 1 : -1;
2949
                }
2950
            }
2951
            return e1.toString().compareTo(e2.toString());
2952
        }
2953
    }
2954

    
2955
    public static String getDefaultLookAndFeel() {
2956
        String osName = (String) System.getProperty("os.name");
2957

    
2958
        if ((osName.length() > 4)
2959
                && osName.substring(0, 5).toLowerCase().equals("linux")) {
2960
            return nonWinDefaultLookAndFeel;
2961
        }
2962
        if (osName.toLowerCase().startsWith("mac os x")) {
2963
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
2964
        }
2965

    
2966
        return UIManager.getSystemLookAndFeelClassName();
2967
    }
2968

    
2969
    /**
2970
     * Gets the ISO 839 two-characters-long language code matching the provided
2971
     * language code (which may be an ISO 839-2/T three-characters-long code or
2972
     * an ISO 839-1 two-characters-long code).
2973
     *
2974
     * If the provided parameter is already two characters long, it returns the
2975
     * parameter without any modification.
2976
     *
2977
     * @param langCode A language code representing either an ISO 839-2/T
2978
     * language code or an ISO 839-1 code.
2979
     * @return A two-characters-long code specifying an ISO 839 language code.
2980
     */
2981
    private static String normalizeLanguageCode(String langCode) {
2982
        final String fileName = "iso_639.tab";
2983
        if (langCode.length() == 2) {
2984
            return langCode;
2985
        } else if (langCode.length() == 3) {
2986
            if (langCode.equals("va") || langCode.equals("val")) { // special
2987
                // case
2988
                // for
2989
                // Valencian
2990
                return "ca";
2991
            }
2992
            URL isoCodes = Launcher.class.getClassLoader()
2993
                    .getResource(fileName);
2994
            if (isoCodes != null) {
2995
                try {
2996
                    BufferedReader reader = new BufferedReader(
2997
                            new InputStreamReader(isoCodes.openStream(),
2998
                                    "ISO-8859-1"));
2999
                    String line;
3000

    
3001
                    while ((line = reader.readLine()) != null) {
3002
                        String[] language = line.split("\t");
3003
                        if (language[0].equals(langCode)) {
3004
                                                        // the three
3005
                            // characters code
3006
                            return language[2]; // third column i the two
3007
                            // characters code
3008
                        }
3009
                    }
3010
                } catch (IOException ex) {
3011
                    logger.error(Messages
3012
                            .getString("Error_reading_isocodes_file"), ex);
3013
                    return "es";
3014
                }
3015
            } else {
3016
                logger.error(Messages.getString("Error_reading_isocodes_file"));
3017
                return "es";
3018
            }
3019
        }
3020
        return "es";
3021
    }
3022

    
3023
    /**
3024
     * Configures the locales (languages and local resources) to be used by the
3025
     * application.
3026
     *
3027
     * First it tries to get the locale from the command line parameters, then
3028
     * the andami-config file is checked.
3029
     *
3030
     * The locale name is normalized to get a two characters language code as
3031
     * defined by ISO-639-1 (although ISO-639-2/T three characters codes are
3032
     * also accepted from the command line or the configuration file).
3033
     *
3034
     * Finally, the gvsig-i18n library and the default locales for Java and
3035
     * Swing are configured.
3036
     *
3037
     */
3038
    private static void configureLocales() {
3039
        // Configurar el locale
3040
        String localeStr = null;
3041

    
3042
        if( getArguments().contains("language") ) {
3043
            localeStr = getArguments().get("language");
3044
        } else {
3045
            localeStr = andamiConfig.getLocaleLanguage();
3046
        }
3047
        localeStr = normalizeLanguageCode(localeStr);
3048
        locale = getLocale(
3049
                localeStr,
3050
                andamiConfig.getLocaleCountry(),
3051
                andamiConfig.getLocaleVariant()
3052
        );
3053
        org.gvsig.i18n.Messages.setCurrentLocale(locale);
3054
        JComponent.setDefaultLocale(locale);
3055
        /*
3056
         org.gvsig.i18n.Messages.addLocale(locale);
3057
         // add english and spanish as fallback languages
3058
         if ( localeStr.equals("es") || localeStr.equals("ca")
3059
         || localeStr.equals("gl") || localeStr.equals("eu")
3060
         || localeStr.equals("va") ) {
3061
         // prefer Spanish for languages spoken in Spain
3062
         org.gvsig.i18n.Messages.addLocale(new Locale("es"));
3063
         org.gvsig.i18n.Messages.addLocale(new Locale("en"));
3064
         } else {
3065
         // prefer English for the rest
3066
         org.gvsig.i18n.Messages.addLocale(new Locale("en"));
3067
         org.gvsig.i18n.Messages.addLocale(new Locale("es"));
3068
         }
3069
         */
3070
        // Create classloader for the i18n resources in the
3071
        // andami and user i18n folder. Those values will have
3072
        // precedence over any other values added afterwards
3073
        File appI18nFolder = new File(getApplicationFolder(), "i18n");
3074
        File userI18nFolder = new File(getAppHomeDir(), "i18n");
3075
        if (!userI18nFolder.exists()) {
3076
            try {
3077
                FileUtils.forceMkdir(userI18nFolder);
3078
            } catch (IOException e) {
3079
                logger.info("Can't create i18n folder in gvSIG home (" + userI18nFolder + ").", e);
3080
            }
3081
        }
3082
//        logger.info("Loading i18n resources from the application and user "
3083
//                + "folders: {}, {}", appI18nFolder, userI18nFolder);
3084

    
3085
        URL[] i18nURLs = getURLsFromI18nFolders(userI18nFolder, appI18nFolder);
3086
        ClassLoader i18nClassLoader = URLClassLoader.newInstance(i18nURLs, null);
3087
        logger.info("loading resources from classloader " + i18nClassLoader.toString() + ".");
3088
        org.gvsig.i18n.Messages.addResourceFamily("text", i18nClassLoader,
3089
                "Andami Launcher");
3090

    
3091
        // Finally load the andami own i18n resources
3092
        org.gvsig.i18n.Messages.addResourceFamily("org.gvsig.andami.text",
3093
                "Andami Launcher");
3094
    }
3095

    
3096
    private static URL[] getURLsFromI18nFolders(File userFolder, File appFolder) {
3097
        List<URL> urls = new ArrayList<URL>();
3098
        File[] files = new File[]{userFolder, appFolder};
3099
        for (int n1 = 0; n1 < files.length; n1++) {
3100
            File folder = files[n1];
3101
//                try {
3102
//                    urls.add(folder.toURI().toURL());
3103
//                } catch (MalformedURLException ex) {
3104
//                    logger.warn("Can't convert file to url (file="+userFolder.getAbsolutePath()+").", ex);
3105
//                    return null;
3106
//                }
3107
            File[] subFiles = folder.listFiles();
3108
            for (int n2 = 0; n2 < subFiles.length; n2++) {
3109
                File subFolder = subFiles[n2];
3110
                if ("andami".equalsIgnoreCase(subFolder.getName())) {
3111
                    // Skip andami and add the last.
3112
                    continue;
3113
                }
3114
                if (subFolder.isDirectory()) {
3115
                    try {
3116
                        urls.add(subFolder.toURI().toURL());
3117
                    } catch (MalformedURLException ex) {
3118
                        logger.warn("Can't convert file to url (file=" + subFolder.getAbsolutePath() + ").", ex);
3119
                        return null;
3120
                    }
3121
                }
3122
            }
3123
        }
3124
        File folder = new File(appFolder, "andami");
3125
        try {
3126
            urls.add(folder.toURI().toURL());
3127
        } catch (MalformedURLException ex) {
3128
            logger.warn("Can't convert file to url (file=" + folder.getAbsolutePath() + ").", ex);
3129
            return null;
3130
        }
3131
        return urls.toArray(new URL[urls.size()]);
3132
    }
3133

    
3134
    /**
3135
     * Gets Home Directory location of the application into users home folder.
3136
     *
3137
     * May be set from outside the aplication by means of
3138
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name of the application
3139
     *
3140
     * @return
3141
     */
3142
    public static String getAppHomeDir() {
3143
        return appHomeDir;
3144
    }
3145

    
3146
    public static File getApplicationHomeFolder() {
3147
        return new File(getAppHomeDir());
3148
    }
3149

    
3150
    /**
3151
     * Sets Home Directory location of the application. May be set from outside
3152
     * the aplication by means of -DgvSIG.home=C:/data/gvSIG, where gvSIG its
3153
     * the name of the application
3154
     *
3155
     * @param appHomeDir
3156
     */
3157
    public static void setAppHomeDir(String appHomeDir) {
3158
        Launcher.appHomeDir = appHomeDir;
3159
    }
3160

    
3161
    /**
3162
     * Initialize the extesion that have to take the control of the state of
3163
     * action controls of the UI of all extensions. <br>
3164
     * <br>
3165
     * For use this option you have to add an argument to the command line like
3166
     * this: <br>
3167
     * <br>
3168
     * -exclusiveUI={pathToExtensionClass} <br>
3169
     *
3170
     */
3171
    private static void initializeExclusiveUIExtension() {
3172
        String name = PluginServices.getArgumentByName("exclusiveUI");
3173
        if (name == null) {
3174
            return;
3175
        }
3176

    
3177
        Iterator<Class<? extends IExtension>> iter = classesExtensions.keySet()
3178
                .iterator();
3179
        int charIndex;
3180
        Class<? extends IExtension> key;
3181
        while (iter.hasNext()) {
3182
            key = iter.next();
3183
            charIndex = key.getName().indexOf(name);
3184
            // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex);
3185
            if (charIndex == 0) {
3186
                IExtension ext = classesExtensions.get(key);
3187
                if (ext instanceof ExtensionDecorator) {
3188
                    ext = ((ExtensionDecorator) ext).getExtension();
3189
                }
3190
                if (ext instanceof ExclusiveUIExtension) {
3191
                    PluginServices
3192
                            .setExclusiveUIExtension((ExclusiveUIExtension) ext);
3193
                }
3194
                break;
3195
            }
3196
        }
3197

    
3198
        logger
3199
                .error(Messages
3200
                        .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
3201
                        + " '" + name + "'");
3202
    }
3203

    
3204
    public static void initIconThemes() {
3205
        PluginsManager pluginsManager = PluginsLocator.getManager();
3206
        IconThemeManager iconManager = ToolsSwingLocator.getIconThemeManager();
3207

    
3208
        File f = new File(pluginsManager.getApplicationHomeFolder(), "icon-theme");
3209
        if (!f.exists()) {
3210
            try {
3211
                f.mkdir();
3212
            } catch (Exception ex) {
3213
                // Do nothing
3214
            }
3215
        }
3216
        iconManager.getRepository().add(f, "_User");
3217

    
3218
        f = new File(pluginsManager.getApplicationFolder(), "icon-theme");
3219
        if (!f.exists()) {
3220
            try {
3221
                f.mkdir();
3222
            } catch (Exception ex) {
3223
                // Do nothing
3224
            }
3225
        }
3226
        iconManager.getRepository().add(f, "_Global");
3227

    
3228
        Preferences prefs = Preferences.userRoot().node("gvsig.icontheme");
3229
        String defaultThemeID = prefs.get("default-theme", null);
3230
        if (defaultThemeID != null) {
3231
            IconTheme iconTheme = iconManager.get(defaultThemeID);
3232
            if (iconTheme != null) {
3233
                iconManager.setCurrent(iconTheme);
3234
            }
3235
        }
3236
        double scaleFactor;
3237
        try {
3238
            scaleFactor = prefs.getDouble("scaleFactor",1.0);
3239
        } catch(Throwable th) {
3240
            scaleFactor = 1.0;
3241
        }
3242
        iconManager.setScaleFactor(scaleFactor);
3243
    }
3244

    
3245
    public static void manageUnsavedData(String prompt) throws Exception {
3246
        final UnsavedDataPanel panel = new UnsavedDataPanel(prompt);
3247
        final List<IUnsavedData> unsavedData = PluginsLocator.getManager().getUnsavedData();
3248
        panel.setUnsavedData(unsavedData);
3249

    
3250
        panel.addActionListener(panel.new UnsavedDataPanelListener() {
3251

    
3252
            public void cancel(UnsavedDataPanel panel) {
3253
                panel.setVisible(false);
3254
            }
3255

    
3256
            public void discard(UnsavedDataPanel panel) {
3257
                panel.setVisible(false);
3258
            }
3259

    
3260
            public void accept(UnsavedDataPanel panel) {
3261
                panel.setVisible(false);
3262

    
3263
                try {
3264
                    PluginsLocator.getManager().saveUnsavedData(panel.getSelectedsUnsavedDataList());
3265
                } catch (UnsavedDataException e) {
3266
                    StringBuilder msg = new StringBuilder();
3267
                    msg.append(PluginServices.getText(this, "The_following_resources_could_not_be_saved"));
3268
                    msg.append("\n");
3269
                    for (Iterator iterator = e.getUnsavedData().iterator(); iterator.hasNext();) {
3270
                        IUnsavedData unsavedData = (IUnsavedData) iterator.next();
3271
                        msg.append(unsavedData.getResourceName());
3272
                        msg.append(" -- ");
3273
                        msg.append(unsavedData.getDescription());
3274
                        msg.append("\n");
3275
                    }
3276
                    JOptionPane.showMessageDialog(panel, msg, PluginServices.getText(this, "Resources_was_not_saved"), JOptionPane.ERROR_MESSAGE);
3277
                }
3278
            }
3279
        });
3280

    
3281
        //TODO: mostrar panel WindowManager
3282
        ToolsSwingLocator.getWindowManager().showWindow(
3283
                panel,
3284
                PluginServices.getText(panel, "Resource_was_not_saved"),
3285
                MODE.DIALOG);
3286

    
3287
    }
3288

    
3289
    /**
3290
     * Manages Andami termination process
3291
     *
3292
     */
3293
    public class TerminationProcess {
3294

    
3295
        private boolean proceed = false;
3296
        private UnsavedDataPanel panel = null;
3297

    
3298
        public void run() {
3299
            try {
3300
                int exit = manageUnsavedData();
3301
                if ((exit == JOptionPane.NO_OPTION)
3302
                        || (exit == JOptionPane.CLOSED_OPTION)) {
3303
                    // the user doesn't want to exit
3304
                    return;
3305
                }
3306
                closeAndami();
3307
            } catch (Exception e) {
3308
                logger.warn("It is not possible to close the application", e);
3309
                                // It is not possible to close the application.
3310
                // this exception has been registered before
3311
            }
3312
        }
3313

    
3314
        /**
3315
         * Finishes the application without asking user if want or not to save
3316
         * unsaved data.
3317
         */
3318
        public void closeAndami() {
3319
            PluginsManager pluginsManager = PluginsLocator.getManager();
3320
            pluginsManager.executeShutdownTasks();
3321

    
3322
            try {
3323
                saveAndamiConfig();
3324
            } catch (Exception ex) {
3325
                logger.error(
3326
                        "There was an error exiting application, can't save andami-config.xml",
3327
                        ex
3328
                );
3329
            }
3330

    
3331
            try {
3332
                // Persistencia de los plugins
3333
                savePluginPersistence();
3334
                savePluginsProperties();
3335
            } catch (Exception ex) {
3336
                logger.error(
3337
                        "There was an error exiting application, can't save plugins properties",
3338
                        ex
3339
                );
3340
            }
3341

    
3342
            // Finalize all the extensions
3343
            finalizeExtensions();
3344

    
3345
            try {
3346
                // Clean any temp data created
3347
                Utilities.cleanUpTempFiles();
3348
            } catch (Exception ex) {
3349
                logger.error(
3350
                        "There was an error exiting application, can't remove temporary files",
3351
                        ex
3352
                );
3353
            }
3354

    
3355
            logger.info("Quiting application.");
3356

    
3357
            // Para la depuraci?n de memory leaks
3358
            System.gc();
3359

    
3360
            System.exit(0);
3361
        }
3362

    
3363
        public void saveAndamiConfig() {
3364
            // Configuraci?n de Andami
3365
            try {
3366
                andamiConfigToXML(andamiConfigPath);
3367
            } catch (MarshalException e) {
3368
                logger
3369
                        .error(
3370
                                Messages
3371
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3372
                                e);
3373
            } catch (ValidationException e) {
3374
                logger
3375
                        .error(
3376
                                Messages
3377
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3378
                                e);
3379
            } catch (IOException e) {
3380
                logger
3381
                        .error(
3382
                                Messages
3383
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3384
                                e);
3385
            }
3386
        }
3387

    
3388
        private void savePluginsProperties() {
3389
            PluginsManager manager = PluginsLocator.getManager();
3390
            List<PluginServices> plugins = manager.getPlugins();
3391
            for (PluginServices plugin : plugins) {
3392
                if (plugin != null) {
3393
                    plugin.savePluginProperties();
3394
                }
3395
            }
3396
        }
3397

    
3398
        /**
3399
         * Exectutes the terminate method for all the extensions, in the reverse
3400
         * order they were initialized
3401
         *
3402
         */
3403
        private void finalizeExtensions() {
3404
            for (int i = extensions.size() - 1; i >= 0; i--) {
3405
                org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
3406
                        .get(i);
3407
                String extensionName = "(unknow)";
3408
                try {
3409
                    extensionName = extensionInstance.getClass().getName();
3410
                    extensionInstance.terminate();
3411
                } catch (Exception ex) {
3412
                    logger.error(MessageFormat.format(
3413
                            "There was an error extension ending {0}",
3414
                            extensionName), ex);
3415
                }
3416
            }
3417
        }
3418

    
3419
        private IUnsavedData[] getUnsavedData() throws Exception {
3420
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
3421
            IExtension exclusiveExtension = PluginServices
3422
                    .getExclusiveUIExtension();
3423

    
3424
            for (int i = extensions.size() - 1; i >= 0; i--) {
3425
                org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
3426
                        .get(i);
3427
                IExtensionStatus status = null;
3428
                if (exclusiveExtension != null) {
3429
                    status = exclusiveExtension.getStatus(extensionInstance);
3430
                } else {
3431
                    status = extensionInstance.getStatus();
3432
                }
3433
                if (status != null) {
3434
                    try {
3435
                        if (status.hasUnsavedData()) {
3436
                            IUnsavedData[] array = status.getUnsavedData();
3437
                            for (int element = 0; element < array.length; element++) {
3438
                                unsavedDataList.add(array[element]);
3439
                            }
3440
                        }
3441
                    } catch (Exception e) {
3442
                        logger.info("Error calling the hasUnsavedData method",
3443
                                new Exception());
3444
                        int option = JOptionPane
3445
                                .showConfirmDialog(
3446
                                        frame,
3447
                                        Messages
3448
                                        .getString("error_getting_unsaved_data"),
3449
                                        Messages.getString("MDIFrame.salir"),
3450
                                        JOptionPane.YES_NO_OPTION);
3451
                        if (option == JOptionPane.NO_OPTION) {
3452
                            throw e;
3453
                        }
3454
                    }
3455
                }
3456
            }
3457
            return unsavedDataList.toArray(new IUnsavedData[unsavedDataList
3458
                    .size()]);
3459
        }
3460

    
3461
        public UnsavedDataPanel getUnsavedDataPanel() {
3462
            if (panel == null) {
3463
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
3464
            }
3465
            return panel;
3466
        }
3467

    
3468
        /**
3469
         * Checks if the extensions have some unsaved data, and shows a dialog
3470
         * to allow saving it. This dialog also allows to don't exit Andami.
3471
         *
3472
         * @return true if the user confirmed he wishes to exit, false otherwise
3473
         * @throws Exception
3474
         */
3475
        public int manageUnsavedData() throws Exception {
3476
            IUnsavedData[] unsavedData = getUnsavedData();
3477

    
3478
            // there was no unsaved data
3479
            if (unsavedData.length == 0) {
3480
                int option = JOptionPane
3481
                        .showConfirmDialog(frame, Messages
3482
                                .getString("MDIFrame.quiere_salir"), Messages
3483
                                .getString("MDIFrame.salir"),
3484
                                JOptionPane.YES_NO_OPTION);
3485
                return option;
3486
            }
3487

    
3488
            UnsavedDataPanel panel = getUnsavedDataPanel();
3489
            panel.setUnsavedDataArray(unsavedData);
3490

    
3491
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
3492

    
3493
                public void cancel(UnsavedDataPanel panel) {
3494
                    proceed(false);
3495
                    PluginServices.getMDIManager().closeWindow(panel);
3496

    
3497
                }
3498

    
3499
                public void discard(UnsavedDataPanel panel) {
3500
                    proceed(true);
3501
                    PluginServices.getMDIManager().closeWindow(panel);
3502

    
3503
                }
3504

    
3505
                public void accept(UnsavedDataPanel panel) {
3506
                    IUnsavedData[] unsavedDataArray = panel
3507
                            .getSelectedsUnsavedData();
3508
                    boolean saved;
3509
                    for (int i = 0; i < unsavedDataArray.length; i++) {
3510
                        try {
3511
                            saved = unsavedDataArray[i].saveData();
3512
                        } catch (Exception ex) {
3513
                            PluginServices.getLogger().error(
3514
                                    "Error saving"
3515
                                    + unsavedDataArray[i]
3516
                                    .getResourceName(), ex);
3517
                            saved = false;
3518
                        }
3519
                        if (!saved) {
3520
                            JOptionPane
3521
                                    .showMessageDialog(
3522
                                            panel,
3523
                                            PluginServices
3524
                                            .getText(this,
3525
                                                    "The_following_resource_could_not_be_saved_")
3526
                                            + "\n"
3527
                                            + unsavedDataArray[i]
3528
                                            .getResourceName()
3529
                                            + " -- "
3530
                                            + unsavedDataArray[i]
3531
                                            .getDescription(),
3532
                                            PluginServices.getText(this,
3533
                                                    "unsaved_resources"),
3534
                                            JOptionPane.ERROR_MESSAGE);
3535

    
3536
                            try {
3537
                                unsavedDataArray = getUnsavedData();
3538
                            } catch (Exception e) {
3539
                                // This exception has been registered before
3540
                            }
3541
                            panel.setUnsavedDataArray(unsavedDataArray);
3542
                            return;
3543
                        }
3544
                    }
3545
                    proceed(true);
3546
                    PluginServices.getMDIManager().closeWindow(panel);
3547
                }
3548
            });
3549

    
3550
            PluginServices.getMDIManager().addWindow(panel);
3551
            if (proceed) {
3552
                return JOptionPane.YES_OPTION;
3553
            } else {
3554
                return JOptionPane.NO_OPTION;
3555
            }
3556
        }
3557

    
3558
        private void proceed(boolean proceed) {
3559
            this.proceed = proceed;
3560
        }
3561

    
3562
    }
3563

    
3564
    public static TerminationProcess getTerminationProcess() {
3565
        return (new Launcher()).new TerminationProcess();
3566
    }
3567

    
3568
    private PackageInfo getPackageInfo(String pluginsFolder) {
3569
        try {
3570
            PluginsManager pm = PluginsLocator.getManager();
3571
            return pm.getPackageInfo();
3572
        } catch (Exception e) {
3573
            logger.info("Can't locate PackageInfo from plugin org.gvsig.app", e);
3574
            return null;
3575
        }
3576
    }
3577

    
3578
    /**
3579
     * Launch the gvSIG package installer.
3580
     *
3581
     * @throws Exception if there is any error
3582
     */
3583
    private void doInstall(String[] args) throws Exception {
3584
        String installURL = null;
3585
        String installURLFile = null;
3586
        String gvSIGVersion = null;
3587
        String[] myArgs = new String[3];
3588
        PackageInfo packageInfo = null;
3589

    
3590
        Options options = new Options();
3591
        options.addOption("i", "install", false, "install");
3592
        options.addOption("u", "installURL", true, "installURL");
3593
        options.addOption("f", "installURLFile", true, "installURLFile");
3594
        options.addOption("v", "installVersion", true, "installVersion");
3595
        options.addOption("A", "applicationName", true, "application name, default is gvSIG");
3596
        options.addOption("P", "pluginsFolder", true, "pluginsFolder");
3597
        options.addOption("l", "language", true, "language");
3598

    
3599
        // This options are managed by the gvSIG.sh but need to be declared here to avoid
3600
        // errors.
3601
        options.addOption(null, "debug", false, "Activate the JVM remote debug");
3602
        options.addOption(null, "pause", false, "Pause when activate JVM debug");
3603

    
3604
        /*
3605
         * Los parametros que deberian pasarse en el instalador oficial de gvSIG serian:
3606
         *
3607
         * --install
3608
         * --applicationName=gvSIG
3609
         * --language=es
3610
         * --pluginsFolder=gvSIG/extensiones
3611
         *
3612
         * Opcionales (casi mejor que dejar los de por defecto y no pasarselos):
3613
         * --installVersion=2.0.0
3614
         * --installURL=http://downloads.gvsig.org/download/gvsig-desktop/dists
3615
         * --installURLFile=gvSIG/extensiones/org.gvsig.installer.app.extension/defaultDownloadsURLs
3616
         *
3617
         */
3618
        CommandLineParser parser = new PosixParser();
3619
        CommandLine line = null;
3620
        try {
3621
            line = parser.parse(options, args);
3622
            boolean hasAllMandatoryOptions = true;
3623
            if (!line.hasOption("install")) {
3624
                hasAllMandatoryOptions = false;
3625
            }
3626

    
3627
            if (line.hasOption("installVersion")) {
3628
                gvSIGVersion = line.getOptionValue("installVersion");
3629
            }
3630
            if (line.hasOption("applicationName")) {
3631
                myArgs[0] = line.getOptionValue("applicationName");
3632
            } else {
3633
                myArgs[0] = "gvSIG";
3634
            }
3635
            if (line.hasOption("pluginsFolder")) {
3636
                myArgs[1] = line.getOptionValue("pluginsFolder");
3637
            } else {
3638
                myArgs[1] = "gvSIG/extensiones";
3639
            }
3640
            if (line.hasOption("language")) {
3641
                myArgs[2] = "language=" + line.getOptionValue("language");
3642
            } else {
3643
                // prevent null
3644
                myArgs[2] = Locale.getDefault().toString();
3645
            }
3646

    
3647
            if (line.hasOption("installURL")) {
3648
                installURL = line.getOptionValue("installURL");
3649
            } else {
3650
                installURL = "http://downloads.gvsig.org/download/gvsig-desktop/";
3651
            }
3652

    
3653
            if (line.hasOption("installURLFile")) {
3654
                installURLFile = line.getOptionValue("installURLFile");
3655
            } else {
3656
                installURLFile = "gvsig-installer-urls.config";
3657
            }
3658

    
3659
            if (!hasAllMandatoryOptions) {
3660
                System.err.println(Messages.get("usage") + ": Launcher "
3661
                        + "--install "
3662
                        + "[--applicationName=appName] "
3663
                        + "[--pluginsFolder=plugins-directory] "
3664
                        + "[--installURLFile=File] "
3665
                        + "[--installURL=URL] "
3666
                        + "[--language=locale]"
3667
                );
3668
                return;
3669
            }
3670
        } catch (ParseException exp) {
3671
            System.err.println("Unexpected exception:" + exp.getMessage());
3672
            System.exit(-1);
3673
        }
3674

    
3675
        initializeApp(myArgs, "installer");
3676

    
3677
        new DefaultLibrariesInitializer().fullInitialize(true);
3678

    
3679
        initializeInstallerManager();
3680

    
3681
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
3682

    
3683
        try {
3684
            logger.info("Loading plugins configurations");
3685
            this.loadPluginConfigs();
3686
        } catch (Throwable ex) {
3687
            logger.warn("Can't load plugins configurations", ex);
3688
        }
3689

    
3690
        try {
3691
            logger.info("Loading plugins");
3692
            this.loadPluginServices();
3693
        } catch (Throwable ex) {
3694
            logger.warn("Can't load plugins", ex);
3695
        }
3696

    
3697
        AndamiConfig config = getAndamiConfig();
3698

    
3699
        initializeIdentityManagement(new File(config.getPluginsDirectory()).getAbsoluteFile());
3700

    
3701
        initializeLibraries();
3702

    
3703
        packageInfo = getPackageInfo(myArgs[1]);
3704

    
3705
        // set the gvSIG version to the install manager, to compose the download URL
3706
        if (packageInfo != null) {
3707
            installerManager.setVersion(packageInfo.getVersion());
3708
        } else {
3709
            installerManager.setVersion(gvSIGVersion);
3710
        }
3711
        if (!installURL.contains(";")
3712
                && !installURL.endsWith(InstallerManager.PACKAGE_EXTENSION)
3713
                && !installURL.endsWith(InstallerManager.PACKAGE_INDEX_EXTENSION)) {
3714
            if (packageInfo != null && (packageInfo.getState().startsWith(InstallerManager.STATE.BETA)
3715
                    || packageInfo.getState().startsWith(InstallerManager.STATE.RC)
3716
                    || packageInfo.getState().equalsIgnoreCase(InstallerManager.STATE.FINAL))) {
3717
                installURL = installURL + "dists/<%Version%>/builds/<%Build%>/packages.gvspki";
3718
            }
3719
        }
3720
        // Configure default index download URL
3721
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(installURL);
3722

    
3723
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(new File(installURLFile));
3724

    
3725
        // Launch installer
3726
        PluginsManager manager = PluginsLocator.getManager();
3727

    
3728
        InstallWizardPanel installPackageWizard = SwingInstallerLocator
3729
                .getSwingInstallerManager().createInstallPackageWizard(
3730
                        manager.getApplicationFolder(),
3731
                        manager.getInstallFolder());
3732
        installPackageWizard.setWizardActionListener(new InstallerWizardActionListener() {
3733
            @Override
3734
            public void finish(InstallerWizardPanel installerWizard) {
3735
                logger.info("Finish installation.");
3736
                System.exit(0);
3737
            }
3738

    
3739
            @Override
3740
            public void cancel(InstallerWizardPanel installerWizard) {
3741
                logger.info("Cancel installation.");
3742
                System.exit(0);
3743
            }
3744
        });
3745

    
3746
        // the wizard will show the Typical or Advanced mode option.
3747
        installPackageWizard.setSkipTypicalOrAdvancedWizardPage(false);
3748
        // default packages will be selected.
3749
        installPackageWizard.setSelectDefaultPackages(true);
3750

    
3751
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
3752
        frame.addWindowListener(new WindowAdapter() {
3753
            @Override
3754
            public void windowClosing(WindowEvent we) {
3755
                logger.info("Closing installation.");
3756
                System.exit(0);
3757
            }
3758

    
3759
            @Override
3760
            public void windowClosed(WindowEvent we) {
3761
                logger.info("Close installation.");
3762
                System.exit(0);
3763
            }
3764
        });
3765
        frame.getContentPane().add(installPackageWizard.asJComponent(), BorderLayout.CENTER);
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
    private static final int INFO_TEMP_FOLDER = 19;
3801

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

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

    
3830
        String values[] = new String[INFO_TEMP_FOLDER + 1];
3831

    
3832
        PluginsManager pluginmgr = PluginsLocator.getManager();
3833
        LocaleManager localemgr = PluginsLocator.getLocaleManager();
3834

    
3835
        Properties props = System.getProperties();
3836

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

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

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

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

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

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

    
3886
        try {
3887
            if (pkgs == null) {
3888
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
3889
                pkgs = installmgr.getInstalledPackages();
3890
            }
3891
            StringWriter writer = new StringWriter();
3892
            for (PackageInfo pkg : pkgs) {
3893
                writer.write("    ");
3894
                writer.write(pkg.toStringCompact());
3895
                writer.write("\n");
3896
            }
3897
            values[INFO_PACKAGES] = writer.toString();
3898

    
3899
        } catch (Throwable e) {
3900
            logger.warn("Can't get installed package information.", e);
3901
        }
3902

    
3903
        String s = MessageFormat.format(template, (Object[])values);
3904
        return s;
3905
    }
3906

    
3907
    private void logger_info(String msg) {
3908
        String info[] = msg.split("\n");
3909
        for (String info1 : info) {
3910
            logger.info(info1);
3911
        }
3912
    }
3913

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

    
3924
    private void fixIncompatiblePlugins(PackageInfo[] installedPackages) {
3925
        final Set<String> incompatiblePlugins = new HashSet<String>();
3926

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

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

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

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

    
3997
    private class DisablePluginsConflictingDialog extends JDialog {
3998

    
3999
        public static final int CONTINUE = 0;
4000
        public static final int CLOSE = 1;
4001

    
4002
        private DisablePluginsConflictingLayoutPanel contents;
4003
        private int action = 0;
4004
        private List<Item> incompatiblePlugins = null;
4005
        private Map<String, PackageInfo> packages;
4006

    
4007
        private class Item {
4008

    
4009
            private String code;
4010
            private PackageInfo pkg;
4011

    
4012
            public Item(String code, PackageInfo pkg) {
4013
                this.code = code;
4014
                this.pkg = pkg;
4015
            }
4016

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

    
4024
            public String getCode() {
4025
                if (pkg == null) {
4026
                    return code;
4027
                }
4028
                return pkg.getCode();
4029
            }
4030
        }
4031

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

    
4036
            this.packages = packages;
4037

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

    
4050
        private void initComponents() {
4051
            this.contents = new DisablePluginsConflictingLayoutPanel();
4052

    
4053
            doTranslations();
4054

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

    
4071
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
4072
            setLocation((screenSize.width / 2) - (this.getWidth() / 2),
4073
                    (screenSize.height / 2) - (this.getHeight() / 2));
4074
        }
4075

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

    
4086
        private String translate(String msg) {
4087
            return PluginServices.getText(this, msg);
4088
        }
4089

    
4090
        private void doClose() {
4091
            this.action = CLOSE;
4092
            this.setVisible(false);
4093
        }
4094

    
4095
        private void doContinue() {
4096
            this.action = CONTINUE;
4097
            this.setVisible(false);
4098
        }
4099

    
4100
        public int getAction() {
4101
            return this.action;
4102
        }
4103

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

    
4121
    private void initializeIdentityManagement(File pluginsFolder) {
4122
        File identityManagementConfigFile = null;
4123
        PluginServices plugin = null;
4124
        Iterator<Entry<String, PluginConfig>> it = pluginsConfig.entrySet().iterator();
4125
        while (it.hasNext()) {
4126
            Entry<String, PluginConfig> entry = it.next();
4127
            File pluginFolder = entry.getValue().getPluginFolder();
4128
            File f = new File(pluginFolder, "identity-management.ini");
4129
            if (f.exists()) {
4130
                if (identityManagementConfigFile != null) {
4131
                    logger.warn("Too many identity-managemnt plugins. Disable all.");
4132
                } else {
4133
                    identityManagementConfigFile = f;
4134
                    plugin = PluginServices.getPluginServices(entry.getKey());
4135
                }
4136
            }
4137
        }
4138
        if(plugin != null){
4139
                new DefaultLibrariesInitializer(plugin.getClassLoader()).fullInitialize(true);
4140
        }
4141

    
4142
        if (identityManagementConfigFile == null || plugin == null) {
4143
            return;
4144
        }
4145
        if (!identityManagementConfigFile.canRead()) {
4146
            return;
4147
        }
4148
        PropertiesConfiguration identityManagementConfig = null;
4149
        try {
4150
            identityManagementConfig = new PropertiesConfiguration(identityManagementConfigFile);
4151
        } catch (Exception ex) {
4152
            logger.warn("Can't open identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.", ex);
4153
            return;
4154
        }
4155
        String identityManagerClassName = identityManagementConfig.getString("IdentityManager", null);
4156
        String identityManagementInitializerClassName = identityManagementConfig.getString("IdentityManagementInitializer", null);
4157
        try {
4158
            if (identityManagerClassName != null) {
4159
                Class identityManagerClass = plugin.getClassLoader().loadClass(identityManagerClassName);
4160
                ToolsLocator.registerIdentityManager(identityManagerClass);
4161
            } else {
4162
                logger.info("Entry IdentityManager not found in identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.");
4163
            }
4164

    
4165
            if (identityManagementInitializerClassName != null) {
4166
                Class identityManagerInitializerClass = plugin.getClassLoader().loadClass(identityManagementInitializerClassName);
4167
                Runnable identityManagerInitializer = (Runnable) identityManagerInitializerClass.newInstance();
4168
                identityManagerInitializer.run();
4169
            } else {
4170
                logger.info("Entry IdentityManagementInitializer not found in identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.");
4171
            }
4172

    
4173
        } catch (Exception ex) {
4174
            logger.warn("Can't initialize the identity manager from '" + identityManagementConfigFile.getAbsolutePath() + ".", ex);
4175
            return;
4176
        }
4177
        logger.info("Loaded an identity manager from plugin '" + plugin.getPluginName() + ".");
4178
    }
4179
}