Statistics
| Revision:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
298
            return item;
299
        }
300

    
301
    }
302

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

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

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

    
322
    }
323

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

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

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

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

    
352
    protected static ListBaseException launcherrors = null;
353

    
354
    protected static Theme theme = null;
355

    
356
    private List<String> deprecatedPluginNames = null;
357

    
358
    private static final class ProxyAuth extends Authenticator {
359

    
360
        private PasswordAuthentication auth;
361

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

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

    
371
    private static Launcher launcherInstance;
372

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

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

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

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

    
405
    public static class LaunchException extends ListBaseException {
406

    
407
        private static final long serialVersionUID = 4541192746962684705L;
408

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

    
415
    }
416

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

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

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

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

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

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

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

    
460
        initializeApp(args, null);
461

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
694
        splashWindow.close();
695

    
696
        frame.setCursor(Cursor.DEFAULT_CURSOR);
697

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

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

    
709
    }
710

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

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

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

    
740
    }
741

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

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

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

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

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

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

    
807
        ToolsLocator.registerDefaultToolsLibraries();
808

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

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

    
822
        configureLocales(args);
823

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

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

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

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

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

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

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

    
906
    private class NotificationAppender extends AppenderSkeleton {
907

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

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

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

    
932
        }
933

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

    
940
    }
941

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1198
        XMLEntity entity = new XMLEntity();
1199

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

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

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

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

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

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

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

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

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

    
1271
        Class<? extends IExtension> skinClass;
1272

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

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

    
1302
    }
1303

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

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

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

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

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

    
1365
    }
1366

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

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

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

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

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

    
1397
    private void initializeExtensions() {
1398

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1644
            Extensions extensionConfig = pluginConfig.getExtensions();
1645

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

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

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

    
1679
        }
1680
    }
1681

    
1682
    private TreeSet<SortableMenu> getOrderedMenus() {
1683

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1750
        }
1751

    
1752
        return orderedMenus;
1753
    }
1754

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

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

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

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

    
1778
    public class PluginMenuItem {
1779

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1886
            @Override
1887
            public int compare(ToolBar o1, ToolBar o2) {
1888
                return Integer.compare(o1.getPosition(), o2.getPosition());
1889
            }
1890
        });
1891
        return toolBarsList;        
1892
    }
1893
    
1894
    /**
1895
     * Installs the menus, toolbars, actiontools, selectable toolbars and
1896
     * combos. The order in which they are shown is determined here.
1897
     */
