Statistics
| Revision:

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

History | View | Annotate | Download (165 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
 * @author $author$
202
 * @version $Revision: 40305 $
203
 */
204
public class Launcher {
205

    
206
    private static Arguments arguments;
207

    
208
    public static abstract class MapWithAlias<Item> extends HashMap<String, Item> {
209

    
210
        private HashMap<String, String> aliases = new HashMap<String, String>();
211

    
212
        public abstract String[] getAliases(Item item);
213

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

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

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

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

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

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

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

    
301
            return item;
302
        }
303

    
304
    }
305

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

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

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

    
325
    }
326

    
327
    public static class PluginsServices extends MapWithAlias<org.gvsig.andami.PluginServices> {
328

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

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

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

    
355
    protected static ListBaseException launcherrors = null;
356

    
357
    protected static Theme theme = null;
358

    
359
    private List<String> deprecatedPluginNames = null;
360

    
361
    private static final class ProxyAuth extends Authenticator {
362

    
363
        private PasswordAuthentication auth;
364

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

    
369
        protected PasswordAuthentication getPasswordAuthentication() {
370
            return auth;
371
        }
372
    }
373

    
374
    private static Launcher launcherInstance;
375

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

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

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

    
404
    protected void downloadExtensions(String extDir) {
405
        // do nothing
406
    }
407

    
408
    public static class LaunchException extends ListBaseException {
409

    
410
        private static final long serialVersionUID = 4541192746962684705L;
411

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

    
418
    }
419

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

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

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

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

    
440
    private List<String> getDeprecatedPluginNames() {
441
        if (deprecatedPluginNames == null) {
442
            String[] ss = new String[]{
443
                "org.gvsig.app",
444
                "org.gvsig.coreplugin",
445
                "org.gvsig.editing",
446
                "org.gvsig.installer.app.extension",
447
                "org.gvsig.exportto.app.extension"
448
            };
449
            deprecatedPluginNames = Arrays.asList(ss);
450
        }
451
        return deprecatedPluginNames;
452
    }
453
    
454
    public static Arguments getArguments() {
455
        return arguments;
456
    }
457
    
458
    public void doMain(String[] args) throws Exception {
459

    
460
        if (args.length < 1) {
461
            System.err.println("Usage: Launcher appName plugins-directory [--language=locale]");
462
            System.err.println("No arguments specified.");
463
            System.err.println("Use default arguments 'gvSIG gvSIG/extensiones'");
464
            args = new String[]{"gvSIG", "gvSIG/extensiones"};
465
        }
466
        arguments = new DefaultArguments(args);
467

    
468
        initializeApp(args, null);
469

    
470
        // Solucionamos el problema de permisos que se produc?do con Java
471
        // Web Start con este codigo.
472
        Policy.setPolicy(new Policy() {
473

    
474
            public PermissionCollection getPermissions(CodeSource codesource) {
475
                Permissions perms = new Permissions();
476
                perms.add(new AllPermission());
477
                return (perms);
478
            }
479

    
480
            public void refresh() {
481
            }
482
        });
483

    
484
        new DefaultLibrariesInitializer().fullInitialize(true);
485
        
486
        InstallerLocator.getInstallerManager().setDownloadBaseURL(
487
                new URL("http://downloads.gvsig.org/download/gvsig-desktop/"));
488

    
489
        try {
490
            initIconThemes();
491
        } catch (Exception ex) {
492
            this.addError("Can't initialize icon theme", ex);
493
        }
494
        // Registramos los iconos base
495
        try {
496
            registerIcons();
497
        } catch (Exception ex) {
498
            this.addError("Can't register icons", ex);
499
        }
500

    
501
        // Obtener la personalizaci?n de la aplicacion.
502
        try {
503
            logger.info("Initialize andami theme");
504
            theme = getTheme(andamiConfig.getPluginsDirectory());
505
        } catch (Exception ex) {
506
            this.addError("Can't get personalized theme for the application",
507
                    ex);
508
        }
509
        UIManager.put("Desktop.background", theme.getBackgroundColor());
510

    
511
        // Mostrar la ventana de inicio
512
        Frame f = new Frame();
513
        splashWindow = new MultiSplashWindow(f, theme, 27);
514

    
515
        // Ponemos los datos del proxy
516
        splashWindow.process(translate("SplashWindow.configuring_proxy"));
517
        logger.info("Configute http proxy");
518
        configureProxy();
519

    
520
        // Buscar actualizaciones de los plugins
521
        splashWindow.process(translate("SplashWindow.looking_for_updates"));
522
        try {
523
//                        this.downloadExtensions(andamiConfig.getPluginsDirectory());
524
        } catch (Exception ex) {
525
            this.addError("Can't downloads plugins", ex);
526
        }
527

    
528
        splashWindow.process(translate("SplashWindow.initialize_install_manager"));
529
        initializeInstallerManager();
530

    
531
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
532
        PackageInfo[] installedPackages = null;
533
        try {
534
            installedPackages = installerManager.getInstalledPackages();
535
        } catch (MakePluginPackageServiceException e) {
536
            // Do nothing, ignore errors
537
        }
538
        logger.info("Dump system information");
539
        logger_info(getInformation(installedPackages));
540
        saveEnvironInformation(installedPackages);
541

    
542
        // Se leen los config.xml de los plugins
543
        splashWindow.process(translate("SplashWindow.load_plugins_configuration"));
544
        try {
545
            logger.info("Load plugins information");
546
            this.loadPluginConfigs();
547
            if (pluginsConfig.isEmpty()) {
548
                logger.warn("No valid plugin was found.");
549
                System.exit(-1);
550
            }
551
        } catch (Throwable ex) {
552
            this.addError("Can't load plugins", ex);
553
        }
554

    
555
        splashWindow.process(translate("SplashWindow.check_incompatible_plugins"));
556
        fixIncompatiblePlugins(installedPackages);
557

    
558
        // Se configura el classloader del plugin
559
        splashWindow.process(translate("SplashWindow.setup_plugins_configuration"));
560
        try {
561
            logger.info("Configure plugins class loader");
562
            this.loadPluginServices();
563
        } catch (Throwable ex) {
564
            logger.warn("Can't initialize plugin's classloaders  ", ex);
565
        }
566
        try {
567
            registerActions();
568
        } catch (Throwable ex) {
569
            logger.warn("Can't register actions of plugins", ex);
570
        }
571

    
572
        initializeIdentityManagement(new File(andamiConfig.getPluginsDirectory()).getAbsoluteFile());
573

    
574
        // Initialize libraries
575
        splashWindow.process(translate("SplashWindow.initialize_plugins_libraries"));
576
        initializeLibraries();
577

    
578
        // Se carga un Skin si alguno ide los plugins trae informacion para ello
579
        splashWindow.process(translate("SplashWindow.looking_for_a_skin"));
580
        logger.info("Initialize skin");
581
        skinPlugin(null);
582

    
583
        // Se configura la cola de eventos
584
        splashWindow.process(translate("setting_up_event_queue"));
585
        EventQueue waitQueue = new AndamiEventQueue();
586
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue);
587

    
588
        // Se configura la internacionalizacion del plugin
589
        splashWindow.process(translate("SplashWindow.starting_plugin_internationalization_system"));
590
        pluginsMessages();
591

    
592
        // Se modifica el andami-config con los plugins nuevos
593
        splashWindow.process(translate("SplashWindow.update_framework_configuration"));
594
        updateAndamiConfig();
595

    
596
        frame = MDIFrame.getInstance();
597
        // Se configura el nombre e icono de la aplicacion
598
        splashWindow.process(translate("SplashWindow.setting_up_applications_name_and_icons"));
599
        frameIcon(theme);
600

    
601
        // Se prepara el MainFrame para albergar las extensiones
602
        splashWindow.process(translate("SplashWindow.preparing_workbench"));
603
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
604
        SwingUtilities.invokeAndWait(new Runnable() {
605
            public void run() {
606
                frame.init();
607
            }
608
        });
609
        ToolsSwingLocator.registerWindowManager(ToolsWindowManager.class);
610

    
611
        // Leer el fichero de persistencia de los plugins
612
        splashWindow.process(translate("SplashWindow.loading_plugin_settings"));
613
        loadPluginsPersistence();
614

    
615
                // Se instalan los controles del skin
616
        // Se inicializan todas las extensiones de todos los plugins
617
        splashWindow.process(translate("SplashWindow.initializing_extensions"));
618
        SwingUtilities.invokeAndWait(new Runnable() {
619
            public void run() {
620
                initializeExtensions();
621
            }
622
        });
623

    
624
        // Se inicializan la extension exclusiva
625
        splashWindow.process(translate("SplashWindow.setting_up_master_extension"));
626
        SwingUtilities.invokeAndWait(new Runnable() {
627
            public void run() {
628
                initializeExclusiveUIExtension();
629
            }
630
        });
631
        frame.setClassesExtensions(classesExtensions);
632

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

    
641
        // Se instalan los menus de las extensiones de los plugins
642
        message(translate("SplashWindow.installing_extensions_menus"));
643
        SwingUtilities.invokeAndWait(new Runnable() {
644
            public void run() {
645
                installPluginsMenus();
646
            }
647
        });
648

    
649
        message(translate("SplashWindow.initializing_server_data_persistence"));
650
        ServerDataPersistence.registerPersistence();
651

    
652
        // Se instalan las etiquetas de las extensiones de los plugins
653
        message(translate("SplashWindow.installing_extensions_labels"));
654
        SwingUtilities.invokeAndWait(new Runnable() {
655
            public void run() {
656
                installPluginsLabels();
657
            }
658
        });
659

    
660
        // Se muestra el frame principal
661
        message(translate("creating_main_window"));
662
        frame.setVisible(true);
663
        frame.setCursor(Cursor.WAIT_CURSOR);
664

    
665
                // Definimos un KeyEventDispatcher global para que las extensiones
666
        // puedan registrar sus "teclas rapidas".
667
        message(translate("SplashWindow.initializing_accelerator_keys"));
668
        GlobalKeyEventDispatcher keyDispatcher = GlobalKeyEventDispatcher.getInstance();
669
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keyDispatcher);
670

    
671
        message(translate("SplashWindow.enable_controls"));
672
        SwingUtilities.invokeAndWait(new Runnable() {
673
            public void run() {
674
                try {
675
                    frame.enableControls();
676
                } catch (Throwable th) {
677
                    logger.warn("Problems enabling controls", th);
678
                }
679
            }
680
        });
681

    
682
        // Se ejecuta el postInitialize
683
        message(translate("SplashWindow.post_initializing_extensions"));
684
        SwingUtilities.invokeAndWait(new Runnable() {
685
            public void run() {
686
                postInitializeExtensions();
687
            }
688
        });
689

    
690
        message(translate("SplashWindow.enable_controls"));
691
        SwingUtilities.invokeAndWait(new Runnable() {
692
            public void run() {
693
                try {
694
                    frame.enableControls();
695
                    message(translate("StatusBar.Aplicacion_iniciada"));
696
                } catch (Throwable th) {
697
                    logger.warn("Problems enabling controls", th);
698
                }
699
            }
700
        });
701

    
702
        splashWindow.close();
703

    
704
        frame.setCursor(Cursor.DEFAULT_CURSOR);
705

    
706
        if (launcherrors != null) {
707
            NotificationManager.addError(launcherrors);
708
        }
709
        org.apache.log4j.Logger.getRootLogger().addAppender(
710
                new NotificationAppender());
711

    
712
        /*
713
         * Executes additional tasks required by plugins
714
         */
715
        PluginsLocator.getManager().executeStartupTasks();
716

    
717
    }
718

    
719
    private void initializeInstallerManager() {
720
        PluginsManager pluginmgr = PluginsLocator.getManager();
721
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
722

    
723
            //
724
        // Configure repository of plugins
725
        //
726
        List<File> folders = pluginmgr.getPluginsFolders();
727
        for (File folder : folders) {
728
            installerManager.addLocalAddonRepository(folder, "plugin");
729
        }
730
        installerManager.setDefaultLocalAddonRepository(folders.get(0), "plugin");
731

    
732
            //
733
        // Configure repository of iconsets
734
        //
735
        IconThemeManager iconManager = ToolsSwingLocator.getIconThemeManager();
736
        FolderSet fset = iconManager.getRepository();
737
        Iterator<FolderSet.FolderEntry> it = fset.iterator();
738
        boolean first = true;
739
        while (it.hasNext()) {
740
            FolderEntry entry = it.next();
741
            installerManager.addLocalAddonRepository(entry.getFolder(), "iconset");
742
            if (first) {
743
                first = false;
744
                installerManager.setDefaultLocalAddonRepository(entry.getFolder(), "iconset");
745
            }
746
        }
747

    
748
    }
749

    
750
    private void message(final String msg) {
751
        if (!SwingUtilities.isEventDispatchThread()) {
752
            try {
753
                SwingUtilities.invokeAndWait(new Runnable() {
754
                    public void run() {
755
                        message(msg);
756
                    }
757
                });
758
            } catch (Exception e) {
759
                logger.info(msg);
760
                logger.warn("Error showing message.", e);
761
            }
762
            return;
763
        }
764
        if (splashWindow.isVisible()) {
765
            splashWindow.process(msg);
766
        }
767
        if (frame.isVisible()) {
768
            frame.message(msg, JOptionPane.INFORMATION_MESSAGE);
769
        }
770
    }
771

    
772
    private void initializeLibraries() {
773
        List<ClassLoader> classLoaders = new ArrayList<ClassLoader>(
774
                pluginsOrdered.size() + 1);
775
        classLoaders.add(getClass().getClassLoader());
776
        Iterator<String> iter = pluginsOrdered.iterator();
777

    
778
        logger.info("Initializing plugins libraries: ");
779
        while (iter.hasNext()) {
780
            String pName = (String) iter.next();
781
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
782
            logger.info("Initializing plugin libraries (" + pName + ")");
783
            classLoaders.add(ps.getClassLoader());
784
        }
785

    
786
                // Create the libraries initializer and
787
        // initialize the plugin libraries
788
        new DefaultLibrariesInitializer(classLoaders
789
                .toArray(new ClassLoader[classLoaders.size()]))
790
                .fullInitialize(true);
791

    
792
        // Remove them all, we don't need them anymore
793
        classLoaders.clear();
794
        classLoaders = null;
795
    }
796

    
797
    /**
798
     * @param args
799
     * @throws IOException
800
     * @throws ConfigurationException
801
     */
802
    private void initializeApp(String[] args, String applicationClasifier) throws IOException, ConfigurationException {
803
        if (args.length < 1) {
804
            appName = "gvSIG"; // Nombre de aplicacion por defecto es "gvSIG"
805
        } else {
806
            appName = args[0];
807
        }
808
        // Hacemos visibles los argumentos como una propiedad est?tica
809
        // de plugin services para quien lo quiera usar (por ejemplo, para
810
        // cargar un proyecto por l?nea de comandos)
811
        PluginServices.setArguments(args);
812
        
813
        getOrCreateConfigFolder();
814
        configureLogging(appName, applicationClasifier);
815
        if (!validJVM()) {
816
            logger.error("Not a valid JRE. Exit application.");
817
            System.exit(-1);
818
        }
819

    
820
        ToolsLocator.registerDefaultToolsLibraries();
821

    
822
        ToolsLocator.getFoldersManager().cleanTemporaryFiles();
823
        
824
        if (args.length < 2) {
825
            loadAndamiConfig("gvSIG/extensiones"); // Valor por defecto
826
        } else {
827
            loadAndamiConfig(args[1]);
828
        }
829

    
830
        configureLocales();
831

    
832
        logger.info("Configure LookAndFeel");
833
        configureLookAndFeel();
834
    }
835

    
836
    /**
837
     *
838
     */
839
    private void configureLookAndFeel() {
840
        // Se pone el lookAndFeel
841
        try {
842
            String lookAndFeel = getAndamiConfig().getLookAndFeel();
843
            if (lookAndFeel == null) {
844
                lookAndFeel = getDefaultLookAndFeel();
845
            }
846
            UIManager.setLookAndFeel(lookAndFeel);
847
        } catch (Exception e) {
848
            logger.warn(Messages.getString("Launcher.look_and_feel"), e);
849
        }
850
        FontUtils.initFonts();
851
    }
852

    
853
    /**
854
     * @param args
855
     * @throws ConfigurationException
856
     */
857
    private void loadAndamiConfig(String pluginFolder)
858
            throws ConfigurationException {
859
        andamiConfigPath = appHomeDir + File.separator + "andami-config.xml";
860
        andamiConfigFromXML(andamiConfigPath);
861
        andamiConfig.setPluginsDirectory(pluginFolder);
862
    }
863

    
864
    /**
865
     *
866
     */
867
    private void getOrCreateConfigFolder() {
868
        // Create application configuration folder
869
        appHomeDir = System.getProperty(appName + ".home");
870
        if (appHomeDir == null) {
871
            appHomeDir = System.getProperty("user.home");
872
        }
873

    
874
        appHomeDir += File.separator + appName;
875
        File parent = new File(appHomeDir);
876
        parent.mkdirs();
877
    }
878

    
879
    /**
880
     * @param args
881
     * @throws IOException
882
     */