1898
    private void installPluginsControls() {
1899
        logger.info("installPluginsControls (toolbars)");
1900

    
1901
        Iterator<String> pluginNames = pluginsConfig.keySet().iterator();
1902

    
1903
        Map<Extension, PluginServices> extensionPluginServices = new HashMap<Extension, PluginServices>();
1904
        Map<Extension, PluginConfig> extensionPluginConfig = new HashMap<Extension, PluginConfig>();
1905
        Set<Extension> orderedExtensions = new TreeSet<Extension>(
1906
                new ExtensionComparator());
1907

    
1908
                // First of all, sort the extensions.
1909
        // We need to iterate on the plugins, and iterate on each plugin's
1910
        // extensions
1911
        // (each plugin may contain one or more extensions)
1912
        while (pluginNames.hasNext()) { // iterate on the plugins
1913
            String pluginName = pluginNames.next();
1914
            try {
1915
                PluginConfig pc = pluginsConfig.get(pluginName);
1916
                PluginServices ps = pluginsServices.get(pluginName);
1917

    
1918
                Extension[] exts = pc.getExtensions().getExtension();
1919

    
1920
                for (int j = 0; j < exts.length; j++) { // iterate on the
1921
                    // extensions
1922
                    String cname = "unknow";
1923
                    try {
1924
                        cname = exts[j].getClassName();
1925
                        if (exts[j].getActive()
1926
                                && !cname.equals(LibraryExtension.class
1927
                                        .getName())) {
1928
                            if (orderedExtensions.contains(exts[j])) {
1929
                                this
1930
                                        .addError(Messages
1931
                                                .getString("Launcher.Two_extensions_with_the_same_priority")
1932
                                                + cname);
1933
                            }
1934

    
1935
                            orderedExtensions.add(exts[j]);
1936
                            extensionPluginServices.put(exts[j], ps);
1937
                            extensionPluginConfig.put(exts[j], pc);
1938
                        }
1939
                    } catch (Throwable e) {
1940
                        addError("Error initializing controls of plugin '"
1941
                                + pluginName + "' extension '" + cname + "'", e);
1942
                    }
1943
                }
1944
            } catch (Throwable e) {
1945
                addError("Error initializing controls of plugin '" + pluginName
1946
                        + "'", e);
1947
            }
1948
        }
1949

    
1950
        
1951
        // A?ade primero las toolbars ordenadas para garantizar el orden de estas
1952
        for( ToolBar toolbar : getOrderedToolBars() ) {
1953
            frame.addToolBar(toolbar.getName(), toolbar.getDescription(), toolbar.getPosition());
1954
        }
1955

    
1956
        TreeSet<SortableTool> orderedTools = new TreeSet<SortableTool>(
1957
                new ToolComparator());
1958
        Iterator<Extension> e = orderedExtensions.iterator();
1959

    
1960
                // sort the toolbars and tools from 'normal' extensions (actiontools,
1961
        // selectabletools)
1962
        // and load the combo-scales and combo-buttons for the status bar
1963
        while (e.hasNext()) {
1964
            Extension ext = e.next();
1965
            String extName = "unknow";
1966
            try {
1967
                extName = ext.getClassName();
1968
                ToolBar[] toolbars = ext.getToolBar();
1969

    
1970
                // get tools from toolbars
1971
                for (int k = 0; k < toolbars.length; k++) {
1972
                    ActionTool[] tools = toolbars[k].getActionTool();
1973

    
1974
                    for (int t = 0; t < tools.length; t++) {
1975
                        SortableTool sm = new SortableTool(
1976
                                (extensionPluginServices.get(ext))
1977
                                .getClassLoader(), ext, toolbars[k],
1978
                                tools[t]);
1979
                        orderedTools.add(sm);
1980
                    }
1981

    
1982
                    SelectableTool[] sTools = toolbars[k].getSelectableTool();
1983

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

    
1993
                // get controls for statusBar
1994
                PluginServices ps = extensionPluginServices.get(ext);
1995
                PluginClassLoader loader = ps.getClassLoader();
1996

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

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

    
2091
                // Add the tools from MDI extensions to the ordered tool-list, so that
2092
        // we get a sorted list containing all the tools
2093
        pluginNames = pluginsConfig.keySet().iterator();
2094
        while (pluginNames.hasNext()) {
2095
            String pName = (String) pluginNames.next();
2096
            try {
2097
                PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
2098
                PluginServices ps = (PluginServices) pluginsServices.get(pName);
2099

    
2100
                SkinExtension[] skinExts = pc.getExtensions()
2101
                        .getSkinExtension();
2102
                for (int j = 0; j < skinExts.length; j++) {
2103

    
2104
                    if (skinExts[j] != null) {
2105
                        ToolBar[] toolbars = skinExts[j].getToolBar();
2106

    
2107
                        for (int k = 0; k < toolbars.length; k++) {
2108
                            ActionTool[] tools = toolbars[k].getActionTool();
2109

    
2110
                            for (int t = 0; t < tools.length; t++) {
2111
                                SortableTool stb = new SortableTool(ps
2112
                                        .getClassLoader(), skinExts[j],
2113
                                        toolbars[k], tools[t]);
2114
                                orderedTools.add(stb);
2115
                            }
2116

    
2117
                            SelectableTool[] sTools = toolbars[k]
2118
                                    .getSelectableTool();
2119

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

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

    
2175
    /**
2176
     * Adds new plugins to the the andami-config file.
2177
     */
2178
    private void updateAndamiConfig() {
2179
        Set<String> olds = new HashSet<String>();
2180

    
2181
        Plugin[] plugins = andamiConfig.getPlugin();
2182

    
2183
        for (int i = 0; i < plugins.length; i++) {
2184
            olds.add(plugins[i].getName());
2185
        }
2186

    
2187
        Iterator<PluginServices> i = pluginsServices.values().iterator();
2188

    
2189
        while (i.hasNext()) {
2190
            PluginServices ps = i.next();
2191

    
2192
            if (!olds.contains(ps.getPluginName())) {
2193
                Plugin p = new Plugin();
2194
                p.setName(ps.getPluginName());
2195
                p.setUpdate(false);
2196

    
2197
                andamiConfig.addPlugin(p);
2198
            }
2199
        }
2200
    }
2201

    
2202
    private URL[] getPluginClasspathURLs(PluginConfig pluginConfig) {
2203
        URL[] urls = null;
2204

    
2205
        String libfolderPath = pluginConfig.getLibraries().getLibraryDir();
2206
        File libFolderFile = new File(pluginConfig.getPluginFolder(), libfolderPath);
2207

    
2208
        File[] files = libFolderFile.listFiles(new FileFilter() {
2209

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

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

    
2324
        for (String pluginName : orderedPlugins) {
2325
            PluginConfig config = pluginsConfig.get(pluginName);
2326

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

    
2398
        while (iterator.hasNext()) {
2399
            String pluginName = iterator.next();
2400
            config = pluginsConfig.get(pluginName);
2401
            ps = pluginsServices.get(pluginName);
2402

    
2403
            if ((config.getResourceBundle() != null)
2404
                    && !config.getResourceBundle().getName().equals("")) {
2405
                // add the locale files associated with the plugin
2406
                org.gvsig.i18n.Messages.addResourceFamily(config
2407
                        .getResourceBundle().getName(), ps.getClassLoader(),
2408
                        pluginName);
2409
                org.gvsig.i18n.Messages.addResourceFamily("i18n." + config
2410
                        .getResourceBundle().getName(), ps.getClassLoader(),
2411
                        pluginName);
2412
            }
2413
        }
2414
    }
2415

    
2416
    static public PluginServices getPluginServices(String name) {
2417
        return (PluginServices) pluginsServices.get(name);
2418
    }
2419

    
2420
    static String getPluginsDir() {
2421
        return andamiConfig.getPluginsDirectory();
2422
    }
2423

    
2424
    static File getPluginFolder(String pluginName) {
2425
        return pluginsConfig.get(pluginName).getPluginFolder();
2426
    }
2427

    
2428
    static void setPluginsDir(String s) {
2429
        andamiConfig.setPluginsDirectory(s);
2430
    }
2431

    
2432
    static MDIFrame getMDIFrame() {
2433
        return frame;
2434
    }
2435

    
2436
    private PluginsConfig loadPluginConfigs() {
2437
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
2438
        List<File> repositoriesFolders = installerManager.getLocalAddonRepositories("plugin");
2439
        for (File repositoryFolder : repositoriesFolders) {
2440
            logger.info("Loading plugins configuration from repository folder " + repositoryFolder.getAbsolutePath() + ".");
2441

    
2442
            if (!repositoryFolder.exists()) {
2443
                logger.warn("Plugins repository folder not found '" + repositoryFolder.getAbsolutePath() + "'.");
2444
                continue;
2445
            }
2446

    
2447
            File[] pluginsFolders = repositoryFolder.listFiles();
2448
            if (pluginsFolders.length == 0) {
2449
                logger.info("Plugins repository folder is empty '" + repositoryFolder.getAbsolutePath() + "'.");
2450
                continue;
2451
            }
2452

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

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

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

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

    
2488
                }
2489
            }
2490
        }
2491
        return pluginsConfig;
2492
    }
2493

    
2494
    private static Locale getLocale(String language, String country,
2495
            String variant) {
2496
        if (variant != null) {
2497
            return new Locale(language, country, variant);
2498
        } else if (country != null) {
2499
            return new Locale(language, country);
2500
        } else if (language != null) {
2501
            return new Locale(language);
2502
        } else {
2503
            return new Locale("es");
2504
        }
2505
    }
2506

    
2507
    private static void andamiConfigToXML(String file) throws IOException,
2508
            MarshalException, ValidationException {
2509
                // write on a temporary file in order to not destroy current file if
2510
        // there is some problem while marshaling
2511
        File tmpFile = new File(file + "-"
2512
                + DateTime.getCurrentDate().getTime());
2513
        File xml = new File(file);
2514
        File parent = xml.getParentFile();
2515
        parent.mkdirs();
2516

    
2517
        BufferedOutputStream os = new BufferedOutputStream(
2518
                new FileOutputStream(tmpFile));
2519
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
2520
        andamiConfig.marshal(writer);
2521
        writer.close();
2522

    
2523
                // if marshaling process finished correctly, move the file to the
2524
        // correct one
2525
        xml.delete();
2526
        if (!tmpFile.renameTo(xml)) {
2527
            // if rename was not succesful, try copying it
2528
            FileChannel sourceChannel = new FileInputStream(tmpFile)
2529
                    .getChannel();
2530
            FileChannel destinationChannel = new FileOutputStream(xml)
2531
                    .getChannel();
2532
            sourceChannel.transferTo(0, sourceChannel.size(),
2533
                    destinationChannel);
2534
            sourceChannel.close();
2535
            destinationChannel.close();
2536
        }
2537
    }
2538

    
2539
    private static void andamiConfigFromXML(String file)
2540
            throws ConfigurationException {
2541
        File xml = new File(file);
2542

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

    
2575
    private static AndamiConfig getDefaultAndamiConfig() {
2576
        AndamiConfig andamiConfig = new AndamiConfig();
2577

    
2578
        Andami andami = new Andami();
2579
        andami.setUpdate(true);
2580
        andamiConfig.setAndami(andami);
2581
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
2582
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
2583
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
2584

    
2585
        if (System.getProperty("javawebstart.version") != null) // Es java web
2586
        // start)
2587
        {
2588
            andamiConfig
2589
                    .setPluginsDirectory(new File(appHomeDir, "extensiones")
2590
                            .getAbsolutePath());
2591
        } else {
2592
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
2593
                    .getAbsolutePath());
2594
        }
2595

    
2596
        andamiConfig.setPlugin(new Plugin[0]);
2597
        return andamiConfig;
2598
    }
2599

    
2600
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
2601
        File xml = getPluginsPersistenceFile(true);
2602

    
2603
        if (xml.exists()) {
2604
            InputStreamReader reader = null;
2605

    
2606
            try {
2607
                reader = XMLEncodingUtils.getReader(xml);
2608
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2609
                return new XMLEntity(tag);
2610
            } catch (FileNotFoundException e) {
2611
                throw new ConfigurationException(e);
2612
            } catch (MarshalException e) {
2613

    
2614
                                // try to reopen with default encoding (for backward
2615
                // compatibility)
2616
                try {
2617
                    reader = new FileReader(xml);
2618
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2619
                    return new XMLEntity(tag);
2620

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

    
2655
    private static File getPluginsPersistenceFile(boolean read) {
2656
        if (read) {
2657
            File pluginsPersistenceFile = new File(getAppHomeDir(),
2658
                    "plugins-persistence-2_0.xml");
2659
            if (pluginsPersistenceFile.exists()) {
2660
                return pluginsPersistenceFile;
2661
            }
2662
            pluginsPersistenceFile = new File(getAppHomeDir(),
2663
                    "plugins-persistence.xml");
2664
            if (pluginsPersistenceFile.exists()) {
2665
                return pluginsPersistenceFile;
2666
            }
2667
        }
2668
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2669

    
2670
    }
2671

    
2672
    private static void persistenceToXML(XMLEntity entity)
2673
            throws ConfigurationException {
2674
                // write on a temporary file in order to not destroy current file if
2675
        // there is some problem while marshaling
2676
        File tmpFile = new File(getPluginsPersistenceFile(false).getPath()
2677
                + "-" + DateTime.getCurrentDate().getTime());
2678

    
2679
        File xml = getPluginsPersistenceFile(false);
2680
        OutputStreamWriter writer = null;
2681

    
2682
        try {
2683
            writer = new OutputStreamWriter(new FileOutputStream(tmpFile),
2684
                    CASTORENCODING);
2685
            entity.getXmlTag().marshal(writer);
2686
            writer.close();
2687

    
2688
                        // if marshaling process finished correctly, move the file to the
2689
            // correct one
2690
            xml.delete();
2691
            if (!tmpFile.renameTo(xml)) {
2692
                // if rename was not succesful, try copying it
2693
                FileChannel sourceChannel = new FileInputStream(tmpFile)
2694
                        .getChannel();
2695
                FileChannel destinationChannel = new FileOutputStream(xml)
2696
                        .getChannel();
2697
                sourceChannel.transferTo(0, sourceChannel.size(),
2698
                        destinationChannel);
2699
                sourceChannel.close();
2700
                destinationChannel.close();
2701

    
2702
            }
2703
        } catch (FileNotFoundException e) {
2704
            throw new ConfigurationException(e);
2705
        } catch (MarshalException e) {
2706
            // try to close the stream, maybe it remains open
2707
            if (writer != null) {
2708
                try {
2709
                    writer.close();
2710
                } catch (IOException e1) {
2711
                }
2712
            }
2713
        } catch (ValidationException e) {
2714
            throw new ConfigurationException(e);
2715
        } catch (IOException e) {
2716
            throw new ConfigurationException(e);
2717
        }
2718
    }
2719

    
2720
    static MDIFrame getFrame() {
2721
        return frame;
2722
    }
2723

    
2724
    /**
2725
     * Gracefully closes the application. It shows dialogs to save data, finish
2726
     * processes, etc, then it terminates the extensions, removes temporal files
2727
     * and finally exits.
2728
     */
2729
    public synchronized static void closeApplication() {
2730
        TerminationProcess terminationProcess = (new Launcher()).new TerminationProcess();
2731
        terminationProcess.run();
2732
    }
2733

    
2734
    static HashMap getClassesExtensions() {
2735
        return classesExtensions;
2736
    }
2737

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

    
2759
        while (iter.hasNext()) {
2760
            array.add(iter.next().getExtensions());
2761
        }
2762

    
2763
        return array.toArray(new Extensions[array.size()]);
2764
    }
2765

    
2766
    public static Iterator getExtensionIterator() {
2767
        return extensions.iterator();
2768
    }
2769

    
2770
    public static HashMap getPluginConfig() {
2771
        return pluginsConfig;
2772
    }
2773

    
2774
    public static Extension getExtension(String s) {
2775
        Extensions[] exts = getExtensions();
2776

    
2777
        for (int i = 0; i < exts.length; i++) {
2778
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2779
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2780
                    return exts[i].getExtension(j);
2781
                }
2782
            }
2783
        }
2784

    
2785
        return null;
2786
    }
2787

    
2788
    public static AndamiConfig getAndamiConfig() {
2789
        return andamiConfig;
2790
    }
2791

    
2792
    private static class ExtensionComparator implements Comparator {
2793

    
2794
        public int compare(Object o1, Object o2) {
2795
            Extension e1 = (Extension) o1;
2796
            Extension e2 = (Extension) o2;
2797

    
2798
            if (!e1.hasPriority() && !e2.hasPriority()) {
2799
                return -1;
2800
            }
2801

    
2802
            if (e1.hasPriority() && !e2.hasPriority()) {
2803
                return Integer.MIN_VALUE;
2804
            }
2805

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

    
2810
            if (e1.getPriority() != e2.getPriority()) {
2811
                return e2.getPriority() - e1.getPriority();
2812
            } else {
2813
                return (e2.toString().compareTo(e1.toString()));
2814
            }
2815
        }
2816
    }
2817

    
2818
    private static class MenuComparator implements Comparator<SortableMenu> {
2819

    
2820
        private static ExtensionComparator extComp = new ExtensionComparator();
2821

    
2822
        public int compare(SortableMenu e1, SortableMenu e2) {
2823

    
2824
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2825
                if (e1.extension instanceof SkinExtensionType) {
2826
                    return 1;
2827
                } else if (e2.extension instanceof SkinExtensionType) {
2828
                    return -1;
2829
                } else {
2830
                    return extComp.compare(e1.extension, e2.extension);
2831
                }
2832
            }
2833

    
2834
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2835
                return Integer.MIN_VALUE;
2836
            }
2837

    
2838
            if (e2.menu.hasPosition() && !e1.menu.hasPosition()) {
2839
                return Integer.MAX_VALUE;
2840
            }
2841

    
2842
            if (e1.menu.getPosition() == e2.menu.getPosition()) {
2843
                                // we don't return 0 unless both objects are the same, otherwise
2844
                // the objects get overwritten in the treemap
2845
                return (e1.toString().compareTo(e2.toString()));
2846
            }
2847
            if (e1.menu.getPosition() > e2.menu.getPosition()) {
2848
                return Integer.MAX_VALUE;
2849
            }
2850
            return Integer.MIN_VALUE;
2851

    
2852
        }
2853
    }
2854

    
2855
    private static class SortableMenu {
2856

    
2857
        public PluginClassLoader loader;
2858
        public Menu menu;
2859
        public SkinExtensionType extension;
2860

    
2861
        public SortableMenu(PluginClassLoader loader,
2862
                SkinExtensionType skinExt, Menu menu2) {
2863
            extension = skinExt;
2864
            menu = menu2;
2865
            this.loader = loader;
2866
        }
2867

    
2868
    }
2869

    
2870
    private static class SortableTool {
2871

    
2872
        public PluginClassLoader loader;
2873
        public ToolBar toolbar;
2874
        public ActionTool actiontool;
2875
        public SelectableTool selectabletool;
2876
        public SkinExtensionType extension;
2877

    
2878
        public SortableTool(PluginClassLoader loader,
2879
                SkinExtensionType skinExt, ToolBar toolbar2,
2880
                ActionTool actiontool2) {
2881
            extension = skinExt;
2882
            toolbar = toolbar2;
2883
            actiontool = actiontool2;
2884
            this.loader = loader;
2885
        }
2886

    
2887
        public SortableTool(PluginClassLoader loader,
2888
                SkinExtensionType skinExt, ToolBar toolbar2,
2889
                SelectableTool selectabletool2) {
2890
            extension = skinExt;
2891
            toolbar = toolbar2;
2892
            selectabletool = selectabletool2;
2893
            this.loader = loader;
2894
        }
2895
    }
2896

    
2897
    private static class ToolBarComparator implements Comparator<SortableTool> {
2898

    
2899
        private static ExtensionComparator extComp = new ExtensionComparator();
2900

    
2901
        public int compare(SortableTool e1, SortableTool e2) {
2902

    
2903
                        // if the toolbars have the same name, they are considered to be
2904
            // the same toolbar, so we don't need to do further comparing
2905
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2906
                return 0;
2907
            }
2908

    
2909
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2910
                if (e1.extension instanceof SkinExtensionType) {
2911
                    return 1;
2912
                } else if (e2.extension instanceof SkinExtensionType) {
2913
                    return -1;
2914
                } else {
2915
                    return extComp.compare(e1.extension, e2.extension);
2916
                }
2917
            }
2918

    
2919
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2920
                return Integer.MIN_VALUE;
2921
            }
2922

    
2923
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2924
                return Integer.MAX_VALUE;
2925
            }
2926
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2927
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2928
            }
2929

    
2930
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2931
                    && e1.toolbar.getSelectableTool().equals(
2932
                            e2.toolbar.getSelectableTool())) {
2933
                return 0;
2934
            }
2935
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2936
        }
2937
    }
2938

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

    
2963
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2964

    
2965
        public int compare(SortableTool e1, SortableTool e2) {
2966
            // compare the toolbars which contain the tools
2967
            long result = toolBarComp.compare(e1, e2);
2968
            if (result != 0) { // if the toolbars are different, use their order
2969
                return result > 0 ? 1 : -1;
2970
            }
2971
            // otherwise, compare the tools
2972
            long e1Position = -1, e2Position = -1;
2973

    
2974
            if (e1.actiontool != null) {
2975
                if (e1.actiontool.hasPosition()) {
2976
                    e1Position = e1.actiontool.getPosition();
2977
                }
2978
            } else if (e1.selectabletool != null) {
2979
                if (e1.selectabletool.hasPosition()) {
2980
                    e1Position = e1.selectabletool.getPosition();
2981
                }
2982
            }
2983

    
2984
            if (e2.actiontool != null) {
2985
                if (e2.actiontool.hasPosition()) {
2986
                    e2Position = e2.actiontool.getPosition();
2987
                }
2988
            } else if (e2.selectabletool != null) {
2989
                if (e2.selectabletool.hasPosition()) {
2990
                    e2Position = e2.selectabletool.getPosition();
2991
                }
2992
            }
2993

    
2994
            if ((e1Position == -1) && (e2Position != -1)) {
2995
                return 1;
2996
            }
2997
            if ((e1Position != -1) && (e2Position == -1)) {
2998
                return -1;
2999
            }
3000
            if ((e1Position != -1) && (e2Position != -1)) {
3001
                result = e1Position - e2Position;
3002
                                // we don't return 0 unless both objects are the same, otherwise
3003
                // the objects get overwritten in the treemap
3004
                if (result != 0) {
3005
                    return result > 0 ? 1 : -1;
3006
                }
3007
            }
3008
            return e1.toString().compareTo(e2.toString());
3009
        }
3010
    }
3011

    
3012
    public static String getDefaultLookAndFeel() {
3013
        String osName = (String) System.getProperty("os.name");
3014

    
3015
        if ((osName.length() > 4)
3016
                && osName.substring(0, 5).toLowerCase().equals("linux")) {
3017
            return nonWinDefaultLookAndFeel;
3018
        }
3019
        if (osName.toLowerCase().startsWith("mac os x")) {
3020
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
3021
        }
3022

    
3023
        return UIManager.getSystemLookAndFeelClassName();
3024
    }
3025

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

    
3058
                    while ((line = reader.readLine()) != null) {
3059
                        String[] language = line.split("\t");
3060
                        if (language[0].equals(langCode)) {
3061
                                                        // the three
3062
                            // characters code
3063
                            return language[2]; // third column i the two
3064
                            // characters code
3065
                        }
3066
                    }
3067
                } catch (IOException ex) {
3068
                    logger.error(Messages
3069
                            .getString("Error_reading_isocodes_file"), ex);
3070
                    return "es";
3071
                }
3072
            } else {
3073
                logger.error(Messages.getString("Error_reading_isocodes_file"));
3074
                return "es";
3075
            }
3076
        }
3077
        return "es";
3078
    }
3079

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

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

    
3141
        URL[] i18nURLs = getURLsFromI18nFolders(userI18nFolder, appI18nFolder);
3142
        ClassLoader i18nClassLoader = URLClassLoader.newInstance(i18nURLs, null);
3143
        logger.info("loading resources from classloader " + i18nClassLoader.toString() + ".");
3144
        org.gvsig.i18n.Messages.addResourceFamily("text", i18nClassLoader,
3145
                "Andami Launcher");
3146

    
3147
        // Finally load the andami own i18n resources
3148
        org.gvsig.i18n.Messages.addResourceFamily("org.gvsig.andami.text",
3149
                "Andami Launcher");
3150
    }
3151

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

    
3190
    /**
3191
     * Gets Home Directory location of the application into users home folder.
3192
     *
3193
     * May be set from outside the aplication by means of
3194
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name of the application
3195
     *
3196
     * @return
3197
     */
3198
    public static String getAppHomeDir() {
3199
        return appHomeDir;
3200
    }
3201

    
3202
    public static File getApplicationHomeFolder() {
3203
        return new File(getAppHomeDir());
3204
    }