883
    private void configureLogging(String appName, String applicationClasifier) throws IOException {
884
        // Configurar el log4j
885

    
886
        String pathname;
887
        if (StringUtils.isBlank(applicationClasifier)) {
888
            pathname = appHomeDir + File.separator + appName + ".log";
889
        } else {
890
            pathname = appHomeDir + File.separator + appName + "-" + applicationClasifier + ".log";
891
        }
892
        URL config = Launcher.class.getClassLoader().getResource("log4j.properties");
893
        if (config == null) {
894
            config = Launcher.class.getClassLoader().getResource("default-log4j/log4j.properties");
895
        }
896
        PropertyConfigurator.configure(config);
897
        PatternLayout l = new PatternLayout("%p %r %t %C - %m%n");
898
        RollingFileAppender fa = new RollingFileAppender(l, pathname, false);
899
        fa.setMaxFileSize("512KB");
900
        fa.setMaxBackupIndex(3);
901
        org.apache.log4j.Logger.getRootLogger().addAppender(fa);
902
        logger.info("Loadded log4j.properties from " + config.toString());
903
        if (StringUtils.isBlank(applicationClasifier)) {
904
            logger.info("Application " + appName);
905
        } else {
906
            logger.info("Application " + appName + "-" + applicationClasifier);
907
        }
908
    }
909
    
910
    public static String getApplicationName() {
911
        return appName;
912
    }
913

    
914
    private class NotificationAppender extends AppenderSkeleton {
915

    
916
        @Override
917
        protected void append(LoggingEvent event) {
918
            if (event.getLevel() == org.apache.log4j.Level.ERROR
919
                    || event.getLevel() == org.apache.log4j.Level.FATAL) {
920

    
921
                Throwable th = null;
922
                ThrowableInformation thi = event.getThrowableInformation();
923
                if (thi != null) {
924
                    th = thi.getThrowable();
925
                }
926
                NotificationManager.dispatchError(event.getRenderedMessage(), th);
927
                return;
928
            }
929
                        // if (event.getLevel() == org.apache.log4j.Level.WARN) {
930
            // NotificationManager.dispatchWarning(event.getRenderedMessage(),
931
            // null);
932
            // return;
933
            // }
934
        }
935

    
936
        @Override
937
        public void close() {
938
            // TODO Auto-generated method stub
939

    
940
        }
941

    
942
        @Override
943
        public boolean requiresLayout() {
944
            // TODO Auto-generated method stub
945
            return false;
946
        }
947

    
948
    }
949

    
950
    /**
951
     * Return the directory applicaction is installed.
952
     */
953
    public static String getApplicationDirectory() {
954
        return getApplicationFolder().getAbsolutePath();
955
    }
956

    
957
    public static File getApplicationFolder() {
958
        // TODO: check if there is a better way to handle this
959
        return new File(System.getProperty("user.dir"));
960
    }
961

    
962
    private void registerIcons() {
963
        IconTheme theme = PluginServices.getIconTheme();
964
        ClassLoader loader = Launcher.class.getClassLoader();
965

    
966
        String[][] icons = {
967
            // MultiSplashWindow
968
            {"main", "splash-default"},
969
            // NewStatusBar
970
            {"main", "statusbar-info"},
971
            {"main", "statusbar-warning"},
972
            {"main", "statusbar-error"}
973
        };
974
        for (int i = 0; i < icons.length; i++) {
975
            try {
976
                IconThemeHelper.registerIcon(icons[i][0], icons[i][1], Launcher.class);
977
            } catch (Exception e) {
978
                logger.info("Can't register icon '" + icons[i][0] + "' (" + icons[i][1] + ").");
979
            }
980
        }
981
        theme.setDefaultIcon(loader.getResource("images/main/default-icon.png"));
982
    }
983

    
984
    private Properties loadProperties(File f) {
985
        FileInputStream fin = null;
986
        Properties p = null;
987
        try {
988
            fin = new FileInputStream(f);
989
            p = new Properties();
990
            p.load(fin);
991
        } catch (IOException ex) {
992
            // Do nothing
993
        }
994
        return p;
995
    }
996

    
997
    /**
998
     * Obtiene la personalizaci?n de los iconos, splash, fondo y el nombre de
999
     * la aplicaci?n.
1000
     *
1001
     * @return Theme
1002
     */
1003
    private Theme getTheme(String pluginsDirectory) {
1004
        File infoFile = new File(Launcher.getApplicationFolder(), "package.info");
1005
        File themeFile = null;
1006
        List<Theme> themes = new ArrayList<Theme>();
1007

    
1008
        // Try to get theme from args
1009
        String name = PluginServices.getArgumentByName("andamiTheme");
1010
        if (name != null) {
1011
            themeFile = new File(name);
1012
            logger.info("search andami-theme in {}", themeFile.getAbsolutePath());
1013
            if (themeFile.exists()) {
1014
                Theme theme = new Theme(loadProperties(infoFile));
1015
                theme.readTheme(themeFile);
1016
                logger.info("andami-theme found in {}", themeFile.getAbsolutePath());
1017
                return theme;
1018
            }
1019
        }
1020

    
1021
        // Try to get theme from a plugin
1022
        File pluginsDir = new File(pluginsDirectory);
1023
        if (!pluginsDir.isAbsolute()) {
1024
            pluginsDir = new File(getApplicationFolder(), pluginsDirectory);
1025
        }
1026
        if (pluginsDir.exists()) {
1027
            logger.info("search andami-theme in plugins folder '" + pluginsDir.getAbsolutePath() + "'.");
1028
            File[] pluginDirs = pluginsDir.listFiles();
1029
            if (pluginDirs.length > 0) {
1030
                for (int i = 0; i < pluginDirs.length; i++) {
1031
                    File pluginThemeFile = new File(pluginDirs[i],
1032
                            "theme" + File.separator + "andami-theme.xml");
1033
                    if (pluginThemeFile.exists()) {
1034
                        Theme theme = new Theme(loadProperties(infoFile));
1035
                        theme.readTheme(pluginThemeFile);
1036
                        themes.add(theme);
1037
                    }
1038
                }
1039
            }
1040
        }
1041

    
1042
        // Try to get theme from dir gvSIG in user home
1043
        themeFile = new File(getAppHomeDir(), "theme" + File.separator
1044
                + "andami-theme.xml");
1045
        logger.info("search andami-theme in user's home {}", themeFile
1046
                .getAbsolutePath());
1047
        if (themeFile.exists()) {
1048
            Theme theme = new Theme(loadProperties(infoFile));
1049
            theme.readTheme(themeFile);
1050
            themes.add(theme);
1051
        }
1052

    
1053
        // Try to get theme from the instalation dir of gvSIG.
1054
        themeFile = new File(getApplicationDirectory(), "theme"
1055
                + File.separator + "andami-theme.xml");
1056
        logger.info("search andami-theme in installation folder {}", themeFile
1057
                .getAbsolutePath());
1058
        if (themeFile.exists()) {
1059
            Theme theme = new Theme(loadProperties(infoFile));
1060
            theme.readTheme(themeFile);
1061
            themes.add(theme);
1062
        }
1063

    
1064
        Collections.sort(themes, new Comparator<Theme>() {
1065
            public int compare(Theme t1, Theme t2) {
1066
                return t2.getPriority() - t1.getPriority();
1067
            }
1068
        });
1069
        if (logger.isInfoEnabled()) {
1070
            logger.info("Found andami-themes in:");
1071
            for (Theme theme : themes) {
1072
                logger.info(" - " + theme.getPriority() + ", " + theme.getSource().getAbsolutePath());
1073
            }
1074
        }
1075
        Theme theme = themes.get(0);
1076
        logger.info("Using theme '" + theme.getSource() + "'.");
1077
        return theme;
1078
    }
1079

    
1080
    /**
1081
     * Establece los datos que tengamos guardados respecto de la configuracion
1082
     * del proxy.
1083
     */
1084
    private void configureProxy() {
1085
        String host = prefs.get("firewall.http.host", "");
1086
        String port = prefs.get("firewall.http.port", "");
1087

    
1088
        System.getProperties().put("http.proxyHost", host);
1089
        System.getProperties().put("http.proxyPort", port);
1090

    
1091
        // Ponemos el usuario y clave del proxy, si existe
1092
        String proxyUser = prefs.get("firewall.http.user", null);
1093
        String proxyPassword = prefs.get("firewall.http.password", null);
1094
        if (proxyUser != null) {
1095
            System.getProperties().put("http.proxyUserName", proxyUser);
1096
            System.getProperties().put("http.proxyPassword", proxyPassword);
1097

    
1098
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
1099
        } else {
1100
            Authenticator.setDefault(new ProxyAuth("", ""));
1101
        }
1102
    }
1103

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

    
1144
    private XMLEntity saveMDIStatus() {
1145
        XMLEntity xml = new XMLEntity();
1146
        // save frame size
1147
        int[] wh = new int[2];
1148
        wh[0] = frame.getWidth();
1149
        wh[1] = frame.getHeight();
1150
        xml.putProperty(MainFrame.MAIN_FRAME_SIZE, wh);
1151
        // save frame location
1152
        int[] xy = new int[2];
1153
        xy[0] = frame.getX();
1154
        xy[1] = frame.getY();
1155
        xml.putProperty(MainFrame.MAIN_FRAME_POS, xy);
1156
        // save frame status
1157
        xml.putProperty(MainFrame.MAIN_FRAME_EXT_STATE,
1158
                frame.getExtendedState());
1159
        return xml;
1160
    }
1161

    
1162
    private boolean validJVM() {
1163
        if (!SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_6)) {
1164
            logger.warn("gvSIG requires Java version 1.6 or higher.");
1165
            logger.warn("The Java HOME is '" + SystemUtils.getJavaHome().getAbsolutePath() + "'.");
1166
            return false;
1167
        }
1168
        if (SystemUtils.isJavaAwtHeadless()) {
1169
            logger.warn("The java used by gvSIG does not contain the libraries for access to the graphical interface (AWT-headless)");
1170
            logger.warn("The Java HOME is '" + SystemUtils.getJavaHome().getAbsolutePath() + "'.");
1171
            return false;
1172
        }
1173
        return true;
1174
    }
1175

    
1176
    private void loadPluginsPersistence() throws ConfigurationException {
1177
        XMLEntity entity = persistenceFromXML();
1178

    
1179
        for (int i = 0; i < entity.getChildrenCount(); i++) {
1180
            XMLEntity plugin = entity.getChild(i);
1181
            String pName = plugin
1182
                    .getStringProperty("com.iver.andami.pluginName");
1183

    
1184
            if (pName.compareToIgnoreCase("com.iver.cit.gvsig") == 0) {
1185
                pName = "org.gvsig.app";
1186
            }
1187
            if (pluginsServices.get(pName) != null) {
1188
                ((PluginServices) pluginsServices.get(pName))
1189
                        .setPersistentXML(plugin);
1190
            } else {
1191
                if (pName.startsWith("Andami.Launcher")) {
1192
                    restoreMDIStatus(plugin);
1193
                }
1194
            }
1195
        }
1196
    }
1197

    
1198
    /**
1199
     * Salva la persistencia de los plugins.
1200
     *
1201
     * @author LWS
1202
     */
1203
    private void savePluginPersistence() {
1204
        Iterator<String> i = pluginsConfig.keySet().iterator();
1205

    
1206
        XMLEntity entity = new XMLEntity();
1207

    
1208
        while (i.hasNext()) {
1209
            String pName = i.next();
1210
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1211
            XMLEntity ent = ps.getPersistentXML();
1212

    
1213
            if (ent != null) {
1214
                ent.putProperty("com.iver.andami.pluginName", pName);
1215
                entity.addChild(ent);
1216
            }
1217
        }
1218
        XMLEntity ent = saveMDIStatus();
1219
        if (ent != null) {
1220
            ent.putProperty("com.iver.andami.pluginName", "Andami.Launcher");
1221
            entity.addChild(ent);
1222
        }
1223
        try {
1224
            persistenceToXML(entity);
1225
        } catch (ConfigurationException e1) {
1226
            this
1227
                    .addError(
1228
                            Messages
1229
                            .getString("Launcher.Se_produjo_un_error_guardando_la_configuracion_de_los_plugins"),
1230
                            e1);
1231
        }
1232
    }
1233

    
1234
    private void installPluginsLabels() {
1235
        Iterator<String> i = pluginsConfig.keySet().iterator();
1236

    
1237
        while (i.hasNext()) {
1238
            String name = i.next();
1239
            PluginConfig pc = pluginsConfig.get(name);
1240
            PluginServices ps = (PluginServices) pluginsServices.get(name);
1241

    
1242
            LabelSet[] ls = pc.getLabelSet();
1243

    
1244
            for (int j = 0; j < ls.length; j++) {
1245
                PluginClassLoader loader = ps.getClassLoader();
1246

    
1247
                try {
1248
                    Class clase = loader.loadClass(ls[j].getClassName());
1249
                    frame.setStatusBarLabels(clase, ls[j].getLabel());
1250
                } catch (Throwable e) {
1251
                    this.addError(
1252
                            Messages.getString("Launcher.labelset_class"), e);
1253
                }
1254
            }
1255
        }
1256
    }
1257

    
1258
    private String configureSkin(XMLEntity xml, String defaultSkin) {
1259
        if (defaultSkin == null) {
1260
            for (int i = 0; i < xml.getChildrenCount(); i++) {
1261
                if (xml.getChild(i).contains("Skin-Selected")) {
1262
                    String className = xml.getChild(i).getStringProperty(
1263
                            "Skin-Selected");
1264
                    return className;
1265
                }
1266
            }
1267
        }
1268
        // return "com.iver.core.mdiManager.NewSkin";
1269
        return defaultSkin;
1270
    }
1271

    
1272
    private void fixSkin(SkinExtension skinExtension,
1273
            PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
1274
        // now insert the skin selected.
1275
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
1276
                // MDIManagerFactory.setSkinExtension(se,
1277
        // ps.getClassLoader());
1278

    
1279
        Class<? extends IExtension> skinClass;
1280

    
1281
        try {
1282
            skinClass = (Class<? extends IExtension>) pluginClassLoader
1283
                    .loadClass(skinExtension.getClassName());
1284

    
1285
            IExtension skinInstance = skinClass.newInstance();
1286
            ExtensionDecorator newExtensionDecorator = new ExtensionDecorator(
1287
                    skinInstance, ExtensionDecorator.INACTIVE);
1288
            classesExtensions.put(skinClass, newExtensionDecorator);
1289
        } catch (ClassNotFoundException e) {
1290
            logger.error(Messages
1291
                    .getString("Launcher.No_se_encontro_la_clase_mdi_manager"),
1292
                    e);
1293
            throw new MDIManagerLoadException(e);
1294
        } catch (InstantiationException e) {
1295
            logger
1296
                    .error(
1297
                            Messages
1298
                            .getString("Launcher.No_se_pudo_instanciar_la_clase_mdi_manager"),
1299
                            e);
1300
            throw new MDIManagerLoadException(e);
1301
        } catch (IllegalAccessException e) {
1302
            logger
1303
                    .error(
1304
                            Messages
1305
                            .getString("Launcher.No_se_pudo_acceder_a_la_clase_mdi_manager"),
1306
                            e);
1307
            throw new MDIManagerLoadException(e);
1308
        }
1309

    
1310
    }
1311

    
1312
    /**
1313
     * DOCUMENT ME!
1314
     *
1315
     * @throws MDIManagerLoadException
1316
     */
1317
    private void skinPlugin(String defaultSkin) throws MDIManagerLoadException {
1318
        XMLEntity entity = null;
1319
        try {
1320
            entity = persistenceFromXML();
1321
        } catch (ConfigurationException e1) {
1322
            // TODO Auto-generated catch block
1323
            e1.printStackTrace();
1324
        }
1325
        Iterator<String> i = pluginsConfig.keySet().iterator();
1326

    
1327
        SkinExtension skinExtension = null;
1328
        PluginClassLoader pluginClassLoader = null;
1329
        List<SkinExtension> skinExtensions = new ArrayList<SkinExtension>();
1330
        while (i.hasNext()) {
1331
            String name = i.next();
1332
            PluginConfig pc = pluginsConfig.get(name);
1333
            PluginServices ps = pluginsServices.get(name);
1334

    
1335
            if (pc.getExtensions().getSkinExtension() != null) {
1336
                                // if (MDIManagerFactory.getSkinExtension() != null) {
1337
                // logger.warn(Messages.getString(
1338
                // "Launcher.Dos_skin_extension"));
1339
                // }
1340

    
1341
                SkinExtension[] se = pc.getExtensions().getSkinExtension();
1342
                for (int numExten = 0; numExten < se.length; numExten++) {
1343
                    skinExtensions.add(se[numExten]);
1344
                }
1345
                for (int j = 0; j < se.length; j++) {
1346
                    String configuredSkin = this.configureSkin(entity,
1347
                            defaultSkin);
1348
                    if ((configuredSkin != null)
1349
                            && configuredSkin.equals(se[j].getClassName())) {
1350
                        skinExtension = se[j];
1351
                        pluginClassLoader = ps.getClassLoader();
1352
                    }
1353
                }
1354
            }
1355
        }
1356

    
1357
        if ((skinExtension != null) && (pluginClassLoader != null)) {
1358
            // configured skin was found
1359
            fixSkin(skinExtension, pluginClassLoader);
1360
        } else {
1361
            if (skinExtensions.contains("com.iver.core.mdiManager.NewSkin")) {
1362
                // try first NewSkin (from CorePlugin)
1363
                skinPlugin("com.iver.core.mdiManager.NewSkin");
1364
            } else if (skinExtensions.size() > 0) {
1365
                // try to load the first skin found
1366
                SkinExtension se = (SkinExtension) skinExtensions.get(0);
1367
                skinPlugin((String) se.getClassName());
1368
            } else {
1369
                throw new MDIManagerLoadException("No Skin-Extension installed");
1370
            }
1371
        }
1372

    
1373
    }