3205

    
3206
    /**
3207
     * Sets Home Directory location of the application. May be set from outside
3208
     * the aplication by means of -DgvSIG.home=C:/data/gvSIG, where gvSIG its
3209
     * the name of the application
3210
     *
3211
     * @param appHomeDir
3212
     */
3213
    public static void setAppHomeDir(String appHomeDir) {
3214
        Launcher.appHomeDir = appHomeDir;
3215
    }
3216

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

    
3235
        Iterator<Class<? extends IExtension>> iter = classesExtensions.keySet()
3236
                .iterator();
3237
        int charIndex;
3238
        Class<? extends IExtension> key;
3239
        while (iter.hasNext()) {
3240
            key = iter.next();
3241
            charIndex = key.getName().indexOf(name);
3242
            // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex);
3243
            if (charIndex == 0) {
3244
                IExtension ext = classesExtensions.get(key);
3245
                if (ext instanceof ExtensionDecorator) {
3246
                    ext = ((ExtensionDecorator) ext).getExtension();
3247
                }
3248
                if (ext instanceof ExclusiveUIExtension) {
3249
                    PluginServices
3250
                            .setExclusiveUIExtension((ExclusiveUIExtension) ext);
3251
                }
3252
                break;
3253
            }
3254
        }
3255

    
3256
        logger
3257
                .error(Messages
3258
                        .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
3259
                        + " '" + name + "'");
3260
    }
3261

    
3262
    public static void initIconThemes() {
3263
        PluginsManager pluginsManager = PluginsLocator.getManager();
3264
        IconThemeManager iconManager = ToolsSwingLocator.getIconThemeManager();
3265

    
3266
        File f = new File(pluginsManager.getApplicationHomeFolder(), "icon-theme");
3267
        if (!f.exists()) {
3268
            try {
3269
                f.mkdir();
3270
            } catch (Exception ex) {
3271
                // Do nothing
3272
            }
3273
        }
3274
        iconManager.getRepository().add(f, "_User");
3275

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

    
3286
        Preferences prefs = Preferences.userRoot().node("gvsig.icontheme");
3287
        String defaultThemeID = prefs.get("default-theme", null);
3288
        if (defaultThemeID != null) {
3289
            IconTheme iconTheme = iconManager.get(defaultThemeID);
3290
            if (iconTheme != null) {
3291
                iconManager.setCurrent(iconTheme);
3292
            }
3293
        }
3294
    }
3295

    
3296
    public static void manageUnsavedData(String prompt) throws Exception {
3297
        final UnsavedDataPanel panel = new UnsavedDataPanel(prompt);
3298
        final List<IUnsavedData> unsavedData = PluginsLocator.getManager().getUnsavedData();
3299
        panel.setUnsavedData(unsavedData);
3300

    
3301
        panel.addActionListener(panel.new UnsavedDataPanelListener() {
3302

    
3303
            public void cancel(UnsavedDataPanel panel) {
3304
                panel.setVisible(false);
3305
            }
3306

    
3307
            public void discard(UnsavedDataPanel panel) {
3308
                panel.setVisible(false);
3309
            }
3310

    
3311
            public void accept(UnsavedDataPanel panel) {
3312
                panel.setVisible(false);
3313

    
3314
                try {
3315
                    PluginsLocator.getManager().saveUnsavedData(panel.getSelectedsUnsavedDataList());
3316
                } catch (UnsavedDataException e) {
3317
                    StringBuilder msg = new StringBuilder();
3318
                    msg.append(PluginServices.getText(this, "The_following_resources_could_not_be_saved"));
3319
                    msg.append("\n");
3320
                    for (Iterator iterator = e.getUnsavedData().iterator(); iterator.hasNext();) {
3321
                        IUnsavedData unsavedData = (IUnsavedData) iterator.next();
3322
                        msg.append(unsavedData.getResourceName());
3323
                        msg.append(" -- ");
3324
                        msg.append(unsavedData.getDescription());
3325
                        msg.append("\n");
3326
                    }
3327
                    JOptionPane.showMessageDialog(panel, msg, PluginServices.getText(this, "Resources_was_not_saved"), JOptionPane.ERROR_MESSAGE);
3328
                }
3329
            }
3330
        });
3331

    
3332
        //TODO: mostrar panel WindowManager
3333
        ToolsSwingLocator.getWindowManager().showWindow(
3334
                panel,
3335
                PluginServices.getText(panel, "Resource_was_not_saved"),
3336
                MODE.DIALOG);
3337

    
3338
    }
3339

    
3340
    /**
3341
     * Manages Andami termination process
3342
     *
3343
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
3344
     */
3345
    public class TerminationProcess {
3346

    
3347
        private boolean proceed = false;
3348
        private UnsavedDataPanel panel = null;
3349

    
3350
        public void run() {
3351
            try {
3352
                int exit = manageUnsavedData();
3353
                if ((exit == JOptionPane.NO_OPTION)
3354
                        || (exit == JOptionPane.CLOSED_OPTION)) {
3355
                    // the user doesn't want to exit
3356
                    return;
3357
                }
3358
                closeAndami();
3359
            } catch (Exception e) {
3360
                logger.warn("It is not possible to close the application", e);
3361
                                // It is not possible to close the application.
3362
                // this exception has been registered before
3363
            }
3364
        }
3365

    
3366
        /**
3367
         * Finishes the application without asking user if want or not to save
3368
         * unsaved data.
3369
         */
3370
        public void closeAndami() {
3371
            PluginsManager pluginsManager = PluginsLocator.getManager();
3372
            pluginsManager.executeShutdownTasks();
3373

    
3374
            try {
3375
                saveAndamiConfig();
3376
            } catch (Exception ex) {
3377
                logger.error(
3378
                        "There was an error exiting application, can't save andami-config.xml",
3379
                        ex
3380
                );
3381
            }
3382

    
3383
            try {
3384
                // Persistencia de los plugins
3385
                savePluginPersistence();
3386
                savePluginsProperties();
3387
            } catch (Exception ex) {
3388
                logger.error(
3389
                        "There was an error exiting application, can't save plugins properties",
3390
                        ex
3391
                );
3392
            }
3393

    
3394
            // Finalize all the extensions
3395
            finalizeExtensions();
3396

    
3397
            try {
3398
                // Clean any temp data created
3399
                Utilities.cleanUpTempFiles();
3400
            } catch (Exception ex) {
3401
                logger.error(
3402
                        "There was an error exiting application, can't remove temporary files",
3403
                        ex
3404
                );
3405
            }
3406

    
3407
            logger.info("Quiting application.");
3408

    
3409
            // Para la depuraci?n de memory leaks
3410
            System.gc();
3411

    
3412
            System.exit(0);
3413
        }
3414

    
3415
        public void saveAndamiConfig() {
3416
            // Configuraci?n de Andami
3417
            try {
3418
                andamiConfigToXML(andamiConfigPath);
3419
            } catch (MarshalException e) {
3420
                logger
3421
                        .error(
3422
                                Messages
3423
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3424
                                e);
3425
            } catch (ValidationException e) {
3426
                logger
3427
                        .error(
3428
                                Messages
3429
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3430
                                e);
3431
            } catch (IOException e) {
3432
                logger
3433
                        .error(
3434
                                Messages
3435
                                .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
3436
                                e);
3437
            }
3438
        }
3439

    
3440
        private void savePluginsProperties() {
3441
            PluginsManager manager = PluginsLocator.getManager();
3442
            List<PluginServices> plugins = manager.getPlugins();
3443
            for (PluginServices plugin : plugins) {
3444
                if (plugin != null) {
3445
                    plugin.savePluginProperties();
3446
                }
3447
            }
3448
        }
3449

    
3450
        /**
3451
         * Exectutes the terminate method for all the extensions, in the reverse
3452
         * order they were initialized
3453
         *
3454
         */
3455
        private void finalizeExtensions() {
3456
            for (int i = extensions.size() - 1; i >= 0; i--) {
3457
                org.gvsig.andami.plugins.IExtension extensionInstance = (org.gvsig.andami.plugins.IExtension) extensions
3458
                        .get(i);
3459
                String extensionName = "(unknow)";
3460
                try {
3461
                    extensionName = extensionInstance.getClass().getName();
3462
                    extensionInstance.terminate();
3463
                } catch (Exception ex) {
3464
                    logger.error(MessageFormat.format(
3465
                            "There was an error extension ending {0}",
3466
                            extensionName), ex);
3467
                }
3468
            }
3469
        }
3470

    
3471
        private IUnsavedData[] getUnsavedData() throws Exception {
3472
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
3473
            IExtension exclusiveExtension = PluginServices
3474
                    .getExclusiveUIExtension();
3475

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

    
3513
        public UnsavedDataPanel getUnsavedDataPanel() {
3514
            if (panel == null) {
3515
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
3516
            }
3517
            return panel;
3518
        }
3519

    
3520
        /**
3521
         * Checks if the extensions have some unsaved data, and shows a dialog
3522
         * to allow saving it. This dialog also allows to don't exit Andami.
3523
         *
3524
         * @return true if the user confirmed he wishes to exit, false otherwise
3525
         * @throws Exception
3526
         */
3527
        public int manageUnsavedData() throws Exception {
3528
            IUnsavedData[] unsavedData = getUnsavedData();
3529

    
3530
            // there was no unsaved data
3531
            if (unsavedData.length == 0) {
3532
                int option = JOptionPane
3533
                        .showConfirmDialog(frame, Messages
3534
                                .getString("MDIFrame.quiere_salir"), Messages
3535
                                .getString("MDIFrame.salir"),
3536
                                JOptionPane.YES_NO_OPTION);
3537
                return option;
3538
            }
3539

    
3540
            UnsavedDataPanel panel = getUnsavedDataPanel();
3541
            panel.setUnsavedDataArray(unsavedData);
3542

    
3543
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
3544

    
3545
                public void cancel(UnsavedDataPanel panel) {
3546
                    proceed(false);
3547
                    PluginServices.getMDIManager().closeWindow(panel);
3548

    
3549
                }
3550

    
3551
                public void discard(UnsavedDataPanel panel) {
3552
                    proceed(true);
3553
                    PluginServices.getMDIManager().closeWindow(panel);
3554

    
3555
                }
3556

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

    
3588
                            try {
3589
                                unsavedDataArray = getUnsavedData();
3590
                            } catch (Exception e) {
3591
                                // This exception has been registered before
3592
                            }
3593
                            panel.setUnsavedDataArray(unsavedDataArray);
3594
                            return;
3595
                        }
3596
                    }
3597
                    proceed(true);
3598
                    PluginServices.getMDIManager().closeWindow(panel);
3599
                }