1374

    
1375
    private static void frameIcon(Theme theme) {
1376
        Iterator<String> i = pluginsConfig.keySet().iterator();
1377

    
1378
        while (i.hasNext()) {
1379
            String pName = i.next();
1380
            PluginConfig pc = pluginsConfig.get(pName);
1381
            if (pc.getIcon() != null) {
1382
                if (theme.getIcon() != null) {
1383
                    frame.setIconImage(theme.getIcon().getImage());
1384
                } else {
1385

    
1386
                    ImageIcon icon = PluginServices.getIconTheme().get(
1387
                            pc.getIcon().getSrc());
1388
                    frame.setIconImage(icon.getImage());
1389

    
1390
                }
1391
                if (theme.getName() != null) {
1392
                    frame.setTitlePrefix(theme.getName());
1393
                } else {
1394
                    frame.setTitlePrefix(pc.getIcon().getText());
1395
                }
1396
                if (theme.getBackgroundImage() != null) {
1397

    
1398
                    PluginServices.getMDIManager().setBackgroundImage(
1399
                            theme.getBackgroundImage(), theme.getTypeDesktop());
1400
                }
1401
            }
1402
        }
1403
    }
1404

    
1405
    private void initializeExtensions() {
1406

    
1407
        List<ClassLoader> classLoaders = new ArrayList<ClassLoader>(
1408
                pluginsOrdered.size());
1409
        classLoaders.add(getClass().getClassLoader());
1410
        Iterator<String> iter = pluginsOrdered.iterator();
1411

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

    
1436
            Extension[] exts = pc.getExtensions().getExtension();
1437

    
1438
            TreeSet<Extension> orderedExtensions = new TreeSet<Extension>(
1439
                    new ExtensionComparator());
1440

    
1441
            for (int j = 0; j < exts.length; j++) {
1442
                if (!exts[j].getActive()) {
1443
                    continue;
1444
                }
1445

    
1446
                if (orderedExtensions.contains(exts[j])) {
1447
                    logger.warn("Two extensions with the same priority ("
1448
                            + exts[j].getClassName() + ")");
1449
                }
1450

    
1451
                orderedExtensions.add(exts[j]);
1452
            }
1453

    
1454
            Iterator<Extension> e = orderedExtensions.iterator();
1455

    
1456
            logger.info("Initializing extensions of plugin " + pName + ": ");
1457
            while (e.hasNext()) {
1458
                Extension extension = e.next();
1459
                org.gvsig.andami.plugins.IExtension extensionInstance;
1460

    
1461
                try {
1462
                    logger.info("Initializing " + extension.getClassName()
1463
                            + "...");
1464
                    message(extension.getClassName() + "...");
1465
                    Class<? extends IExtension> extensionClass = (Class<? extends IExtension>) ps
1466
                            .getClassLoader().loadClass(
1467
                                    extension.getClassName());
1468
                    extensionInstance = extensionClass.newInstance();
1469
                    if (extensionInstance instanceof org.gvsig.andami.plugins.Extension) {
1470
                        ((org.gvsig.andami.plugins.Extension) extensionInstance).setPlugin(ps);
1471
                    } else {
1472
                        logger.warn("The extension " + extensionClass.getName() + " don't extends of Extension.");
1473
                    }
1474

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

    
1493
                    extensionInstance.initialize();
1494
                    extensions.add(extensionInstance);
1495

    
1496
                } catch (NoClassDefFoundError e1) {
1497
                    this.addError("Can't find class extension ("
1498
                            + extension.getClassName() + ")", e1);
1499
                } catch (Throwable e1) {
1500
                    this.addError("Can't initialize extension '"
1501
                            + extension.getClassName() + "'.", e1);
1502
                }
1503
            }
1504
        }
1505
    }
1506

    
1507
    private void postInitializeExtensions() {
1508
        logger.info("PostInitializing extensions: ");
1509

    
1510
        for (int i = 0; i < extensions.size(); i++) {
1511
            org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
1512
                    .get(i);
1513
            String name = extensionInstance.getClass().getName();
1514
            logger.info("PostInitializing " + name + "...");
1515
            message(name + "...");
1516
            try {
1517
                extensionInstance.postInitialize();
1518
            } catch (Throwable ex) {
1519
                this.addError("postInitialize of extension '"
1520
                        + extensionInstance.getClass().getName() + "' failed",
1521
                        ex);
1522
            }
1523
        }
1524
    }