3600
            });
3601

    
3602
            PluginServices.getMDIManager().addWindow(panel);
3603
            if (proceed) {
3604
                return JOptionPane.YES_OPTION;
3605
            } else {
3606
                return JOptionPane.NO_OPTION;
3607
            }
3608
        }
3609

    
3610
        private void proceed(boolean proceed) {
3611
            this.proceed = proceed;
3612
        }
3613

    
3614
    }
3615

    
3616
    public static TerminationProcess getTerminationProcess() {
3617
        return (new Launcher()).new TerminationProcess();
3618
    }
3619

    
3620
    private PackageInfo getPackageInfo(String pluginsFolder) {
3621
        try {
3622
            PluginsManager pm = PluginsLocator.getManager();
3623
            return pm.getPackageInfo();
3624
        } catch (Exception e) {
3625
            logger.info("Can't locate PackageInfo from plugin org.gvsig.app", e);
3626
            return null;
3627
        }
3628
    }
3629

    
3630
    /**
3631
     * Launch the gvSIG package installer.
3632
     *
3633
     * @throws Exception if there is any error
3634
     */
3635
    private void doInstall(String[] args) throws Exception {
3636
        String installURL = null;
3637
        String installURLFile = null;
3638
        String gvSIGVersion = null;
3639
        String[] myArgs = new String[3];
3640
        PackageInfo packageInfo = null;
3641

    
3642
        Options options = new Options();
3643
        options.addOption("i", "install", false, "install");
3644
        options.addOption("u", "installURL", true, "installURL");
3645
        options.addOption("f", "installURLFile", true, "installURLFile");
3646
        options.addOption("v", "installVersion", true, "installVersion");
3647
        options.addOption("A", "applicationName", true, "application name, default is gvSIG");
3648
        options.addOption("P", "pluginsFolder", true, "pluginsFolder");
3649
        options.addOption("l", "language", true, "language");
3650

    
3651
        // This options are managed by the gvSIG.sh but need to be declared here to avoid
3652
        // errors.
3653
        options.addOption(null, "debug", false, "Activate the JVM remote debug");
3654
        options.addOption(null, "pause", false, "Pause when activate JVM debug");
3655

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

    
3679
            if (line.hasOption("installVersion")) {
3680
                gvSIGVersion = line.getOptionValue("installVersion");
3681
            }
3682
            if (line.hasOption("applicationName")) {
3683
                myArgs[0] = line.getOptionValue("applicationName");
3684
            } else {
3685
                myArgs[0] = "gvSIG";
3686
            }
3687
            if (line.hasOption("pluginsFolder")) {
3688
                myArgs[1] = line.getOptionValue("pluginsFolder");
3689
            } else {
3690
                myArgs[1] = "gvSIG/extensiones";
3691
            }
3692
            if (line.hasOption("language")) {
3693
                myArgs[2] = "language=" + line.getOptionValue("language");
3694
            } else {
3695
                // prevent null
3696
                myArgs[2] = Locale.getDefault().toString();
3697
            }
3698

    
3699
            if (line.hasOption("installURL")) {
3700
                installURL = line.getOptionValue("installURL");
3701
            } else {
3702
                installURL = "http://downloads.gvsig.org/download/gvsig-desktop/";
3703
            }
3704

    
3705
            if (line.hasOption("installURLFile")) {
3706
                installURLFile = line.getOptionValue("installURLFile");
3707
            } else {
3708
                installURLFile = "gvsig-installer-urls.config";
3709
            }
3710

    
3711
            if (!hasAllMandatoryOptions) {
3712
                System.err.println(Messages.get("usage") + ": Launcher "
3713
                        + "--install "
3714
                        + "[--applicationName=appName] "
3715
                        + "[--pluginsFolder=plugins-directory] "
3716
                        + "[--installURLFile=File] "
3717
                        + "[--installURL=URL] "
3718
                        + "[--language=locale]"
3719
                );
3720
                return;
3721
            }
3722
        } catch (ParseException exp) {
3723
            System.err.println("Unexpected exception:" + exp.getMessage());
3724
            System.exit(-1);
3725
        }
3726

    
3727
        initializeApp(myArgs, "installer");
3728

    
3729
        new DefaultLibrariesInitializer().fullInitialize(true);
3730

    
3731
        initializeInstallerManager();
3732

    
3733
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
3734
        
3735
        try {
3736
            logger.info("Loading plugins configurations");
3737
            this.loadPluginConfigs();
3738
        } catch (Throwable ex) {
3739
            logger.warn("Can't load plugins configurations", ex);
3740
        }
3741

    
3742
        try {
3743
            logger.info("Loading plugins");
3744
            this.loadPluginServices();
3745
        } catch (Throwable ex) {
3746
            logger.warn("Can't load plugins", ex);
3747
        }
3748

    
3749
        AndamiConfig config = getAndamiConfig();
3750

    
3751
        initializeIdentityManagement(new File(config.getPluginsDirectory()).getAbsoluteFile());
3752

    
3753
        initializeLibraries();
3754

    
3755
        packageInfo = getPackageInfo(myArgs[1]);
3756

    
3757
        // set the gvSIG version to the install manager, to compose the download URL
3758
        if (packageInfo != null) {
3759
            installerManager.setVersion(packageInfo.getVersion());
3760
        } else {
3761
            installerManager.setVersion(gvSIGVersion);
3762
        }
3763
        if (!installURL.contains(";")
3764
                && !installURL.endsWith(InstallerManager.PACKAGE_EXTENSION)
3765
                && !installURL.endsWith(InstallerManager.PACKAGE_INDEX_EXTENSION)) {
3766
            if (packageInfo != null && (packageInfo.getState().startsWith(InstallerManager.STATE.BETA)
3767
                    || packageInfo.getState().startsWith(InstallerManager.STATE.RC)
3768
                    || packageInfo.getState().equalsIgnoreCase(InstallerManager.STATE.FINAL))) {
3769
                installURL = installURL + "dists/<%Version%>/builds/<%Build%>/packages.gvspki";
3770
            }
3771
        }
3772
        // Configure default index download URL
3773
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(installURL);
3774

    
3775
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(new File(installURLFile));
3776

    
3777
        // Launch installer
3778
        PluginsManager manager = PluginsLocator.getManager();
3779

    
3780
        InstallWizardPanel installPackageWizard = SwingInstallerLocator
3781
                .getSwingInstallerManager().createInstallPackageWizard(
3782
                        manager.getApplicationFolder(),
3783
                        manager.getInstallFolder());