1525

    
1526
    private void registerActionOfExtensions(ActionInfoManager actionManager,
1527
            Enumeration<SkinExtensionType> extensiones, ClassLoader loader) {
1528
        ActionInfo actionInfo;
1529
        while (extensiones.hasMoreElements()) {
1530
            SkinExtensionType extension = extensiones.nextElement();
1531
            Class<? extends IExtension> classExtension;
1532
            try {
1533
                classExtension = (Class<? extends IExtension>) loader
1534
                        .loadClass(extension.getClassName());
1535

    
1536
                Enumeration<Action> actions = extension.enumerateAction();
1537
                while (actions.hasMoreElements()) {
1538
                    Action action = actions.nextElement();
1539
                    if (action.getName() == null) {
1540
                        logger.info("invalid action name (null) in " + extension.getClassName() + " of " + loader.toString());
1541
                    } else {
1542
                        actionInfo = actionManager.createAction(
1543
                                classExtension, action.getName(),
1544
                                action.getLabel(), action.getActionCommand(),
1545
                                action.getIcon(), action.getAccelerator(), action.getPosition(),
1546
                                action.getTooltip());
1547
                        actionManager.registerAction(actionInfo);
1548
                        if (action.getPosition() < 100000000) {
1549
                            logger.info("Invalid position in action (" + actionInfo.toString() + ").");
1550
                            action.setPosition(action.getPosition() + 1000000000);
1551
                        }
1552
                    }
1553
                }
1554

    
1555
                Enumeration<Menu> menus = extension.enumerateMenu();
1556
                while (menus.hasMoreElements()) {
1557
                    Menu menu = menus.nextElement();
1558
                    if (!menu.getIs_separator()) {
1559
                        actionInfo = actionManager.createAction(
1560
                                classExtension, menu.getName(), menu.getText(),
1561
                                menu.getActionCommand(), menu.getIcon(),
1562
                                menu.getKey(), menu.getPosition(),
1563
                                menu.getTooltip());
1564
                        actionInfo = actionManager.registerAction(actionInfo);
1565
                        if (actionInfo != null) {
1566
                            menu.setActionCommand(actionInfo.getCommand());
1567
                            menu.setTooltip(actionInfo.getTooltip());
1568
                            menu.setIcon(actionInfo.getIconName());
1569
                            menu.setPosition(actionInfo.getPosition());
1570
                            menu.setKey(actionInfo.getAccelerator());
1571
                            menu.setName(actionInfo.getName());
1572
                        }
1573
                    }
1574
                    if (menu.getPosition() < 100000000) {
1575
                        logger.info("Invalid position in menu (" + menu.getText() + ").");
1576
                        menu.setPosition(menu.getPosition() + 1000000000);
1577
                    }
1578

    
1579
                }
1580
                Enumeration<ToolBar> toolBars = extension.enumerateToolBar();
1581
                while (toolBars.hasMoreElements()) {
1582
                    ToolBar toolBar = toolBars.nextElement();
1583

    
1584
                    Enumeration<ActionTool> actionTools = toolBar
1585
                            .enumerateActionTool();
1586
                    while (actionTools.hasMoreElements()) {
1587
                        ActionTool actionTool = actionTools.nextElement();
1588
                        actionInfo = actionManager.createAction(
1589
                                classExtension, actionTool.getName(),
1590
                                actionTool.getText(),
1591
                                actionTool.getActionCommand(),
1592
                                actionTool.getIcon(),
1593
                                null,
1594
                                actionTool.getPosition(),
1595
                                actionTool.getTooltip());
1596
                        actionInfo = actionManager.registerAction(actionInfo);
1597
                        if (actionInfo != null) {
1598
                            actionTool.setActionCommand(actionInfo.getCommand());
1599
                            actionTool.setTooltip(actionInfo.getTooltip());
1600
                            actionTool.setIcon(actionInfo.getIconName());
1601
                            actionTool.setPosition(actionInfo.getPosition());
1602
                            actionTool.setName(actionInfo.getName());
1603
                        }
1604
                    }
1605

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

    
1637
    @SuppressWarnings("unchecked")
1638
    private void registerActions() {
1639
        logger.info("registerActions");
1640

    
1641
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1642
        Iterator<String> it = pluginsConfig.keySet().iterator();
1643

    
1644
        while (it.hasNext()) {
1645
            String pluginName = it.next();
1646
            PluginConfig pluginConfig = pluginsConfig.get(pluginName);
1647
            PluginServices pluginService = pluginsServices.get(pluginName);
1648
            PluginClassLoader loader = pluginService.getClassLoader();
1649

    
1650
            logger.info("registerActions of plugin '" + pluginName + "'.");
1651

    
1652
            Extensions extensionConfig = pluginConfig.getExtensions();
1653

    
1654
            Enumeration<SkinExtensionType> extensiones = extensionConfig.enumerateExtension();
1655
            registerActionOfExtensions(actionManager, extensiones, loader);
1656

    
1657
            Enumeration<SkinExtensionType> skinSxtensiones = extensionConfig.enumerateSkinExtension();
1658
            registerActionOfExtensions(actionManager, skinSxtensiones, loader);
1659

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

    
1687
        }
1688
    }
1689

    
1690
    private TreeSet<SortableMenu> getOrderedMenus() {
1691

    
1692
        TreeSet<SortableMenu> orderedMenus = new TreeSet<SortableMenu>(
1693
                new MenuComparator());
1694

    
1695
        Iterator<String> i = pluginsConfig.keySet().iterator();
1696

    
1697
        while (i.hasNext()) {
1698
            String pName = i.next();
1699
            try {
1700
                PluginServices ps = pluginsServices.get(pName);
1701
                PluginConfig pc = pluginsConfig.get(pName);
1702

    
1703
                Extension[] exts = pc.getExtensions().getExtension();
1704

    
1705
                for (int j = 0; j < exts.length; j++) {
1706
                    if (!exts[j].getActive()) {
1707
                        continue;
1708
                    }
1709

    
1710
                    Menu[] menus = exts[j].getMenu();
1711

    
1712
                    for (int k = 0; k < menus.length; k++) {
1713
                        SortableMenu sm = new SortableMenu(ps.getClassLoader(),
1714
                                exts[j], menus[k]);
1715

    
1716
                        if (orderedMenus.contains(sm)) {
1717
                            this
1718
                                    .addError(Messages
1719
                                            .getString("Launcher.Two_menus_with_the_same_position")
1720
                                            + " - "
1721
                                            + menus[k].getText()
1722
                                            + " - " + exts[j].getClassName());
1723
                        }
1724

    
1725
                        orderedMenus.add(sm);
1726
                    }
1727
                }
1728

    
1729
                // Se instalan las extensiones de MDI
1730
                SkinExtension[] skinExts = pc.getExtensions()
1731
                        .getSkinExtension();
1732
                for (int j = 0; j < skinExts.length; j++) {
1733

    
1734
                    if (skinExts[j] != null) {
1735
                        Menu[] menu = skinExts[j].getMenu();
1736

    
1737
                        for (int k = 0; k < menu.length; k++) {
1738
                            SortableMenu sm = new SortableMenu(ps
1739
                                    .getClassLoader(), skinExts[j], menu[k]);
1740

    
1741
                            if (orderedMenus.contains(sm)) {
1742
                                this
1743
                                        .addError(Messages
1744
                                                .getString("Launcher.Two_menus_with_the_same_position")
1745
                                                + skinExts[j].getClassName());
1746
                            }
1747

    
1748
                            orderedMenus.add(sm);
1749
                        }
1750
                    }
1751
                }
1752

    
1753
            } catch (Throwable e) {
1754
                addError("Error initializing menus of plugin '" + pName + "'",
1755
                        e);
1756
            }
1757

    
1758
        }
1759

    
1760
        return orderedMenus;
1761
    }
1762

    
1763
    private void installPluginsMenus() {
1764
        logger.info("installPluginsMenus");
1765

    
1766
        TreeSet<SortableMenu> orderedMenus = getOrderedMenus();
1767

    
1768
        // Se itera por los menus ordenados
1769
        Iterator<SortableMenu> e = orderedMenus.iterator();
1770

    
1771
        // Se ordenan los menues
1772
        while (e.hasNext()) {
1773
            try {
1774
                SortableMenu sm = e.next();
1775
                logger.debug(sm.menu.getPosition() + ":" + sm.menu.getText() + ":" + sm.loader.getPluginName() + ":" + sm.extension.getClassName());
1776
                frame.addMenu(sm.loader, sm.extension, sm.menu);
1777
            } catch (Throwable ex) {
1778
                this.addError(
1779
                        Messages.getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1780
                        ex
1781
                );
1782
            }
1783
        }
1784
    }
1785

    
1786
    public class PluginMenuItem {
1787

    
1788
        private Menu menu;
1789
        private PluginClassLoader loader;
1790
        private SkinExtensionType extension;
1791

    
1792
        PluginMenuItem(PluginClassLoader loader,
1793
                SkinExtensionType extension, Menu menu) {
1794
            this.menu = menu;
1795
            this.loader = loader;
1796
            this.extension = extension;
1797
        }
1798

    
1799
        public PluginServices getPlugin() {
1800
            String pluginName = loader.getPluginName();
1801
            return PluginServices.getPluginServices(pluginName);
1802
        }
1803

    
1804
        public String getExtensionName() {
1805
            return this.extension.getClassName();
1806
        }
1807

    
1808
        public IExtension getExtension() {
1809
            Class<?> extensionClass;
1810
            try {
1811
                extensionClass = loader.loadClass(this.extension.getClassName());
1812
            } catch (ClassNotFoundException e) {
1813
                return null;
1814
            }
1815
            return PluginServices.getExtension(extensionClass);
1816
        }
1817

    
1818
        public String getText() {
1819
            return this.menu.getText();
1820
        }
1821

    
1822
        public long getPosition() {
1823
            return this.menu.getPosition();
1824
        }
1825

    
1826
        public String getName() {
1827
            return this.menu.getName();
1828
        }
1829

    
1830
        public boolean isParent() {
1831
            return menu.getIs_separator();
1832
        }
1833

    
1834
        public String getPluginName() {
1835
            return this.loader.getPluginName();
1836
        }
1837

    
1838
        public ActionInfo getAction() {
1839
            ActionInfoManager manager = PluginsLocator.getActionInfoManager();
1840
            return manager.getAction(this.menu.getName());
1841
        }
1842
    }
1843

    
1844
    public List<PluginMenuItem> getPluginMenuItems() {
1845
        List<PluginMenuItem> menuItems = new ArrayList<Launcher.PluginMenuItem>();
1846

    
1847
        TreeSet<SortableMenu> orderedMenus = getOrderedMenus();
1848
        Iterator<SortableMenu> e = orderedMenus.iterator();
1849
        while (e.hasNext()) {
1850
            SortableMenu sm = e.next();
1851
            PluginMenuItem item = new PluginMenuItem(sm.loader, sm.extension, sm.menu);
1852
            menuItems.add(item);
1853
        }
1854
        return menuItems;
1855
    }
1856

    
1857
    private List<ToolBar> getOrderedToolBars() {
1858
        Map<String, ToolBar> toolbars = new HashMap<>();
1859

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

    
1894
            @Override
1895
            public int compare(ToolBar o1, ToolBar o2) {
1896
                return Integer.compare(o1.getPosition(), o2.getPosition());
1897
            }
1898
        });
1899
        return toolBarsList;        
1900
    }
1901
    
1902
    /**
1903
     * Installs the menus, toolbars, actiontools, selectable toolbars and
1904
     * combos. The order in which they are shown is determined here.
1905
     */
1906
    private void installPluginsControls() {
1907
        logger.info("installPluginsControls (toolbars)");
1908

    
1909
        Iterator<String> pluginNames = pluginsConfig.keySet().iterator();
1910

    
1911
        Map<Extension, PluginServices> extensionPluginServices = new HashMap<Extension, PluginServices>();
1912
        Map<Extension, PluginConfig> extensionPluginConfig = new HashMap<Extension, PluginConfig>();
1913
        Set<Extension> orderedExtensions = new TreeSet<Extension>(
1914
                new ExtensionComparator());
1915

    
1916
                // First of all, sort the extensions.
1917
        // We need to iterate on the plugins, and iterate on each plugin's
1918
        // extensions
1919
        // (each plugin may contain one or more extensions)
1920
        while (pluginNames.hasNext()) { // iterate on the plugins
1921
            String pluginName = pluginNames.next();
1922
            try {
1923
                PluginConfig pc = pluginsConfig.get(pluginName);
1924
                PluginServices ps = pluginsServices.get(pluginName);
1925

    
1926
                Extension[] exts = pc.getExtensions().getExtension();
1927

    
1928
                for (int j = 0; j < exts.length; j++) { // iterate on the
1929
                    // extensions
1930
                    String cname = "unknow";
1931
                    try {
1932
                        cname = exts[j].getClassName();
1933
                        if (exts[j].getActive()
1934
                                && !cname.equals(LibraryExtension.class
1935
                                        .getName())) {
1936
                            if (orderedExtensions.contains(exts[j])) {
1937
                                this
1938
                                        .addError(Messages
1939
                                                .getString("Launcher.Two_extensions_with_the_same_priority")
1940
                                                + cname);
1941
                            }
1942

    
1943
                            orderedExtensions.add(exts[j]);
1944
                            extensionPluginServices.put(exts[j], ps);
1945
                            extensionPluginConfig.put(exts[j], pc);
1946
                        }
1947
                    } catch (Throwable e) {
1948
                        addError("Error initializing controls of plugin '"
1949
                                + pluginName + "' extension '" + cname + "'", e);
1950
                    }
1951
                }
1952
            } catch (Throwable e) {
1953
                addError("Error initializing controls of plugin '" + pluginName
1954
                        + "'", e);
1955
            }
1956
        }
1957

    
1958
        
1959
        // A?ade primero las toolbars ordenadas para garantizar el orden de estas
1960
        for( ToolBar toolbar : getOrderedToolBars() ) {
1961
            frame.addToolBar(toolbar.getName(), toolbar.getDescription(), toolbar.getPosition());
1962
        }
1963

    
1964
        TreeSet<SortableTool> orderedTools = new TreeSet<SortableTool>(
1965
                new ToolComparator());
1966
        Iterator<Extension> e = orderedExtensions.iterator();
1967

    
1968
                // sort the toolbars and tools from 'normal' extensions (actiontools,
1969
        // selectabletools)
1970
        // and load the combo-scales and combo-buttons for the status bar
1971
        while (e.hasNext()) {
1972
            Extension ext = e.next();
1973
            String extName = "unknow";
1974
            try {
1975
                extName = ext.getClassName();
1976
                ToolBar[] toolbars = ext.getToolBar();
1977

    
1978
                // get tools from toolbars
1979
                for (int k = 0; k < toolbars.length; k++) {
1980
                    ActionTool[] tools = toolbars[k].getActionTool();
1981

    
1982
                    for (int t = 0; t < tools.length; t++) {
1983
                        SortableTool sm = new SortableTool(
1984
                                (extensionPluginServices.get(ext))
1985
                                .getClassLoader(), ext, toolbars[k],
1986
                                tools[t]);
1987
                        orderedTools.add(sm);
1988
                    }
1989

    
1990
                    SelectableTool[] sTools = toolbars[k].getSelectableTool();
1991

    
1992
                    for (int t = 0; t < sTools.length; t++) {
1993
                        SortableTool sm = new SortableTool(
1994
                                (extensionPluginServices.get(ext))
1995
                                .getClassLoader(), ext, toolbars[k],
1996
                                sTools[t]);
1997
                        orderedTools.add(sm);
1998
                    }
1999
                }
2000

    
2001
                // get controls for statusBar
2002
                PluginServices ps = extensionPluginServices.get(ext);
2003
                PluginClassLoader loader = ps.getClassLoader();
2004

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

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

    
2099
                // Add the tools from MDI extensions to the ordered tool-list, so that
2100
        // we get a sorted list containing all the tools
2101
        pluginNames = pluginsConfig.keySet().iterator();
2102
        while (pluginNames.hasNext()) {
2103
            String pName = (String) pluginNames.next();
2104
            try {
2105
                PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
2106
                PluginServices ps = (PluginServices) pluginsServices.get(pName);
2107

    
2108
                SkinExtension[] skinExts = pc.getExtensions()
2109
                        .getSkinExtension();
2110
                for (int j = 0; j < skinExts.length; j++) {
2111

    
2112
                    if (skinExts[j] != null) {
2113
                        ToolBar[] toolbars = skinExts[j].getToolBar();
2114

    
2115
                        for (int k = 0; k < toolbars.length; k++) {
2116
                            ActionTool[] tools = toolbars[k].getActionTool();
2117

    
2118
                            for (int t = 0; t < tools.length; t++) {
2119
                                SortableTool stb = new SortableTool(ps
2120
                                        .getClassLoader(), skinExts[j],
2121
                                        toolbars[k], tools[t]);
2122
                                orderedTools.add(stb);
2123
                            }
2124

    
2125
                            SelectableTool[] sTools = toolbars[k]
2126
                                    .getSelectableTool();
2127

    
2128
                            for (int t = 0; t < sTools.length; t++) {
2129
                                SortableTool stb = new SortableTool(ps
2130
                                        .getClassLoader(), skinExts[j],
2131
                                        toolbars[k], sTools[t]);
2132
                                orderedTools.add(stb);
2133
                            }
2134
                        }
2135
                    }
2136
                }
2137
                // Install popup menus
2138
                PopupMenus pus = pc.getPopupMenus();
2139
                if (pus != null) {
2140
                    PopupMenu[] menus = pus.getPopupMenu();
2141
                    for (int j = 0; j < menus.length; j++) {
2142
                        String menuName = "(unknow)";
2143
                        try {
2144
                            menuName = menus[j].getName();
2145
                            frame.addPopupMenu(ps.getClassLoader(), menus[j]);
2146
                        } catch (Throwable ex) {
2147
                            addError("Error adding popup menu' " + menuName + "' in plugin '" + pName + "'.");
2148
                        }
2149
                    }
2150
                }
2151
            } catch (Throwable e3) {
2152
                addError("Error initializing skins of the plugin '" + pName
2153
                        + "'", e3);
2154
            }
2155
        }
2156

    
2157
                // loop on the ordered extension list, to add them to the interface in
2158
        // an ordered way
2159
        Iterator<SortableTool> t = orderedTools.iterator();
2160
        while (t.hasNext()) {
2161
            SortableTool stb = t.next();
2162
            try {
2163
                if (stb.actiontool != null) {
2164
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
2165
                            stb.actiontool);
2166
                } else {
2167
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
2168
                            stb.selectabletool);
2169
                }
2170
            } catch (ClassNotFoundException ex) {
2171
                this
2172
                        .addError(
2173
                                Messages
2174
                                .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
2175
                                ex);
2176
            } catch (Throwable e2) {
2177
                addError("Error adding tools to the interface of extension '"
2178
                        + stb.extension.getClassName() + "'", e2);
2179
            }
2180
        }
2181
    }
2182

    
2183
    /**
2184
     * Adds new plugins to the the andami-config file.
2185
     */
2186
    private void updateAndamiConfig() {
2187
        Set<String> olds = new HashSet<String>();
2188

    
2189
        Plugin[] plugins = andamiConfig.getPlugin();
2190

    
2191
        for (int i = 0; i < plugins.length; i++) {
2192
            olds.add(plugins[i].getName());
2193
        }
2194

    
2195
        Iterator<PluginServices> i = pluginsServices.values().iterator();
2196

    
2197
        while (i.hasNext()) {
2198
            PluginServices ps = i.next();
2199

    
2200
            if (!olds.contains(ps.getPluginName())) {
2201
                Plugin p = new Plugin();
2202
                p.setName(ps.getPluginName());
2203
                p.setUpdate(false);
2204

    
2205
                andamiConfig.addPlugin(p);
2206
            }
2207
        }
2208
    }
2209

    
2210
    private URL[] getPluginClasspathURLs(PluginConfig pluginConfig) {
2211
        URL[] urls = null;
2212

    
2213
        String libfolderPath = pluginConfig.getLibraries().getLibraryDir();
2214
        File libFolderFile = new File(pluginConfig.getPluginFolder(), libfolderPath);
2215

    
2216
        File[] files = libFolderFile.listFiles(new FileFilter() {
2217

    
2218
            public boolean accept(File pathname) {
2219
                return (pathname.getName().toUpperCase().endsWith(".JAR")
2220
                        || pathname.getName().toUpperCase().endsWith(".ZIP"));
2221
            }
2222
        });
2223
        if (files == null) {
2224
            urls = new URL[0];
2225
        } else {
2226
            urls = new URL[files.length];
2227
            for (int j = 0; j < files.length; j++) {
2228
                try {
2229
                    urls[j] = new URL("file:" + files[j]);
2230
                } catch (MalformedURLException e) {
2231
                    logger.warn("Can't add file '" + files[j] + "' to the classpath of plugin '" + pluginConfig.getPluginName() + "'.");
2232
                }
2233
            }
2234
        }
2235
        return urls;
2236
    }
2237

    
2238
    private static class OrderedPlugins extends ArrayList<String> {
2239
        
2240
        private List<String> problems = new ArrayList<String>();
2241
        private int retries = 0;
2242
        private PluginsConfig pluginsConfig = null;
2243
        private List<String> deprcatedPluginNames = null;
2244
        
2245
        OrderedPlugins(PluginsConfig pluginsConfig, List<String>deprcatedPluginNames) {
2246
            super();
2247
            this.pluginsConfig = pluginsConfig;
2248
            this.deprcatedPluginNames = deprcatedPluginNames;
2249
            List<String> pluginNames = new ArrayList<String>();
2250
            for (String pluginName : pluginsConfig.keySet()) {
2251
                pluginNames.add(pluginName);
2252
            }
2253
            Collections.sort(pluginNames);
2254
            for (String pluginName : pluginNames) {
2255
                this.add(pluginName);
2256
            }
2257
        }
2258
        
2259
        public List<String> getProblems() {
2260
            return this.problems;
2261
        }
2262
 
2263
        private void addProblem(String msg) {
2264
           this.problems.add(msg);
2265
        }
2266
    
2267
        public boolean add(String pluginName) {
2268
            return this.add(pluginName,new ArrayList<String>());
2269
        }
2270
        
2271
        private boolean add(String pluginName, List<String>processing) {
2272
            pluginName = this.pluginsConfig.getMainKey(pluginName);
2273
            if( this.contains(pluginName) ) {
2274
                return true;
2275
            }
2276
            if( processing.contains(pluginName) ) {
2277
                this.addProblem("Dependencias ciclicas procesando '"+pluginName+"'.");
2278
                return true;
2279
            }
2280
            PluginConfig pluginConfig = this.pluginsConfig.get(pluginName);
2281
            Depends[] dependencies = pluginConfig.getDepends();
2282
            if( dependencies.length==0 ) {
2283
               super.add(pluginName);
2284
               return true;
2285
            }
2286
            if( this.retries > 100 ) {
2287
               this.addProblem("Posible dependencias ciclicas procesando '"+pluginName+"'." );
2288
               return false;
2289
            }
2290
            processing.add(pluginName);
2291
            boolean dependenciesAvailables = true;
2292
            for (Depends dependency : dependencies) {
2293
                String dependencyName = dependency.getPluginName();
2294
                if (deprcatedPluginNames.contains(dependencyName)) {
2295
                    this.addProblem("Plugin '" + pluginName + "' use a deprecated plugin name '" + dependencyName + "' as dependency. Must use '" + pluginsConfig.getMainKey(dependencyName) + "'.");
2296
                }                
2297
                PluginConfig dependencyConfig = this.pluginsConfig.get(dependencyName);
2298
                if( dependencyConfig == null) {
2299
                  if( dependency.getOptional() ) {
2300
                    this.addProblem("Plugin '" + pluginName + "', declare an optional dependency '" + dependencyName + "' that not found.");
2301
                    continue;
2302
                  }
2303
                  dependenciesAvailables = false;
2304
                  this.addProblem("Plugin '"+pluginName+"' declara a dependency '"+dependencyName+"' that not found.");
2305
                  continue;
2306
                }
2307
                this.retries++;
2308
                if( ! (this.add(dependencyName, processing)) ) {
2309
                  dependenciesAvailables = false;
2310
                }
2311
                this.retries--;
2312
            }
2313
            if( dependenciesAvailables ) {
2314
                super.add(pluginName);
2315
            } else {
2316
              this.addProblem("Plugin '"+pluginName+"' no disponible, alguna dependencia no resuelta.");
2317
              return false;
2318
            }
2319
            return true;
2320
        }      
2321
    }
2322
            
2323
    private void loadPluginServices() {
2324
        OrderedPlugins orderedPlugins = new OrderedPlugins(pluginsConfig, getDeprecatedPluginNames());
2325
        
2326
        if( !orderedPlugins.getProblems().isEmpty() ) {
2327
            for (String problem : orderedPlugins.getProblems()) {
2328
                logger.warn(problem);
2329
            }
2330
        }
2331

    
2332
        for (String pluginName : orderedPlugins) {
2333
            PluginConfig config = pluginsConfig.get(pluginName);
2334

    
2335
            URL[] urls = getPluginClasspathURLs(config);
2336
            
2337
            List<PluginClassLoader> loaders = new ArrayList<PluginClassLoader>();
2338
            for (Depends dependency : config.getDepends()) {
2339
                String dependencyName = dependency.getPluginName();
2340
                PluginServices dependencyPluginService = pluginsServices.get(dependencyName);
2341
                if( dependencyPluginService == null ) {
2342
                    if( dependency.getOptional() ) {
2343
                        logger.info("Procesing plugin '"+pluginName+", optional dependency not found ("+dependencyName+").");
2344
                    } else {
2345
                        logger.warn("Procesing plugin '"+pluginName+", dependency not found ("+dependencyName+").");
2346
                    }
2347
                    continue;
2348
                }
2349
                loaders.add(dependencyPluginService.getClassLoader());
2350
            }
2351
            try {
2352
                PluginClassLoader loader = new PluginClassLoader(
2353
                        urls,
2354
                        config.getPluginFolder().getAbsolutePath(),
2355
                        Launcher.class.getClassLoader(),
2356
                        loaders
2357
                );
2358
                PluginServices ps = new PluginServices(
2359
                        loader,
2360
                        PluginsConfig.getAlternativeNames(config)
2361
                );
2362
                logger.info("Plugin '" + pluginName + "' created");
2363
                pluginsServices.put(ps.getPluginName(), ps);
2364
                pluginsOrdered.add(pluginName);
2365
            } catch (IOException ex) {
2366
                logger.warn("Can't create PluginServices for '" + pluginName + "'.", ex);
2367
            }
2368
        }
2369
        
2370
        // Se eliminan los plugins que no fueron instalados
2371
        List<String> pluginsToRemove = new ArrayList<String>();
2372
        for (String pluginName : pluginsConfig.keySet()) {
2373
            PluginServices pluginService = pluginsServices.get(pluginName);
2374
            if( pluginService == null ) {
2375
                pluginsToRemove.add(pluginName);
2376
            } 
2377
        }
2378
        for (String pluginName : pluginsToRemove) {
2379
            logger.warn("Removed plugin "+pluginName+".");
2380
            pluginsConfig.remove(pluginName);
2381
       }
2382
    }
2383
 
2384
    /*
2385
    private void dumpPluginsDependencyInformation() {
2386
        logger.info("Plugin dependency information");
2387
        Iterator<String> i = pluginsConfig.keySet().iterator();
2388
        while (i.hasNext()) {
2389
            String pluginName = i.next();
2390
            PluginConfig config = (PluginConfig) pluginsConfig.get(pluginName);
2391
            logger.info("  Plugin " + pluginName);
2392
            Depends[] dependencies = config.getDepends();
2393
            for (int j = 0; j < dependencies.length; j++) {
2394
                Depends dependency = dependencies[j];
2395
                String dependencyName = dependency.getPluginName();
2396
                logger.info("    Dependency " + dependencyName);
2397
            }
2398
        }
2399
    }
2400
    */
2401
    private void pluginsMessages() {
2402
        Iterator<String> iterator = pluginsOrdered.iterator();
2403
        PluginConfig config;
2404
        PluginServices ps;
2405

    
2406
        while (iterator.hasNext()) {
2407
            String pluginName = iterator.next();
2408
            config = pluginsConfig.get(pluginName);
2409
            ps = pluginsServices.get(pluginName);
2410

    
2411
            if ((config.getResourceBundle() != null)
2412
                    && !config.getResourceBundle().getName().equals("")) {
2413
                // add the locale files associated with the plugin
2414
                org.gvsig.i18n.Messages.addResourceFamily(config
2415
                        .getResourceBundle().getName(), ps.getClassLoader(),
2416
                        pluginName);
2417
                org.gvsig.i18n.Messages.addResourceFamily("i18n." + config
2418
                        .getResourceBundle().getName(), ps.getClassLoader(),
2419
                        pluginName);
2420
            }
2421
        }
2422
    }
2423

    
2424
    static public PluginServices getPluginServices(String name) {
2425
        return (PluginServices) pluginsServices.get(name);
2426
    }
2427

    
2428
    static String getPluginsDir() {
2429
        return andamiConfig.getPluginsDirectory();
2430
    }
2431

    
2432
    static File getPluginFolder(String pluginName) {
2433
        return pluginsConfig.get(pluginName).getPluginFolder();
2434
    }
2435

    
2436
    static void setPluginsDir(String s) {
2437
        andamiConfig.setPluginsDirectory(s);
2438
    }
2439

    
2440
    static MDIFrame getMDIFrame() {
2441
        return frame;
2442
    }
2443

    
2444
    private PluginsConfig loadPluginConfigs() {
2445
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
2446
        List<File> repositoriesFolders = installerManager.getLocalAddonRepositories("plugin");
2447
        for (File repositoryFolder : repositoriesFolders) {
2448
            logger.info("Loading plugins configuration from repository folder " + repositoryFolder.getAbsolutePath() + ".");
2449

    
2450
            if (!repositoryFolder.exists()) {
2451
                logger.warn("Plugins repository folder not found '" + repositoryFolder.getAbsolutePath() + "'.");
2452
                continue;
2453
            }
2454

    
2455
            File[] pluginsFolders = repositoryFolder.listFiles();
2456
            if (pluginsFolders.length == 0) {
2457
                logger.info("Plugins repository folder is empty '" + repositoryFolder.getAbsolutePath() + "'.");
2458
                continue;
2459
            }
2460

    
2461
            for (int i = 0; i < pluginsFolders.length; i++) {
2462
                File pluginFolder = pluginsFolders[i];
2463
                if (!pluginFolder.isDirectory()) {
2464
                    continue;
2465
                }
2466
                String pluginName = pluginFolder.getName();
2467
                File pluginConfigFile = new File(pluginFolder, "config.xml");
2468
                if (!pluginConfigFile.exists()) {
2469
                    logger.info("Plugin '" + pluginName + "' not has a config.xml file (" + pluginConfigFile.getAbsolutePath() + ".");
2470
                    continue;
2471
                }
2472
                try {
2473
                    FileInputStream is = new FileInputStream(pluginConfigFile);
2474
                    Reader xml = org.gvsig.utils.xml.XMLEncodingUtils.getReader(is);
2475
                    if (xml == null) {
2476
                        // the encoding was not correctly detected, use system default
2477
                        xml = new FileReader(pluginConfigFile);
2478
                    } else {
2479
                        // use a buffered reader to improve performance
2480
                        xml = new BufferedReader(xml);
2481
                    }
2482
                    PluginConfig pluginConfig = (PluginConfig) PluginConfig.unmarshal(xml);
2483
                    pluginConfig.setPluginName(pluginName);
2484
                    pluginConfig.setPluginFolder(pluginFolder);
2485
                    pluginsConfig.put(pluginName, pluginConfig);
2486

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

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

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

    
2496
                }
2497
            }
2498
        }
2499
        return pluginsConfig;
2500
    }
2501

    
2502
    private static Locale getLocale(String language, String country,
2503
            String variant) {
2504
        if (variant != null) {
2505
            return new Locale(language, country, variant);
2506
        } else if (country != null) {
2507
            return new Locale(language, country);
2508
        } else if (language != null) {
2509
            return new Locale(language);
2510
        } else {
2511
            return new Locale("es");
2512
        }
2513
    }
2514

    
2515
    private static void andamiConfigToXML(String file) throws IOException,
2516
            MarshalException, ValidationException {
2517
                // write on a temporary file in order to not destroy current file if
2518
        // there is some problem while marshaling
2519
        File tmpFile = new File(file + "-"
2520
                + DateTime.getCurrentDate().getTime());
2521
        File xml = new File(file);
2522
        File parent = xml.getParentFile();
2523
        parent.mkdirs();
2524

    
2525
        BufferedOutputStream os = new BufferedOutputStream(
2526
                new FileOutputStream(tmpFile));
2527
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
2528
        andamiConfig.marshal(writer);
2529
        writer.close();
2530

    
2531
                // if marshaling process finished correctly, move the file to the
2532
        // correct one
2533
        xml.delete();
2534
        if (!tmpFile.renameTo(xml)) {
2535
            // if rename was not succesful, try copying it
2536
            FileChannel sourceChannel = new FileInputStream(tmpFile)
2537
                    .getChannel();
2538
            FileChannel destinationChannel = new FileOutputStream(xml)
2539
                    .getChannel();
2540
            sourceChannel.transferTo(0, sourceChannel.size(),
2541
                    destinationChannel);
2542
            sourceChannel.close();
2543
            destinationChannel.close();
2544
        }
2545
    }
2546

    
2547
    private static void andamiConfigFromXML(String file)
2548
            throws ConfigurationException {
2549
        File xml = new File(file);
2550

    
2551
        InputStreamReader reader = null;
2552
        try {
2553
            // Se lee la configuraci?n
2554
            reader = XMLEncodingUtils.getReader(xml);
2555
            andamiConfig = (AndamiConfig) AndamiConfig.unmarshal(reader);
2556
        } catch (FileNotFoundException e) {
2557
            // Si no existe se ponen los valores por defecto
2558
            andamiConfig = getDefaultAndamiConfig();
2559
        } catch (MarshalException e) {
2560
            // try to close the stream, maybe it remains open
2561
            if (reader != null) {
2562
                try {
2563
                    reader.close();
2564
                } catch (IOException e1) {
2565
                }
2566
            }
2567
                        // if there was a problem reading the file, backup it and create a
2568
            // new one with default values
2569
            String backupFile = file + "-"
2570
                    + DateTime.getCurrentDate().getTime();
2571
            NotificationManager
2572
                    .addError(
2573
                            Messages
2574
                            .getString("Error_reading_andami_config_New_file_created_A_backup_was_made_on_")
2575
                            + backupFile, new ConfigurationException(e));
2576
            xml.renameTo(new File(backupFile));
2577
            andamiConfig = getDefaultAndamiConfig();
2578
        } catch (ValidationException e) {
2579
            throw new ConfigurationException(e);
2580
        }
2581
    }
2582

    
2583
    private static AndamiConfig getDefaultAndamiConfig() {
2584
        AndamiConfig andamiConfig = new AndamiConfig();
2585

    
2586
        Andami andami = new Andami();
2587
        andami.setUpdate(true);
2588
        andamiConfig.setAndami(andami);
2589
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
2590
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
2591
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
2592

    
2593
        if (System.getProperty("javawebstart.version") != null) // Es java web
2594
        // start)
2595
        {
2596
            andamiConfig
2597
                    .setPluginsDirectory(new File(appHomeDir, "extensiones")
2598
                            .getAbsolutePath());
2599
        } else {
2600
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
2601
                    .getAbsolutePath());
2602
        }
2603

    
2604
        andamiConfig.setPlugin(new Plugin[0]);
2605
        return andamiConfig;
2606
    }
2607

    
2608
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
2609
        File xml = getPluginsPersistenceFile(true);
2610

    
2611
        if (xml.exists()) {
2612
            InputStreamReader reader = null;
2613

    
2614
            try {
2615
                reader = XMLEncodingUtils.getReader(xml);
2616
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2617
                return new XMLEntity(tag);
2618
            } catch (FileNotFoundException e) {
2619
                throw new ConfigurationException(e);
2620
            } catch (MarshalException e) {
2621

    
2622
                                // try to reopen with default encoding (for backward
2623
                // compatibility)
2624
                try {
2625
                    reader = new FileReader(xml);
2626
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2627
                    return new XMLEntity(tag);
2628

    
2629
                } catch (MarshalException ex) {
2630
                    // try to close the stream, maybe it remains open
2631
                    if (reader != null) {
2632
                        try {
2633
                            reader.close();
2634
                        } catch (IOException e1) {
2635
                        }
2636
                    }
2637
                    // backup the old file
2638
                    String backupFile = getPluginsPersistenceFile(true)
2639
                            .getPath()
2640
                            + "-" + DateTime.getCurrentDate().getTime();
2641
                    NotificationManager
2642
                            .addError(
2643
                                    Messages
2644
                                    .getString("Error_reading_plugin_persinstence_New_file_created_A_backup_was_made_on_")
2645
                                    + backupFile,
2646
                                    new ConfigurationException(e));
2647
                    xml.renameTo(new File(backupFile));
2648
                    // create a new, empty configuration
2649
                    return new XMLEntity();
2650
                } catch (FileNotFoundException ex) {
2651
                    return new XMLEntity();
2652
                } catch (ValidationException ex) {
2653
                    throw new ConfigurationException(e);
2654
                }
2655
            } catch (ValidationException e) {
2656
                throw new ConfigurationException(e);
2657
            }
2658
        } else {
2659
            return new XMLEntity();
2660
        }
2661
    }
2662

    
2663
    private static File getPluginsPersistenceFile(boolean read) {
2664
        if (read) {
2665
            File pluginsPersistenceFile = new File(getAppHomeDir(),
2666
                    "plugins-persistence-2_0.xml");
2667
            if (pluginsPersistenceFile.exists()) {
2668
                return pluginsPersistenceFile;
2669
            }
2670
            pluginsPersistenceFile = new File(getAppHomeDir(),
2671
                    "plugins-persistence.xml");
2672
            if (pluginsPersistenceFile.exists()) {
2673
                return pluginsPersistenceFile;
2674
            }
2675
        }
2676
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2677

    
2678
    }
2679

    
2680
    private static void persistenceToXML(XMLEntity entity)
2681
            throws ConfigurationException {
2682
                // write on a temporary file in order to not destroy current file if
2683
        // there is some problem while marshaling
2684
        File tmpFile = new File(getPluginsPersistenceFile(false).getPath()
2685
                + "-" + DateTime.getCurrentDate().getTime());
2686

    
2687
        File xml = getPluginsPersistenceFile(false);
2688
        OutputStreamWriter writer = null;
2689

    
2690
        try {
2691
            writer = new OutputStreamWriter(new FileOutputStream(tmpFile),
2692
                    CASTORENCODING);
2693
            entity.getXmlTag().marshal(writer);
2694
            writer.close();
2695

    
2696
                        // if marshaling process finished correctly, move the file to the
2697
            // correct one
2698
            xml.delete();
2699
            if (!tmpFile.renameTo(xml)) {
2700
                // if rename was not succesful, try copying it
2701
                FileChannel sourceChannel = new FileInputStream(tmpFile)
2702
                        .getChannel();
2703
                FileChannel destinationChannel = new FileOutputStream(xml)
2704
                        .getChannel();
2705
                sourceChannel.transferTo(0, sourceChannel.size(),
2706
                        destinationChannel);
2707
                sourceChannel.close();
2708
                destinationChannel.close();
2709

    
2710
            }
2711
        } catch (FileNotFoundException e) {
2712
            throw new ConfigurationException(e);
2713
        } catch (MarshalException e) {
2714
            // try to close the stream, maybe it remains open
2715
            if (writer != null) {
2716
                try {
2717
                    writer.close();
2718
                } catch (IOException e1) {
2719
                }
2720
            }
2721
        } catch (ValidationException e) {
2722
            throw new ConfigurationException(e);
2723
        } catch (IOException e) {
2724
            throw new ConfigurationException(e);
2725
        }
2726
    }
2727

    
2728
    static MDIFrame getFrame() {
2729
        return frame;
2730
    }
2731

    
2732
    /**
2733
     * Gracefully closes the application. It shows dialogs to save data, finish
2734
     * processes, etc, then it terminates the extensions, removes temporal files
2735
     * and finally exits.
2736
     */
2737
    public synchronized static void closeApplication() {
2738
        TerminationProcess terminationProcess = (new Launcher()).new TerminationProcess();
2739
        terminationProcess.run();
2740
    }
2741

    
2742
    static HashMap getClassesExtensions() {
2743
        return classesExtensions;
2744
    }
2745

    
2746
    public static IExtension getExtensionByName(String extensionName) {
2747
        if( StringUtils.isEmpty(extensionName) ) {
2748
            return null;
2749
        }
2750
        for (Entry<Class<? extends IExtension>, ExtensionDecorator> entry : classesExtensions.entrySet()) {
2751
            Class<? extends IExtension> extensionClass = entry.getKey();
2752
            IExtension extension = entry.getValue();
2753
            if( extensionName.equals(extensionClass.getName()) ) {
2754
                while( extension instanceof ExtensionDecorator ) {
2755
                    extension = ((ExtensionDecorator)extension).getExtension();
2756
                }
2757
                return extension;
2758
            }
2759
        }
2760
        return null;
2761
    }
2762
    
2763
    private static Extensions[] getExtensions() {
2764
        List<Extensions> array = new ArrayList<Extensions>();
2765
        Iterator<PluginConfig> iter = pluginsConfig.values().iterator();
2766

    
2767
        while (iter.hasNext()) {
2768
            array.add(iter.next().getExtensions());
2769
        }
2770

    
2771
        return array.toArray(new Extensions[array.size()]);
2772
    }
2773

    
2774
    public static Iterator getExtensionIterator() {
2775
        return extensions.iterator();
2776
    }
2777

    
2778
    public static HashMap getPluginConfig() {
2779
        return pluginsConfig;
2780
    }
2781

    
2782
    public static Extension getExtension(String s) {
2783
        Extensions[] exts = getExtensions();
2784

    
2785
        for (int i = 0; i < exts.length; i++) {
2786
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2787
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2788
                    return exts[i].getExtension(j);
2789
                }
2790
            }
2791
        }
2792

    
2793
        return null;
2794
    }
2795

    
2796
    public static AndamiConfig getAndamiConfig() {
2797
        return andamiConfig;
2798
    }
2799

    
2800
    private static class ExtensionComparator implements Comparator {
2801

    
2802
        public int compare(Object o1, Object o2) {
2803
            Extension e1 = (Extension) o1;
2804
            Extension e2 = (Extension) o2;
2805

    
2806
            if (!e1.hasPriority() && !e2.hasPriority()) {
2807
                return -1;
2808
            }
2809

    
2810
            if (e1.hasPriority() && !e2.hasPriority()) {
2811
                return Integer.MIN_VALUE;
2812
            }
2813

    
2814
            if (e2.hasPriority() && !e1.hasPriority()) {
2815
                return Integer.MAX_VALUE;
2816
            }
2817

    
2818
            if (e1.getPriority() != e2.getPriority()) {
2819
                return e2.getPriority() - e1.getPriority();
2820
            } else {
2821
                return (e2.toString().compareTo(e1.toString()));
2822
            }
2823
        }
2824
    }
2825

    
2826
    private static class MenuComparator implements Comparator<SortableMenu> {
2827

    
2828
        private static ExtensionComparator extComp = new ExtensionComparator();
2829

    
2830
        public int compare(SortableMenu e1, SortableMenu e2) {
2831

    
2832
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2833
                if (e1.extension instanceof SkinExtensionType) {
2834
                    return 1;
2835
                } else if (e2.extension instanceof SkinExtensionType) {
2836
                    return -1;
2837
                } else {
2838
                    return extComp.compare(e1.extension, e2.extension);
2839
                }
2840
            }
2841

    
2842
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2843
                return Integer.MIN_VALUE;
2844
            }
2845

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

    
2850
            if (e1.menu.getPosition() == e2.menu.getPosition()) {
2851
                                // we don't return 0 unless both objects are the same, otherwise
2852
                // the objects get overwritten in the treemap
2853
                return (e1.toString().compareTo(e2.toString()));
2854
            }
2855
            if (e1.menu.getPosition() > e2.menu.getPosition()) {
2856
                return Integer.MAX_VALUE;
2857
            }
2858
            return Integer.MIN_VALUE;
2859

    
2860
        }
2861
    }
2862

    
2863
    private static class SortableMenu {
2864

    
2865
        public PluginClassLoader loader;
2866
        public Menu menu;
2867
        public SkinExtensionType extension;
2868

    
2869
        public SortableMenu(PluginClassLoader loader,
2870
                SkinExtensionType skinExt, Menu menu2) {
2871
            extension = skinExt;
2872
            menu = menu2;
2873
            this.loader = loader;
2874
        }
2875

    
2876
    }
2877

    
2878
    private static class SortableTool {
2879

    
2880
        public PluginClassLoader loader;
2881
        public ToolBar toolbar;
2882
        public ActionTool actiontool;
2883
        public SelectableTool selectabletool;
2884
        public SkinExtensionType extension;
2885

    
2886
        public SortableTool(PluginClassLoader loader,
2887
                SkinExtensionType skinExt, ToolBar toolbar2,
2888
                ActionTool actiontool2) {
2889
            extension = skinExt;
2890
            toolbar = toolbar2;
2891
            actiontool = actiontool2;
2892
            this.loader = loader;
2893
        }
2894

    
2895
        public SortableTool(PluginClassLoader loader,
2896
                SkinExtensionType skinExt, ToolBar toolbar2,
2897
                SelectableTool selectabletool2) {
2898
            extension = skinExt;
2899
            toolbar = toolbar2;
2900
            selectabletool = selectabletool2;
2901
            this.loader = loader;
2902
        }
2903
    }
2904

    
2905
    private static class ToolBarComparator implements Comparator<SortableTool> {
2906

    
2907
        private static ExtensionComparator extComp = new ExtensionComparator();
2908

    
2909
        public int compare(SortableTool e1, SortableTool e2) {
2910

    
2911
                        // if the toolbars have the same name, they are considered to be
2912
            // the same toolbar, so we don't need to do further comparing
2913
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2914
                return 0;
2915
            }
2916

    
2917
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2918
                if (e1.extension instanceof SkinExtensionType) {
2919
                    return 1;
2920
                } else if (e2.extension instanceof SkinExtensionType) {
2921
                    return -1;
2922
                } else {
2923
                    return extComp.compare(e1.extension, e2.extension);
2924
                }
2925
            }
2926

    
2927
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2928
                return Integer.MIN_VALUE;
2929
            }
2930

    
2931
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2932
                return Integer.MAX_VALUE;
2933
            }
2934
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2935
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2936
            }
2937

    
2938
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2939
                    && e1.toolbar.getSelectableTool().equals(
2940
                            e2.toolbar.getSelectableTool())) {
2941
                return 0;
2942
            }
2943
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2944
        }
2945
    }