3784
        installPackageWizard.setWizardActionListener(new InstallerWizardActionListener() {
3785
            @Override
3786
            public void finish(InstallerWizardPanel installerWizard) {
3787
                logger.info("Finish installation.");
3788
                System.exit(0);
3789
            }
3790

    
3791
            @Override
3792
            public void cancel(InstallerWizardPanel installerWizard) {
3793
                logger.info("Cancel installation.");
3794
                System.exit(0);
3795
            }
3796
        });
3797

    
3798
        // the wizard will show the Typical or Advanced mode option.
3799
        installPackageWizard.setSkipTypicalOrAdvancedWizardPage(false);
3800
        // default packages will be selected.
3801
        installPackageWizard.setSelectDefaultPackages(true);
3802

    
3803
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
3804
        frame.addWindowListener(new WindowAdapter() {
3805
            @Override
3806
            public void windowClosing(WindowEvent we) {
3807
                logger.info("Closing installation.");
3808
                System.exit(0);
3809
            }
3810

    
3811
            @Override
3812
            public void windowClosed(WindowEvent we) {
3813
                logger.info("Close installation.");
3814
                System.exit(0);
3815
            }
3816
        });
3817
        frame.getContentPane().add(installPackageWizard.asJComponent(), BorderLayout.CENTER);
3818
        URL iconURL = getClass().getResource("/images/main/install-icon.png");
3819
        if( iconURL!=null ) {
3820
            ImageIcon icon = new ImageIcon(iconURL);
3821
            frame.setIconImage(icon.getImage());
3822
        }
3823
        frame.pack();
3824
        frame.setLocationRelativeTo(null);
3825

    
3826
        frame.setVisible(true);
3827
    }
3828

    
3829
    public static String getInformation() {
3830
        return getInformation(null);
3831
    }
3832

    
3833
    private static final int INFO_OS_NAME = 0;
3834
    private static final int INFO_OS_ARCH = 1;
3835
    private static final int INFO_OS_VERSION = 2;
3836
    private static final int INFO_OS_ADITIONAL = 3;
3837
    private static final int INFO_JRE_VENDOR = 4;
3838
    private static final int INFO_JRE_VERSION = 5;
3839
    private static final int INFO_JRE_HOME = 6;
3840
    private static final int INFO_PROXY_HOST = 7;
3841
    private static final int INFO_PROXY_PORT = 8;
3842
    private static final int INFO_PROXY_USER = 9;
3843
    private static final int INFO_PROXY_PASSWORD = 10;
3844
    private static final int INFO_APP_LOCALE = 11;
3845
    private static final int INFO_APP_FOLDER = 12;
3846
    private static final int INFO_APP_HOME = 13;
3847
    private static final int INFO_APP_INSTALL_FOLDER = 14;
3848
    private static final int INFO_APP_PLUGINS_FOLDER = 15;
3849
    private static final int INFO_APP_THEME = 16;
3850
    private static final int INFO_APP_SKIN = 17;
3851
    private static final int INFO_PACKAGES = 18;
3852
    private static final int INFO_TEMP_FOLDER = 19;
3853
    
3854
    public static String getInformation(PackageInfo[] pkgs) {
3855

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

    
3882
        String values[] = new String[INFO_TEMP_FOLDER + 1];
3883

    
3884
        PluginsManager pluginmgr = PluginsLocator.getManager();
3885
        LocaleManager localemgr = PluginsLocator.getLocaleManager();
3886

    
3887
        Properties props = System.getProperties();
3888

    
3889
        // OS information
3890
        values[INFO_OS_NAME] = props.getProperty("os.name");
3891
        values[INFO_OS_ARCH] = props.getProperty("os.arch");
3892
        values[INFO_OS_VERSION] = props.getProperty("os.version");
3893

    
3894
        if (values[INFO_OS_NAME].startsWith("Linux")) {
3895
            try {
3896
                StringWriter writer = new StringWriter();
3897

    
3898
                String[] command = {"lsb_release", "-a"};
3899
                Process p = Runtime.getRuntime().exec(command);
3900
                InputStream is = p.getInputStream();
3901
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
3902
                String line;
3903
                while ((line = reader.readLine()) != null) {
3904
                    writer.write("    " + line + "\n");
3905
                }
3906
                values[INFO_OS_ADITIONAL] = writer.toString();
3907
            } catch (Exception ex) {
3908
                logger.warn("Can't get detailled os information (lsb_release -a).", ex);
3909
            }
3910
        }
3911

    
3912
        values[INFO_JRE_VENDOR] = props.getProperty("java.vendor");
3913
        values[INFO_JRE_VERSION] = props.getProperty("java.version");
3914
        values[INFO_JRE_HOME] = props.getProperty("java.home");
3915
        values[INFO_PROXY_HOST] = props.getProperty("http.proxyHost");
3916
        values[INFO_PROXY_PORT] = props.getProperty("http.proxyPort");
3917
        values[INFO_PROXY_USER] = props.getProperty("http.proxyUserName");
3918

    
3919
        if (props.get("http.proxyPassword") == null) {
3920
            values[INFO_PROXY_PASSWORD] = "(null)";
3921
        } else {
3922
            values[INFO_PROXY_PASSWORD] = "***********";
3923
        }
3924

    
3925
        try {
3926
            values[INFO_APP_SKIN] = MDIManagerFactory.getSkinExtension().getClassName();
3927
        } catch (Throwable e) {
3928
            values[INFO_APP_SKIN] = "(unknow)";
3929
        }
3930
        values[INFO_TEMP_FOLDER] = ToolsLocator.getFoldersManager().getTemporaryFolder().getAbsolutePath();
3931
        values[INFO_APP_LOCALE] = localemgr.getCurrentLocale().toString();
3932
        values[INFO_APP_FOLDER] = pluginmgr.getApplicationFolder().getAbsolutePath();
3933
        values[INFO_APP_HOME] = pluginmgr.getApplicationHomeFolder().getAbsolutePath();
3934
        values[INFO_APP_INSTALL_FOLDER] = pluginmgr.getInstallFolder().getAbsolutePath();
3935
        values[INFO_APP_PLUGINS_FOLDER] = StringUtils.join(pluginmgr.getPluginsFolders());
3936
        values[INFO_APP_THEME] = Launcher.theme.getSource().getAbsolutePath();
3937

    
3938
        try {
3939
            if (pkgs == null) {
3940
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
3941
                pkgs = installmgr.getInstalledPackages();
3942
            }
3943
            StringWriter writer = new StringWriter();
3944
            for (PackageInfo pkg : pkgs) {
3945
                writer.write("    ");
3946
                writer.write(pkg.toStringCompact());
3947
                writer.write("\n");
3948
            }
3949
            values[INFO_PACKAGES] = writer.toString();
3950

    
3951
        } catch (Throwable e) {
3952
            logger.warn("Can't get installed package information.", e);
3953
        }
3954

    
3955
        String s = MessageFormat.format(template, (Object[])values);
3956
        return s;
3957
    }
3958

    
3959
    private void logger_info(String msg) {
3960
        String info[] = msg.split("\n");
3961
        for (String info1 : info) {
3962
            logger.info(info1);
3963
        }
3964
    }
3965

    
3966
    private void saveEnvironInformation(PackageInfo[] pkgs) {
3967
        PluginsManager manager = PluginsLocator.getManager();
3968
        File fout = new File(manager.getApplicationHomeFolder(), "gvSIG-environ.info");
3969
        try {
3970
            FileUtils.write(fout, getInformation(pkgs));
3971
        } catch (IOException e) {
3972
            logger.info("Can't create '" + fout.getAbsolutePath() + "'");
3973
        }
3974
    }