2946

    
2947
    /**
2948
     * <p>
2949
     * This class is used to compare tools (selectabletool and actiontool),
2950
     * using the "position" attribute.
2951
     * </p>
2952
     * <p>
2953
     * The ordering criteria are:
2954
     * </p>
2955
     * <ul>
2956
     * <li>If the tools are placed in different toolbars, they use the toolbars'
2957
     * order. (using the ToolBarComparator).</li>
2958
     * <li></li>
2959
     * <li>If any of the tools has not 'position' attribute, the tool which
2960
     * <strong>has</strong> the attribute will be placed first.</li>
2961
     * <li>If both tools have the same position (or they don't have a 'position'
2962
     * attribute), the priority of the extensions where the tool is
2963
     * defined.</li>
2964
     * </ul>
2965
     *
2966
     * @author cesar
2967
     * @version $Revision: 40305 $
2968
     */
2969
    private static class ToolComparator implements Comparator<SortableTool> {
2970

    
2971
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2972

    
2973
        public int compare(SortableTool e1, SortableTool e2) {
2974
            // compare the toolbars which contain the tools
2975
            long result = toolBarComp.compare(e1, e2);
2976
            if (result != 0) { // if the toolbars are different, use their order
2977
                return result > 0 ? 1 : -1;
2978
            }
2979
            // otherwise, compare the tools
2980
            long e1Position = -1, e2Position = -1;
2981

    
2982
            if (e1.actiontool != null) {
2983
                if (e1.actiontool.hasPosition()) {
2984
                    e1Position = e1.actiontool.getPosition();
2985
                }
2986
            } else if (e1.selectabletool != null) {
2987
                if (e1.selectabletool.hasPosition()) {
2988
                    e1Position = e1.selectabletool.getPosition();
2989
                }
2990
            }
2991

    
2992
            if (e2.actiontool != null) {
2993
                if (e2.actiontool.hasPosition()) {
2994
                    e2Position = e2.actiontool.getPosition();
2995
                }
2996
            } else if (e2.selectabletool != null) {
2997
                if (e2.selectabletool.hasPosition()) {
2998
                    e2Position = e2.selectabletool.getPosition();
2999
                }
3000
            }
3001

    
3002
            if ((e1Position == -1) && (e2Position != -1)) {
3003
                return 1;
3004
            }
3005
            if ((e1Position != -1) && (e2Position == -1)) {
3006
                return -1;
3007
            }
3008
            if ((e1Position != -1) && (e2Position != -1)) {
3009
                result = e1Position - e2Position;
3010
                                // we don't return 0 unless both objects are the same, otherwise
3011
                // the objects get overwritten in the treemap
3012
                if (result != 0) {
3013
                    return result > 0 ? 1 : -1;
3014
                }
3015
            }
3016
            return e1.toString().compareTo(e2.toString());
3017
        }
3018
    }
3019

    
3020
    public static String getDefaultLookAndFeel() {
3021
        String osName = (String) System.getProperty("os.name");
3022

    
3023
        if ((osName.length() > 4)
3024
                && osName.substring(0, 5).toLowerCase().equals("linux")) {
3025
            return nonWinDefaultLookAndFeel;
3026
        }
3027
        if (osName.toLowerCase().startsWith("mac os x")) {
3028
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
3029
        }
3030

    
3031
        return UIManager.getSystemLookAndFeelClassName();
3032
    }
3033

    
3034
    /**
3035
     * Gets the ISO 839 two-characters-long language code matching the provided
3036
     * language code (which may be an ISO 839-2/T three-characters-long code or
3037
     * an ISO 839-1 two-characters-long code).
3038
     *
3039
     * If the provided parameter is already two characters long, it returns the
3040
     * parameter without any modification.
3041
     *
3042
     * @param langCode A language code representing either an ISO 839-2/T
3043
     * language code or an ISO 839-1 code.
3044
     * @return A two-characters-long code specifying an ISO 839 language code.
3045
     */
3046
    private static String normalizeLanguageCode(String langCode) {
3047
        final String fileName = "iso_639.tab";
3048
        if (langCode.length() == 2) {
3049
            return langCode;
3050
        } else if (langCode.length() == 3) {
3051
            if (langCode.equals("va") || langCode.equals("val")) { // special
3052
                // case
3053
                // for
3054
                // Valencian
3055
                return "ca";
3056
            }
3057
            URL isoCodes = Launcher.class.getClassLoader()
3058
                    .getResource(fileName);
3059
            if (isoCodes != null) {
3060
                try {
3061
                    BufferedReader reader = new BufferedReader(
3062
                            new InputStreamReader(isoCodes.openStream(),
3063
                                    "ISO-8859-1"));
3064
                    String line;
3065

    
3066
                    while ((line = reader.readLine()) != null) {
3067
                        String[] language = line.split("\t");
3068
                        if (language[0].equals(langCode)) {
3069
                                                        // the three
3070
                            // characters code
3071
                            return language[2]; // third column i the two
3072
                            // characters code
3073
                        }
3074
                    }
3075
                } catch (IOException ex) {
3076
                    logger.error(Messages
3077
                            .getString("Error_reading_isocodes_file"), ex);
3078
                    return "es";
3079
                }
3080
            } else {
3081
                logger.error(Messages.getString("Error_reading_isocodes_file"));
3082
                return "es";
3083
            }
3084
        }
3085
        return "es";
3086
    }
3087

    
3088
    /**
3089
     * Configures the locales (languages and local resources) to be used by the
3090
     * application.
3091
     *
3092
     * First it tries to get the locale from the command line parameters, then
3093
     * the andami-config file is checked.
3094
     *
3095
     * The locale name is normalized to get a two characters language code as
3096
     * defined by ISO-639-1 (although ISO-639-2/T three characters codes are
3097
     * also accepted from the command line or the configuration file).
3098
     *
3099
     * Finally, the gvsig-i18n library and the default locales for Java and
3100
     * Swing are configured.
3101
     *
3102
     */
3103
    private static void configureLocales() {
3104
        // Configurar el locale
3105
        String localeStr = null;
3106

    
3107
        if( getArguments().contains("language") ) {
3108
            localeStr = getArguments().get("language");
3109
        } else {
3110
            localeStr = andamiConfig.getLocaleLanguage();
3111
        }
3112
        localeStr = normalizeLanguageCode(localeStr);
3113
        locale = getLocale(
3114
                localeStr,
3115
                andamiConfig.getLocaleCountry(),
3116
                andamiConfig.getLocaleVariant()
3117
        );
3118
        org.gvsig.i18n.Messages.setCurrentLocale(locale);
3119
        JComponent.setDefaultLocale(locale);
3120
        /*
3121
         org.gvsig.i18n.Messages.addLocale(locale);
3122
         // add english and spanish as fallback languages
3123
         if ( localeStr.equals("es") || localeStr.equals("ca")
3124
         || localeStr.equals("gl") || localeStr.equals("eu")
3125
         || localeStr.equals("va") ) {
3126
         // prefer Spanish for languages spoken in Spain
3127
         org.gvsig.i18n.Messages.addLocale(new Locale("es"));
3128
         org.gvsig.i18n.Messages.addLocale(new Locale("en"));
3129
         } else {
3130
         // prefer English for the rest
3131
         org.gvsig.i18n.Messages.addLocale(new Locale("en"));
3132
         org.gvsig.i18n.Messages.addLocale(new Locale("es"));
3133
         }
3134
         */
3135
        // Create classloader for the i18n resources in the
3136
        // andami and user i18n folder. Those values will have
3137
        // precedence over any other values added afterwards
3138
        File appI18nFolder = new File(getApplicationFolder(), "i18n");
3139
        File userI18nFolder = new File(getAppHomeDir(), "i18n");
3140
        if (!userI18nFolder.exists()) {
3141
            try {
3142
                FileUtils.forceMkdir(userI18nFolder);
3143
            } catch (IOException e) {
3144
                logger.info("Can't create i18n folder in gvSIG home (" + userI18nFolder + ").", e);
3145
            }
3146
        }
3147
//        logger.info("Loading i18n resources from the application and user "
3148
//                + "folders: {}, {}", appI18nFolder, userI18nFolder);
3149

    
3150
        URL[] i18nURLs = getURLsFromI18nFolders(userI18nFolder, appI18nFolder);
3151
        ClassLoader i18nClassLoader = URLClassLoader.newInstance(i18nURLs, null);
3152
        logger.info("loading resources from classloader " + i18nClassLoader.toString() + ".");
3153
        org.gvsig.i18n.Messages.addResourceFamily("text", i18nClassLoader,
3154
                "Andami Launcher");
3155

    
3156
        // Finally load the andami own i18n resources
3157
        org.gvsig.i18n.Messages.addResourceFamily("org.gvsig.andami.text",
3158
                "Andami Launcher");
3159
    }
3160

    
3161
    private static URL[] getURLsFromI18nFolders(File userFolder, File appFolder) {
3162
        List<URL> urls = new ArrayList<URL>();
3163
        File[] files = new File[]{userFolder, appFolder};
3164
        for (int n1 = 0; n1 < files.length; n1++) {
3165
            File folder = files[n1];
3166
//                try {
3167
//                    urls.add(folder.toURI().toURL());
3168
//                } catch (MalformedURLException ex) {
3169
//                    logger.warn("Can't convert file to url (file="+userFolder.getAbsolutePath()+").", ex);
3170
//                    return null;
3171
//                }
3172
            File[] subFiles = folder.listFiles();
3173
            for (int n2 = 0; n2 < subFiles.length; n2++) {
3174
                File subFolder = subFiles[n2];
3175
                if ("andami".equalsIgnoreCase(subFolder.getName())) {
3176
                    // Skip andami and add the last.
3177
                    continue;
3178
                }
3179
                if (subFolder.isDirectory()) {
3180
                    try {
3181
                        urls.add(subFolder.toURI().toURL());
3182
                    } catch (MalformedURLException ex) {
3183
                        logger.warn("Can't convert file to url (file=" + subFolder.getAbsolutePath() + ").", ex);
3184
                        return null;
3185
                    }
3186
                }
3187
            }
3188
        }
3189
        File folder = new File(appFolder, "andami");
3190
        try {
3191
            urls.add(folder.toURI().toURL());
3192
        } catch (MalformedURLException ex) {
3193
            logger.warn("Can't convert file to url (file=" + folder.getAbsolutePath() + ").", ex);
3194
            return null;
3195
        }
3196
        return urls.toArray(new URL[urls.size()]);
3197
    }
3198

    
3199
    /**
3200
     * Gets Home Directory location of the application into users home folder.
3201
     *
3202
     * May be set from outside the aplication by means of
3203
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name of the application
3204
     *
3205
     * @return
3206
     */
3207
    public static String getAppHomeDir() {
3208
        return appHomeDir;
3209
    }
3210

    
3211
    public static File getApplicationHomeFolder() {
3212
        return new File(getAppHomeDir());
3213
    }
3214

    
3215
    /**
3216
     * Sets Home Directory location of the application. May be set from outside
3217
     * the aplication by means of -DgvSIG.home=C:/data/gvSIG, where gvSIG its
3218
     * the name of the application
3219
     *
3220
     * @param appHomeDir
3221
     */
3222
    public static void setAppHomeDir(String appHomeDir) {
3223
        Launcher.appHomeDir = appHomeDir;
3224
    }
3225

    
3226
    /**
3227
     * Initialize the extesion that have to take the control of the state of
3228
     * action controls of the UI of all extensions. <br>
3229
     * <br>
3230
     * For use this option you have to add an argument to the command line like
3231
     * this: <br>
3232
     * <br>
3233
     * -exclusiveUI={pathToExtensionClass} <br>
3234
     *
3235
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
3236
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
3237
     */
3238
    private static void initializeExclusiveUIExtension() {
3239
        String name = PluginServices.getArgumentByName("exclusiveUI");
3240
        if (name == null) {
3241
            return;
3242
        }
3243

    
3244
        Iterator<Class<? extends IExtension>> iter = classesExtensions.keySet()
3245
                .iterator();
3246
        int charIndex;
3247
        Class<? extends IExtension> key;
3248
        while (iter.hasNext()) {
3249
            key = iter.next();
3250
            charIndex = key.getName().indexOf(name);
3251
            // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex);
3252
            if (charIndex == 0) {
3253
                IExtension ext = classesExtensions.get(key);
3254
                if (ext instanceof ExtensionDecorator) {
3255
                    ext = ((ExtensionDecorator) ext).getExtension();
3256
                }
3257
                if (ext instanceof ExclusiveUIExtension) {
3258
                    PluginServices
3259
                            .setExclusiveUIExtension((ExclusiveUIExtension) ext);
3260
                }
3261
                break;
3262
            }
3263
        }
3264

    
3265
        logger
3266
                .error(Messages
3267
                        .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
3268
                        + " '" + name + "'");
3269
    }
3270

    
3271
    public static void initIconThemes() {
3272
        PluginsManager pluginsManager = PluginsLocator.getManager();
3273
        IconThemeManager iconManager = ToolsSwingLocator.getIconThemeManager();
3274

    
3275
        File f = new File(pluginsManager.getApplicationHomeFolder(), "icon-theme");
3276
        if (!f.exists()) {
3277
            try {
3278
                f.mkdir();
3279
            } catch (Exception ex) {
3280
                // Do nothing
3281
            }
3282
        }
3283
        iconManager.getRepository().add(f, "_User");
3284

    
3285
        f = new File(pluginsManager.getApplicationFolder(), "icon-theme");
3286
        if (!f.exists()) {
3287
            try {
3288
                f.mkdir();
3289
            } catch (Exception ex) {
3290
                // Do nothing
3291
            }
3292
        }
3293
        iconManager.getRepository().add(f, "_Global");
3294

    
3295
        Preferences prefs = Preferences.userRoot().node("gvsig.icontheme");
3296
        String defaultThemeID = prefs.get("default-theme", null);
3297
        if (defaultThemeID != null) {
3298
            IconTheme iconTheme = iconManager.get(defaultThemeID);
3299
            if (iconTheme != null) {
3300
                iconManager.setCurrent(iconTheme);
3301
            }
3302
        }
3303
    }
3304

    
3305
    public static void manageUnsavedData(String prompt) throws Exception {
3306
        final UnsavedDataPanel panel = new UnsavedDataPanel(prompt);
3307
        final List<IUnsavedData> unsavedData = PluginsLocator.getManager().getUnsavedData();
3308
        panel.setUnsavedData(unsavedData);
3309

    
3310
        panel.addActionListener(panel.new UnsavedDataPanelListener() {
3311

    
3312
            public void cancel(UnsavedDataPanel panel) {
3313
                panel.setVisible(false);
3314
            }
3315

    
3316
            public void discard(UnsavedDataPanel panel) {
3317
                panel.setVisible(false);
3318
            }
3319

    
3320
            public void accept(UnsavedDataPanel panel) {
3321
                panel.setVisible(false);
3322

    
3323
                try {
3324
                    PluginsLocator.getManager().saveUnsavedData(panel.getSelectedsUnsavedDataList());
3325
                } catch (UnsavedDataException e) {
3326
                    StringBuilder msg = new StringBuilder();
3327
                    msg.append(PluginServices.getText(this, "The_following_resources_could_not_be_saved"));
3328
                    msg.append("\n");
3329
                    for (Iterator iterator = e.getUnsavedData().iterator(); iterator.hasNext();) {
3330
                        IUnsavedData unsavedData = (IUnsavedData) iterator.next();
3331
                        msg.append(unsavedData.getResourceName());
3332
                        msg.append(" -- ");
3333
                        msg.append(unsavedData.getDescription());
3334
                        msg.append("\n");
3335
                    }
3336
                    JOptionPane.showMessageDialog(panel, msg, PluginServices.getText(this, "Resources_was_not_saved"), JOptionPane.ERROR_MESSAGE);
3337
                }
3338
            }
3339
        });
3340

    
3341
        //TODO: mostrar panel WindowManager
3342
        ToolsSwingLocator.getWindowManager().showWindow(
3343
                panel,
3344
                PluginServices.getText(panel, "Resource_was_not_saved"),
3345
                MODE.DIALOG);
3346

    
3347
    }
3348

    
3349
    /**
3350
     * Manages Andami termination process
3351
     *
3352
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
3353
     */