3975

    
3976
    private void fixIncompatiblePlugins(PackageInfo[] installedPackages) {
3977
        final Set<String> incompatiblePlugins = new HashSet<String>();
3978

    
3979
        // Add installed packages to a Map to optimize searchs
3980
        final Map<String, PackageInfo> packages = new HashMap<String, PackageInfo>();
3981
        for (int i = 0; i < installedPackages.length; i++) {
3982
            packages.put(installedPackages[i].getCode(), installedPackages[i]);
3983
        }
3984
        Iterator<Entry<String, PluginConfig>> it = pluginsConfig.entrySet().iterator();
3985
        while (it.hasNext()) {
3986
            List<String> pluginNames = new ArrayList<String>();
3987
            Entry<String, PluginConfig> entry = it.next();
3988
            PluginConfig pluginConfig = entry.getValue();
3989
            pluginNames.add(entry.getKey());
3990

    
3991
                        // Locate the package for this plugin.
3992
            // Be care whith alias
3993
            String[] aliases = pluginsConfig.getAliases(pluginConfig);
3994
            if (aliases != null) {
3995
                for (int i = 0; i < aliases.length; i++) {
3996
                    pluginNames.add(aliases[i]);
3997
                }
3998
            }
3999
            PackageInfo pkg = null;
4000
            for (int n = 0; n < pluginNames.size(); n++) {
4001
                pkg = packages.get(pluginNames.get(n));
4002
                if (pkg != null) {
4003
                    break;
4004
                }
4005
            }
4006

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

    
4041
        Iterator<String> it2 = pluginsToDissable.iterator();
4042
        while (it2.hasNext()) {
4043
            String pluginName = it2.next();
4044
            logger.info("Dissabling plugin '" + pluginName + "' by user action.");
4045
            pluginsConfig.remove(pluginName);
4046
        }
4047
    }
4048

    
4049
    private class DisablePluginsConflictingDialog extends JDialog {
4050

    
4051
        public static final int CONTINUE = 0;
4052
        public static final int CLOSE = 1;
4053

    
4054
        private DisablePluginsConflictingLayoutPanel contents;
4055
        private int action = 0;
4056
        private List<Item> incompatiblePlugins = null;
4057
        private Map<String, PackageInfo> packages;
4058

    
4059
        private class Item {
4060

    
4061
            private String code;
4062
            private PackageInfo pkg;
4063

    
4064
            public Item(String code, PackageInfo pkg) {
4065
                this.code = code;
4066
                this.pkg = pkg;
4067
            }
4068

    
4069
            public String toString() {
4070
                if (this.pkg == null) {
4071
                    return code;
4072
                }
4073
                return this.pkg.getName() + " (" + this.pkg.getCode() + ")";
4074
            }
4075

    
4076
            public String getCode() {
4077
                if (pkg == null) {
4078
                    return code;
4079
                }
4080
                return pkg.getCode();
4081
            }
4082
        }
4083

    
4084
        DisablePluginsConflictingDialog(Map<String, PackageInfo> packages, Set<String> incompatiblePlugins) {
4085
            super((Frame) null, "", true);
4086
            this.setTitle(translate("_Conflicting_plugins"));
4087

    
4088
            this.packages = packages;
4089

    
4090
            this.incompatiblePlugins = new ArrayList<Item>();
4091
            Item item = null;
4092
            Iterator<String> it = incompatiblePlugins.iterator();
4093
            while (it.hasNext()) {
4094
                String code = it.next();
4095
                item = new Item(code, packages.get(code));
4096
                this.incompatiblePlugins.add(item);
4097
                logger.info("Found plugin '" + item.getCode() + "' incopatibles with each other.");
4098
            }
4099
            initComponents();
4100
        }
4101

    
4102
        private void initComponents() {
4103
            this.contents = new DisablePluginsConflictingLayoutPanel();
4104

    
4105
            doTranslations();
4106

    
4107
            this.contents.buttonClose.addActionListener(new ActionListener() {
4108
                public void actionPerformed(ActionEvent arg0) {
4109
                    doClose();
4110
                }
4111
            });
4112
            this.contents.buttonContinue.addActionListener(new ActionListener() {
4113
                public void actionPerformed(ActionEvent arg0) {
4114
                    doContinue();
4115
                }
4116
            });
4117
            this.contents.pluginList.setModel(new DefaultListModel(this.incompatiblePlugins));
4118
            ListSelectionModel sm = this.contents.pluginList.getSelectionModel();
4119
            sm.setSelectionMode(sm.MULTIPLE_INTERVAL_SELECTION);
4120
            this.setContentPane(this.contents);
4121
            this.pack();
4122

    
4123
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
4124
            setLocation((screenSize.width / 2) - (this.getWidth() / 2),
4125
                    (screenSize.height / 2) - (this.getHeight() / 2));
4126
        }
4127

    
4128
        private void doTranslations() {
4129
            DisablePluginsConflictingLayoutPanel c = this.contents;
4130
            c.lblConflict.setText(translate("_Some_of_plugins_installed_conflict_with_each_other"));
4131
            c.lblSelectPluginToDisable.setText(translate("_Select_the_plugins_that_you_want_to_disable_and_click_the_continue_button"));
4132
            c.lblClickContinue.setText(translate("_You_can_click_on_continue_button_directly_if_you_dont_want_to_disable_any_plugins"));
4133
            c.lblClickClose.setText(translate("_Or_click_the_close_button_to_close_the_application"));
4134
            c.buttonClose.setText(translate("_Close"));
4135
            c.buttonContinue.setText(translate("_Continue"));
4136
        }
4137

    
4138
        private String translate(String msg) {
4139
            return PluginServices.getText(this, msg);
4140
        }
4141

    
4142
        private void doClose() {
4143
            this.action = CLOSE;
4144
            this.setVisible(false);
4145
        }
4146

    
4147
        private void doContinue() {
4148
            this.action = CONTINUE;
4149
            this.setVisible(false);
4150
        }
4151

    
4152
        public int getAction() {
4153
            return this.action;
4154
        }
4155

    
4156
        public List<String> getPluginNamesToDisable() {
4157
            if (this.action == CLOSE) {
4158
                return null;
4159
            }
4160
            Object[] selecteds = null;
4161
            selecteds = (Object[]) this.contents.pluginList.getSelectedValues();
4162
            if (selecteds == null || selecteds.length < 1) {
4163
                return null;
4164
            }
4165
            List<String> values = new ArrayList<String>();
4166
            for (int i = 0; i < selecteds.length; i++) {
4167
                values.add(((Item) selecteds[i]).getCode());
4168
            }
4169
            return values;
4170
        }
4171
    }
4172

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

    
4217
            if (identityManagementInitializerClassName != null) {
4218
                Class identityManagerInitializerClass = plugin.getClassLoader().loadClass(identityManagementInitializerClassName);
4219
                Runnable identityManagerInitializer = (Runnable) identityManagerInitializerClass.newInstance();
4220
                identityManagerInitializer.run();
4221
            } else {
4222
                logger.info("Entry IdentityManagementInitializer not found in identity management config file '" + identityManagementConfigFile.getAbsolutePath() + "'.");
4223
            }
4224

    
4225
        } catch (Exception ex) {
4226
            logger.warn("Can't initialize the identity manager from '" + identityManagementConfigFile.getAbsolutePath() + ".", ex);
4227
            return;
4228
        }
4229
        logger.info("Loaded an identity manager from plugin '" + plugin.getPluginName() + ".");
4230
    }
4231

    
4232
}