3354
    public class TerminationProcess {
3355

    
3356
        private boolean proceed = false;
3357
        private UnsavedDataPanel panel = null;
3358

    
3359
        public void run() {
3360
            try {
3361
                int exit = manageUnsavedData();
3362
                if ((exit == JOptionPane.NO_OPTION)
3363
                        || (exit == JOptionPane.CLOSED_OPTION)) {
3364
                    // the user doesn't want to exit
3365
                    return;
3366
                }
3367
                closeAndami();
3368
            } catch (Exception e) {
3369
                logger.warn("It is not possible to close the application", e);
3370
                                // It is not possible to close the application.
3371
                // this exception has been registered before
3372
            }
3373
        }
3374

    
3375
        /**
3376
         * Finishes the application without asking user if want or not to save
3377
         * unsaved data.
3378
         */
3379
        public void closeAndami() {
3380
            PluginsManager pluginsManager = PluginsLocator.getManager();
3381
            pluginsManager.executeShutdownTasks();
3382

    
3383
            try {
3384
                saveAndamiConfig();
3385
            } catch (Exception ex) {
3386
                logger.error(
3387
                        "There was an error exiting application, can't save andami-config.xml",
3388
                        ex
3389
                );
3390
            }
3391

    
3392
            try {
3393
                // Persistencia de los plugins
3394
                savePluginPersistence();
3395
                savePluginsProperties();
3396
            } catch (Exception ex) {
3397
                logger.error(
3398
                        "There was an error exiting application, can't save plugins properties",
3399
                        ex
3400
                );
3401
            }
3402

    
3403
            // Finalize all the extensions
3404
            finalizeExtensions();
3405

    
3406
            try {
3407
                // Clean any temp data created
3408
                Utilities.cleanUpTempFiles();
3409
            } catch (Exception ex) {
3410
                logger.error(
3411
                        "There was an error exiting application, can't remove temporary files",
3412
                        ex
3413
                );
3414
            }
3415

    
3416
            logger.info("Quiting application.");
3417

    
3418
            // Para la depuraci?n de memory leaks
3419
            System.gc();
3420

    
3421
            System.exit(0);
3422
        }
3423

    
3424
        public void saveAndamiConfig() {
3425
            // Configuraci?n de Andami
3426
            try {
3427
                andamiConfigToXML(andamiConfigPath);
3428
            } catch (MarshalException e) {
3429
                logger
3430
                        .error(
3431
                                Messages
3432
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3433
                                e);
3434
            } catch (ValidationException e) {
3435
                logger
3436
                        .error(
3437
                                Messages
3438
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3439
                                e);
3440
            } catch (IOException e) {
3441
                logger
3442
                        .error(
3443
                                Messages
3444
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3445
                                e);
3446
            }
3447
        }
3448

    
3449
        private void savePluginsProperties() {
3450
            PluginsManager manager = PluginsLocator.getManager();
3451
            List<PluginServices> plugins = manager.getPlugins();
3452
            for (PluginServices plugin : plugins) {
3453
                if (plugin != null) {
3454
                    plugin.savePluginProperties();
3455
                }
3456
            }
3457
        }
3458

    
3459
        /**
3460
         * Exectutes the terminate method for all the extensions, in the reverse
3461
         * order they were initialized
3462
         *
3463
         */
3464
        private void finalizeExtensions() {
3465
            for (int i = extensions.size() - 1; i >= 0; i--) {
3466
                org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
3467
                        .get(i);
3468
                String extensionName = "(unknow)";
3469
                try {
3470
                    extensionName = extensionInstance.getClass().getName();
3471
                    extensionInstance.terminate();
3472
                } catch (Exception ex) {
3473
                    logger.error(MessageFormat.format(
3474
                            "There was an error extension ending {0}",
3475
                            extensionName), ex);
3476
                }
3477
            }
3478
        }
3479

    
3480
        private IUnsavedData[] getUnsavedData() throws Exception {
3481
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
3482
            IExtension exclusiveExtension = PluginServices
3483
                    .getExclusiveUIExtension();
3484

    
3485
            for (int i = extensions.size() - 1; i >= 0; i--) {
3486
                org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
3487
                        .get(i);
3488
                IExtensionStatus status = null;
3489
                if (exclusiveExtension != null) {
3490
                    status = exclusiveExtension.getStatus(extensionInstance);
3491
                } else {
3492
                    status = extensionInstance.getStatus();
3493
                }
3494
                if (status != null) {
3495
                    try {
3496
                        if (status.hasUnsavedData()) {
3497
                            IUnsavedData[] array = status.getUnsavedData();
3498
                            for (int element = 0; element < array.length; element++) {
3499
                                unsavedDataList.add(array[element]);
3500
                            }
3501
                        }
3502
                    } catch (Exception e) {
3503
                        logger.info("Error calling the hasUnsavedData method",
3504
                                new Exception());
3505
                        int option = JOptionPane
3506
                                .showConfirmDialog(
3507
                                        frame,
3508
                                        Messages
3509
                                        .getString("error_getting_unsaved_data"),
3510
                                        Messages.getString("MDIFrame.salir"),
3511
                                        JOptionPane.YES_NO_OPTION);
3512
                        if (option == JOptionPane.NO_OPTION) {
3513
                            throw e;
3514
                        }
3515
                    }
3516
                }
3517
            }
3518
            return unsavedDataList.toArray(new IUnsavedData[unsavedDataList
3519
                    .size()]);
3520
        }
3521

    
3522
        public UnsavedDataPanel getUnsavedDataPanel() {
3523
            if (panel == null) {
3524
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
3525
            }
3526
            return panel;
3527
        }
3528

    
3529
        /**
3530
         * Checks if the extensions have some unsaved data, and shows a dialog
3531
         * to allow saving it. This dialog also allows to don't exit Andami.
3532
         *
3533
         * @return true if the user confirmed he wishes to exit, false otherwise
3534
         * @throws Exception
3535
         */
3536
        public int manageUnsavedData() throws Exception {
3537
            IUnsavedData[] unsavedData = getUnsavedData();
3538

    
3539
            // there was no unsaved data
3540
            if (unsavedData.length == 0) {
3541
                int option = JOptionPane
3542
                        .showConfirmDialog(frame, Messages
3543
                                .getString("MDIFrame.quiere_salir"), Messages
3544
                                .getString("MDIFrame.salir"),
3545
                                JOptionPane.YES_NO_OPTION);
3546
                return option;
3547
            }
3548

    
3549
            UnsavedDataPanel panel = getUnsavedDataPanel();
3550
            panel.setUnsavedDataArray(unsavedData);
3551

    
3552
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
3553

    
3554
                public void cancel(UnsavedDataPanel panel) {
3555
                    proceed(false);
3556
                    PluginServices.getMDIManager().closeWindow(panel);
3557

    
3558
                }
3559

    
3560
                public void discard(UnsavedDataPanel panel) {
3561
                    proceed(true);
3562
                    PluginServices.getMDIManager().closeWindow(panel);
3563

    
3564
                }
3565

    
3566
                public void accept(UnsavedDataPanel panel) {
3567
                    IUnsavedData[] unsavedDataArray = panel
3568
                            .getSelectedsUnsavedData();
3569
                    boolean saved;
3570
                    for (int i = 0; i < unsavedDataArray.length; i++) {
3571
                        try {
3572
                            saved = unsavedDataArray[i].saveData();
3573
                        } catch (Exception ex) {
3574
                            PluginServices.getLogger().error(
3575
                                    "Error saving"
3576
                                    + unsavedDataArray[i]
3577
                                    .getResourceName(), ex);
3578
                            saved = false;
3579
                        }
3580
                        if (!saved) {
3581
                            JOptionPane
3582
                                    .showMessageDialog(
3583
                                            panel,
3584
                                            PluginServices
3585
                                            .getText(this,
3586
                                                    "The_following_resource_could_not_be_saved_")
3587
                                            + "\n"
3588
                                            + unsavedDataArray[i]
3589
                                            .getResourceName()
3590
                                            + " -- "
3591
                                            + unsavedDataArray[i]
3592
                                            .getDescription(),
3593
                                            PluginServices.getText(this,
3594
                                                    "unsaved_resources"),
3595
                                            JOptionPane.ERROR_MESSAGE);
3596

    
3597
                            try {
3598
                                unsavedDataArray = getUnsavedData();
3599
                            } catch (Exception e) {
3600
                                // This exception has been registered before
3601
                            }
3602
                            panel.setUnsavedDataArray(unsavedDataArray);
3603
                            return;
3604
                        }
3605
                    }
3606
                    proceed(true);
3607
                    PluginServices.getMDIManager().closeWindow(panel);
3608
                }
3609
            });
3610

    
3611
            PluginServices.getMDIManager().addWindow(panel);
3612
            if (proceed) {
3613
                return JOptionPane.YES_OPTION;
3614
            } else {
3615
                return JOptionPane.NO_OPTION;
3616
            }
3617
        }
3618

    
3619
        private void proceed(boolean proceed) {
3620
            this.proceed = proceed;
3621
        }
3622

    
3623
    }
3624

    
3625
    public static TerminationProcess getTerminationProcess() {
3626
        return (new Launcher()).new TerminationProcess();
3627
    }
3628

    
3629
    private PackageInfo getPackageInfo(String pluginsFolder) {
3630
        try {
3631
            PluginsManager pm = PluginsLocator.getManager();
3632
            return pm.getPackageInfo();
3633
        } catch (Exception e) {
3634
            logger.info("Can't locate PackageInfo from plugin org.gvsig.app", e);
3635
            return null;
3636
        }
3637
    }
3638

    
3639
    /**
3640
     * Launch the gvSIG package installer.
3641
     *
3642
     * @throws Exception if there is any error
3643
     */
3644
    private void doInstall(String[] args) throws Exception {
3645
        String installURL = null;
3646
        String installURLFile = null;
3647
        String gvSIGVersion = null;
3648
        String[] myArgs = new String[3];
3649
        PackageInfo packageInfo = null;
3650

    
3651
        Options options = new Options();
3652
        options.addOption("i", "install", false, "install");
3653
        options.addOption("u", "installURL", true, "installURL");
3654
        options.addOption("f", "installURLFile", true, "installURLFile");
3655
        options.addOption("v", "installVersion", true, "installVersion");
3656
        options.addOption("A", "applicationName", true, "application name, default is gvSIG");
3657
        options.addOption("P", "pluginsFolder", true, "pluginsFolder");
3658
        options.addOption("l", "language", true, "language");
3659

    
3660
        // This options are managed by the gvSIG.sh but need to be declared here to avoid
3661
        // errors.
3662
        options.addOption(null, "debug", false, "Activate the JVM remote debug");
3663
        options.addOption(null, "pause", false, "Pause when activate JVM debug");
3664

    
3665
        /*
3666
         * Los parametros que deberian pasarse en el instalador oficial de gvSIG serian:
3667
         *
3668
         * --install
3669
         * --applicationName=gvSIG
3670
         * --language=es
3671
         * --pluginsFolder=gvSIG/extensiones
3672
         *
3673
         * Opcionales (casi mejor que dejar los de por defecto y no pasarselos):
3674
         * --installVersion=2.0.0
3675
         * --installURL=http://downloads.gvsig.org/download/gvsig-desktop/dists
3676
         * --installURLFile=gvSIG/extensiones/org.gvsig.installer.app.extension/defaultDownloadsURLs
3677
         *
3678
         */
3679
        CommandLineParser parser = new PosixParser();
3680
        CommandLine line = null;
3681
        try {
3682
            line = parser.parse(options, args);
3683
            boolean hasAllMandatoryOptions = true;
3684
            if (!line.hasOption("install")) {
3685
                hasAllMandatoryOptions = false;
3686
            }
3687

    
3688
            if (line.hasOption("installVersion")) {
3689
                gvSIGVersion = line.getOptionValue("installVersion");
3690
            }
3691
            if (line.hasOption("applicationName")) {
3692
                myArgs[0] = line.getOptionValue("applicationName");
3693
            } else {
3694
                myArgs[0] = "gvSIG";
3695
            }
3696
            if (line.hasOption("pluginsFolder")) {
3697
                myArgs[1] = line.getOptionValue("pluginsFolder");
3698
            } else {
3699
                myArgs[1] = "gvSIG/extensiones";
3700
            }
3701
            if (line.hasOption("language")) {
3702
                myArgs[2] = "language=" + line.getOptionValue("language");
3703
            } else {
3704
                // prevent null
3705
                myArgs[2] = Locale.getDefault().toString();
3706
            }
3707

    
3708
            if (line.hasOption("installURL")) {
3709
                installURL = line.getOptionValue("installURL");
3710
            } else {
3711
                installURL = "http://downloads.gvsig.org/download/gvsig-desktop/";
3712
            }
3713

    
3714
            if (line.hasOption("installURLFile")) {
3715
                installURLFile = line.getOptionValue("installURLFile");
3716
            } else {
3717
                installURLFile = "gvsig-installer-urls.config";
3718
            }
3719

    
3720
            if (!hasAllMandatoryOptions) {
3721
                System.err.println(Messages.get("usage") + ": Launcher "
3722
                        + "--install "
3723
                        + "[--applicationName=appName] "
3724
                        + "[--pluginsFolder=plugins-directory] "
3725
                        + "[--installURLFile=File] "
3726
                        + "[--installURL=URL] "
3727
                        + "[--language=locale]"
3728
                );
3729
                return;
3730
            }
3731
        } catch (ParseException exp) {
3732
            System.err.println("Unexpected exception:" + exp.getMessage());
3733
            System.exit(-1);
3734
        }
3735

    
3736
        initializeApp(myArgs, "installer");
3737

    
3738
        new DefaultLibrariesInitializer().fullInitialize(true);
3739

    
3740
        initializeInstallerManager();
3741

    
3742
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
3743
        
3744
        try {
3745
            logger.info("Loading plugins configurations");
3746
            this.loadPluginConfigs();
3747
        } catch (Throwable ex) {
3748
            logger.warn("Can't load plugins configurations", ex);
3749
        }
3750

    
3751
        try {
3752
            logger.info("Loading plugins");
3753
            this.loadPluginServices();
3754
        } catch (Throwable ex) {
3755
            logger.warn("Can't load plugins", ex);
3756
        }
3757

    
3758
        AndamiConfig config = getAndamiConfig();
3759

    
3760
        initializeIdentityManagement(new File(config.getPluginsDirectory()).getAbsoluteFile());
3761

    
3762
        initializeLibraries();
3763

    
3764
        packageInfo = getPackageInfo(myArgs[1]);
3765

    
3766
        // set the gvSIG version to the install manager, to compose the download URL
3767
        if (packageInfo != null) {
3768
            installerManager.setVersion(packageInfo.getVersion());
3769
        } else {
3770
            installerManager.setVersion(gvSIGVersion);
3771
        }
3772
        if (!installURL.contains(";")
3773
                && !installURL.endsWith(InstallerManager.PACKAGE_EXTENSION)
3774
                && !installURL.endsWith(InstallerManager.PACKAGE_INDEX_EXTENSION)) {
3775
            if (packageInfo != null && (packageInfo.getState().startsWith(InstallerManager.STATE.BETA)
3776
                    || packageInfo.getState().startsWith(InstallerManager.STATE.RC)
3777
                    || packageInfo.getState().equalsIgnoreCase(InstallerManager.STATE.FINAL))) {
3778
                installURL = installURL + "dists/<%Version%>/builds/<%Build%>/packages.gvspki";
3779
            }
3780
        }
3781
        // Configure default index download URL
3782
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(installURL);
3783

    
3784
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(new File(installURLFile));
3785

    
3786
        // Launch installer
3787
        PluginsManager manager = PluginsLocator.getManager();
3788

    
3789
        InstallWizardPanel installPackageWizard = SwingInstallerLocator
3790
                .getSwingInstallerManager().createInstallPackageWizard(
3791
                        manager.getApplicationFolder(),
3792
                        manager.getInstallFolder());
3793
        installPackageWizard.setWizardActionListener(new InstallerWizardActionListener() {
3794
            @Override
3795
            public void finish(InstallerWizardPanel installerWizard) {
3796
                logger.info("Finish installation.");
3797
                System.exit(0);
3798
            }
3799

    
3800
            @Override
3801
            public void cancel(InstallerWizardPanel installerWizard) {
3802
                logger.info("Cancel installation.");
3803
                System.exit(0);
3804
            }
3805
        });
3806

    
3807
        // the wizard will show the Typical or Advanced mode option.
3808
        installPackageWizard.setSkipTypicalOrAdvancedWizardPage(false);
3809
        // default packages will be selected.
3810
        installPackageWizard.setSelectDefaultPackages(true);
3811

    
3812
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
3813
        frame.addWindowListener(new WindowAdapter() {
3814
            @Override
3815
            public void windowClosing(WindowEvent we) {
3816
                logger.info("Closing installation.");
3817
                System.exit(0);
3818
            }
3819

    
3820
            @Override
3821
            public void windowClosed(WindowEvent we) {
3822
                logger.info("Close installation.");
3823
                System.exit(0);
3824
            }
3825
        });
3826
        frame.getContentPane().add(installPackageWizard.asJComponent(), BorderLayout.CENTER);
3827
        URL iconURL = getClass().getResource("/images/main/install-icon.png");
3828
        if( iconURL!=null ) {
3829
            ImageIcon icon = new ImageIcon(iconURL);
3830
            frame.setIconImage(icon.getImage());
3831
        }
3832
        frame.pack();
3833
        frame.setLocationRelativeTo(null);
3834

    
3835
        frame.setVisible(true);
3836
    }
3837

    
3838
    public static String getInformation() {
3839
        return getInformation(null);
3840
    }
3841

    
3842
    private static final int INFO_OS_NAME = 0;
3843
    private static final int INFO_OS_ARCH = 1;
3844
    private static final int INFO_OS_VERSION = 2;
3845
    private static final int INFO_OS_ADITIONAL = 3;
3846
    private static final int INFO_JRE_VENDOR = 4;
3847
    private static final int INFO_JRE_VERSION = 5;
3848
    private static final int INFO_JRE_HOME = 6;
3849
    private static final int INFO_PROXY_HOST = 7;
3850
    private static final int INFO_PROXY_PORT = 8;
3851
    private static final int INFO_PROXY_USER = 9;
3852
    private static final int INFO_PROXY_PASSWORD = 10;
3853
    private static final int INFO_APP_LOCALE = 11;
3854
    private static final int INFO_APP_FOLDER = 12;
3855
    private static final int INFO_APP_HOME = 13;
3856
    private static final int INFO_APP_INSTALL_FOLDER = 14;
3857
    private static final int INFO_APP_PLUGINS_FOLDER = 15;
3858
    private static final int INFO_APP_THEME = 16;
3859
    private static final int INFO_APP_SKIN = 17;
3860
    private static final int INFO_PACKAGES = 18;
3861
    private static final int INFO_TEMP_FOLDER = 19;
3862
    
3863
    public static String getInformation(PackageInfo[] pkgs) {
3864

    
3865
        String template = "OS\n"
3866
                + "    name    : {" + INFO_OS_NAME + "}\n"
3867
                + "    arch    : {" + INFO_OS_ARCH + "}\n"
3868
                + "    version : {" + INFO_OS_VERSION + "} \n"
3869
                + "{" + INFO_OS_ADITIONAL + "}"
3870
                + "JRE\n"
3871
                + "    vendor  : {" + INFO_JRE_VENDOR + "}\n"
3872
                + "    version : {" + INFO_JRE_VERSION + "}\n"
3873
                + "    home    : {" + INFO_JRE_HOME + "}\n"
3874
                + "HTTP Proxy\n"
3875
                + "    http.proxyHost     : {" + INFO_PROXY_HOST + "}\n"
3876
                + "    http.proxyPort     : {" + INFO_PROXY_PORT + "}\n"
3877
                + "    http.proxyUserName : {" + INFO_PROXY_USER + "}\n"
3878
                + "    http.proxyPassword : {" + INFO_PROXY_PASSWORD + "}\n"
3879
                + "Application\n"
3880
                + "    locale language         : {" + INFO_APP_LOCALE + "}\n"
3881
                + "    application forlder     : {" + INFO_APP_FOLDER + "}\n"
3882
                + "    application home forlder: {" + INFO_APP_HOME + "}\n"
3883
                + "    install forlder         : {" + INFO_APP_INSTALL_FOLDER + "}\n"
3884
                + "    plugins forlder         : {" + INFO_APP_PLUGINS_FOLDER + "}\n"
3885
                + "    theme                   : {" + INFO_APP_THEME + "}\n"
3886
                + "    Skin                    : {" + INFO_APP_SKIN + "}\n"
3887
                + "    temp forlder            : {" + INFO_TEMP_FOLDER + "}\n"
3888
                + "Installed packages\n"
3889
                + "{" + INFO_PACKAGES + "}";
3890

    
3891
        String values[] = new String[INFO_TEMP_FOLDER + 1];
3892

    
3893
        PluginsManager pluginmgr = PluginsLocator.getManager();
3894
        LocaleManager localemgr = PluginsLocator.getLocaleManager();
3895

    
3896
        Properties props = System.getProperties();
3897

    
3898
        // OS information
3899
        values[INFO_OS_NAME] = props.getProperty("os.name");
3900
        values[INFO_OS_ARCH] = props.getProperty("os.arch");
3901
        values[INFO_OS_VERSION] = props.getProperty("os.version");
3902

    
3903
        if (values[INFO_OS_NAME].startsWith("Linux")) {
3904
            try {
3905
                StringWriter writer = new StringWriter();
3906

    
3907
                String[] command = {"lsb_release", "-a"};
3908
                Process p = Runtime.getRuntime().exec(command);
3909
                InputStream is = p.getInputStream();
3910
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
3911
                String line;
3912
                while ((line = reader.readLine()) != null) {
3913
                    writer.write("    " + line + "\n");
3914
                }
3915
                values[INFO_OS_ADITIONAL] = writer.toString();
3916
            } catch (Exception ex) {
3917
                logger.warn("Can't get detailled os information (lsb_release -a).", ex);
3918
            }
3919
        }
3920

    
3921
        values[INFO_JRE_VENDOR] = props.getProperty("java.vendor");
3922
        values[INFO_JRE_VERSION] = props.getProperty("java.version");
3923
        values[INFO_JRE_HOME] = props.getProperty("java.home");
3924
        values[INFO_PROXY_HOST] = props.getProperty("http.proxyHost");
3925
        values[INFO_PROXY_PORT] = props.getProperty("http.proxyPort");
3926
        values[INFO_PROXY_USER] = props.getProperty("http.proxyUserName");
3927

    
3928
        if (props.get("http.proxyPassword") == null) {
3929
            values[INFO_PROXY_PASSWORD] = "(null)";
3930
        } else {
3931
            values[INFO_PROXY_PASSWORD] = "***********";
3932
        }
3933

    
3934
        try {
3935
            values[INFO_APP_SKIN] = MDIManagerFactory.getSkinExtension().getClassName();
3936
        } catch (Throwable e) {
3937
            values[INFO_APP_SKIN] = "(unknow)";
3938
        }
3939
        values[INFO_TEMP_FOLDER] = ToolsLocator.getFoldersManager().getTemporaryFolder().getAbsolutePath();
3940
        values[INFO_APP_LOCALE] = localemgr.getCurrentLocale().toString();
3941
        values[INFO_APP_FOLDER] = pluginmgr.getApplicationFolder().getAbsolutePath();
3942
        values[INFO_APP_HOME] = pluginmgr.getApplicationHomeFolder().getAbsolutePath();
3943
        values[INFO_APP_INSTALL_FOLDER] = pluginmgr.getInstallFolder().getAbsolutePath();
3944
        values[INFO_APP_PLUGINS_FOLDER] = StringUtils.join(pluginmgr.getPluginsFolders());
3945
        values[INFO_APP_THEME] = Launcher.theme.getSource().getAbsolutePath();
3946

    
3947
        try {
3948
            if (pkgs == null) {
3949
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
3950
                pkgs = installmgr.getInstalledPackages();
3951
            }
3952
            StringWriter writer = new StringWriter();
3953
            for (PackageInfo pkg : pkgs) {
3954
                writer.write("    ");
3955
                writer.write(pkg.toStringCompact());
3956
                writer.write("\n");
3957
            }
3958
            values[INFO_PACKAGES] = writer.toString();
3959

    
3960
        } catch (Throwable e) {
3961
            logger.warn("Can't get installed package information.", e);
3962
        }
3963

    
3964
        String s = MessageFormat.format(template, (Object[])values);
3965
        return s;
3966
    }
3967

    
3968
    private void logger_info(String msg) {
3969
        String info[] = msg.split("\n");
3970
        for (String info1 : info) {
3971
            logger.info(info1);
3972
        }
3973
    }
3974

    
3975
    private void saveEnvironInformation(PackageInfo[] pkgs) {
3976
        PluginsManager manager = PluginsLocator.getManager();
3977
        File fout = new File(manager.getApplicationHomeFolder(), "gvSIG-environ.info");
3978
        try {
3979
            FileUtils.write(fout, getInformation(pkgs));
3980
        } catch (IOException e) {
3981
            logger.info("Can't create '" + fout.getAbsolutePath() + "'");
3982
        }
3983
    }
3984

    
3985
    private void fixIncompatiblePlugins(PackageInfo[] installedPackages) {
3986
        final Set<String> incompatiblePlugins = new HashSet<String>();
3987

    
3988
        // Add installed packages to a Map to optimize searchs
3989
        final Map<String, PackageInfo> packages = new HashMap<String, PackageInfo>();
3990
        for (int i = 0; i < installedPackages.length; i++) {
3991
            packages.put(installedPackages[i].getCode(), installedPackages[i]);
3992
        }
3993
        Iterator<Entry<String, PluginConfig>> it = pluginsConfig.entrySet().iterator();
3994
        while (it.hasNext()) {
3995
            List<String> pluginNames = new ArrayList<String>();
3996
            Entry<String, PluginConfig> entry = it.next();
3997
            PluginConfig pluginConfig = entry.getValue();
3998
            pluginNames.add(entry.getKey());
3999

    
4000
                        // Locate the package for this plugin.
4001
            // Be care whith alias
4002
            String[] aliases = pluginsConfig.getAliases(pluginConfig);
4003
            if (aliases != null) {
4004
                for (int i = 0; i < aliases.length; i++) {
4005
                    pluginNames.add(aliases[i]);
4006
                }
4007
            }
4008
            PackageInfo pkg = null;
4009
            for (int n = 0; n < pluginNames.size(); n++) {
4010
                pkg = packages.get(pluginNames.get(n));
4011
                if (pkg != null) {
4012
                    break;
4013
                }
4014
            }
4015

    
4016
            // If package is found verify dependencies
4017
            if (pkg != null) {
4018
                Dependencies dependencies = pkg.getDependencies();
4019
                for (int i = 0; i < dependencies.size(); i++) {
4020
                    Dependency dependency = (Dependency) dependencies.get(i);
4021
                    if (Dependency.CONFLICT.equalsIgnoreCase(dependency.getType())) {
4022
                        String code = dependency.getCode();
4023
                        if (pluginsConfig.get(code) != null) {
4024
                            incompatiblePlugins.add(pkg.getCode());
4025
                            incompatiblePlugins.add(code);
4026
                        }
4027
                    }
4028
                }
4029
            }
4030
        }
4031
        if (incompatiblePlugins.isEmpty()) {
4032
            return;
4033
        }
4034
        splashWindow.toBack();
4035
        DisablePluginsConflictingDialog dlg = new DisablePluginsConflictingDialog(packages, incompatiblePlugins);
4036
        dlg.setVisible(true);
4037
        splashWindow.toFront();
4038
        switch (dlg.getAction()) {
4039
            case DisablePluginsConflictingDialog.CLOSE:
4040
                System.exit(0);
4041
                break;
4042
            case DisablePluginsConflictingDialog.CONTINUE:
4043
                break;
4044
        }
4045
        List<String> pluginsToDissable = dlg.getPluginNamesToDisable();
4046
        if (pluginsToDissable == null) {
4047
            return;
4048
        }
4049

    
4050
        Iterator<String> it2 = pluginsToDissable.iterator();
4051
        while (it2.hasNext()) {
4052
            String pluginName = it2.next();
4053
            logger.info("Dissabling plugin '" + pluginName + "' by user action.");
4054
            pluginsConfig.remove(pluginName);
4055
        }
4056
    }
4057

    
4058
    private class DisablePluginsConflictingDialog extends JDialog {
4059

    
4060
        public static final int CONTINUE = 0;
4061
        public static final int CLOSE = 1;
4062

    
4063
        private DisablePluginsConflictingLayoutPanel contents;
4064
        private int action = 0;
4065
        private List<Item> incompatiblePlugins = null;
4066
        private Map<String, PackageInfo> packages;
4067

    
4068
        private class Item {
4069

    
4070
            private String code;
4071
            private PackageInfo pkg;
4072

    
4073
            public Item(String code, PackageInfo pkg) {
4074
                this.code = code;
4075
                this.pkg = pkg;
4076
            }
4077

    
4078
            public String toString() {
4079
                if (this.pkg == null) {
4080
                    return code;
4081
                }
4082
                return this.pkg.getName() + " (" + this.pkg.getCode() + ")";
4083
            }
4084

    
4085
            public String getCode() {
4086
                if (pkg == null) {
4087
                    return code;
4088
                }
4089
                return pkg.getCode();
4090
            }
4091
        }
4092

    
4093
        DisablePluginsConflictingDialog(Map<String, PackageInfo> packages, Set<String> incompatiblePlugins) {
4094
            super((Frame) null, "", true);
4095
            this.setTitle(translate("_Conflicting_plugins"));
4096

    
4097
            this.packages = packages;
4098

    
4099
            this.incompatiblePlugins = new ArrayList<Item>();
4100
            Item item = null;
4101
            Iterator<String> it = incompatiblePlugins.iterator();
4102
            while (it.hasNext()) {
4103
                String code = it.next();
4104
                item = new Item(code, packages.get(code));
4105
                this.incompatiblePlugins.add(item);
4106
                logger.info("Found plugin '" + item.getCode() + "' incopatibles with each other.");
4107
            }
4108
            initComponents();
4109
        }
4110

    
4111
        private void initComponents() {
4112
            this.contents = new DisablePluginsConflictingLayoutPanel();
4113

    
4114
            doTranslations();
4115

    
4116
            this.contents.buttonClose.addActionListener(new ActionListener() {
4117
                public void actionPerformed(ActionEvent arg0) {
4118
                    doClose();
4119
                }
4120
            });
4121
            this.contents.buttonContinue.addActionListener(new ActionListener() {
4122
                public void actionPerformed(ActionEvent arg0) {
4123
                    doContinue();
4124
                }
4125
            });
4126
            this.contents.pluginList.setModel(new DefaultListModel(this.incompatiblePlugins));
4127
            ListSelectionModel sm = this.contents.pluginList.getSelectionModel();
4128
            sm.setSelectionMode(sm.MULTIPLE_INTERVAL_SELECTION);
4129
            this.setContentPane(this.contents);
4130
            this.pack();
4131

    
4132
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
4133
            setLocation((screenSize.width / 2) - (this.getWidth() / 2),
4134
                    (screenSize.height / 2) - (this.getHeight() / 2));
4135
        }
4136

    
4137
        private void doTranslations() {
4138
            DisablePluginsConflictingLayoutPanel c = this.contents;
4139
            c.lblConflict.setText(translate("_Some_of_plugins_installed_conflict_with_each_other"));
4140
            c.lblSelectPluginToDisable.setText(translate("_Select_the_plugins_that_you_want_to_disable_and_click_the_continue_button"));
4141
            c.lblClickContinue.setText(translate("_You_can_click_on_continue_button_directly_if_you_dont_want_to_disable_any_plugins"));
4142
            c.lblClickClose.setText(translate("_Or_click_the_close_button_to_close_the_application"));
4143
            c.buttonClose.setText(translate("_Close"));
4144
            c.buttonContinue.setText(translate("_Continue"));
4145
        }
4146

    
4147
        private String translate(String msg) {
4148
            return PluginServices.getText(this, msg);
4149
        }
4150

    
4151
        private void doClose() {
4152
            this.action = CLOSE;
4153
            this.setVisible(false);
4154
        }
4155

    
4156
        private void doContinue() {
4157
            this.action = CONTINUE;
4158
            this.setVisible(false);
4159
        }
4160

    
4161
        public int getAction() {
4162
            return this.action;
4163
        }
4164

    
4165
        public List<String> getPluginNamesToDisable() {
4166
            if (this.action == CLOSE) {
4167
                return null;
4168
            }
4169
            Object[] selecteds = null;
4170
            selecteds = (Object[]) this.contents.pluginList.getSelectedValues();
4171
            if (selecteds == null || selecteds.length < 1) {
4172
                return null;
4173
            }
4174
            List<String> values = new ArrayList<String>();
4175
            for (int i = 0; i < selecteds.length; i++) {
4176
                values.add(((Item) selecteds[i]).getCode());
4177
            }
4178
            return values;
4179
        }
4180
    }
4181

    
4182
    private void initializeIdentityManagement(File pluginsFolder) {
4183
        File identityManagementConfigFile = null;
4184
        PluginServices plugin = null;
4185
        Iterator<Entry<String, PluginConfig>> it = pluginsConfig.entrySet().iterator();
4186
        while (it.hasNext()) {
4187
            Entry<String, PluginConfig> entry = it.next();
4188
            File pluginFolder = entry.getValue().getPluginFolder();
4189
            File f = new File(pluginFolder, "identity-management.ini");
4190
            if (f.exists()) {
4191
                if (identityManagementConfigFile != null) {
4192
                    logger.warn("Too many identity-managemnt plugins. Disable all.");
4193
                } else {
4194
                    identityManagementConfigFile = f;
4195
                    plugin = PluginServices.getPluginServices(entry.getKey());
4196
                }
4197
            }
4198
        }
4199
        if(plugin != null){
4200
                new DefaultLibrariesInitializer(plugin.getClassLoader()).fullInitialize(true);
4201
        }
4202
        
4203
        if (identityManagementConfigFile == null || plugin == null) {
4204
            return;
4205
        }
4206
        if (!identityManagementConfigFile.canRead()) {
4207
            return;
4208
        }
4209
        PropertiesConfiguration identityManagementConfig = null;
4210
        try {
4211
            identityManagementConfig = new PropertiesConfiguration(identityManagementConfigFile);
4212
        } catch (Exception ex) {
4213
            logger.warn("Can't open identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.", ex);
4214
            return;
4215
        }
4216
        String identityManagerClassName = identityManagementConfig.getString("IdentityManager", null);
4217
        String identityManagementInitializerClassName = identityManagementConfig.getString("IdentityManagementInitializer", null);
4218
        try {
4219
            if (identityManagerClassName != null) {
4220
                Class identityManagerClass = plugin.getClassLoader().loadClass(identityManagerClassName);
4221
                ToolsLocator.registerIdentityManager(identityManagerClass);
4222
            } else {
4223
                logger.info("Entry IdentityManager not found in identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.");
4224
            }
4225

    
4226
            if (identityManagementInitializerClassName != null) {
4227
                Class identityManagerInitializerClass = plugin.getClassLoader().loadClass(identityManagementInitializerClassName);
4228
                Runnable identityManagerInitializer = (Runnable) identityManagerInitializerClass.newInstance();
4229
                identityManagerInitializer.run();
4230
            } else {
4231
                logger.info("Entry IdentityManagementInitializer not found in identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.");
4232
            }
4233

    
4234
        } catch (Exception ex) {
4235
            logger.warn("Can't initialize the identity manager from '" + identityManagementConfigFile.getAbsolutePath() + ".", ex);
4236
            return;
4237
        }
4238
        logger.info("Loaded an identity manager from plugin '" + plugin.getPluginName() + ".");
4239
    }
4240

    
4241
}