Statistics
| Revision:

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

History | View | Annotate | Download (165 KB)

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

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

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

    
91

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

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

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

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

    
206
    private static Arguments arguments;
207

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

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

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

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

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

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

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

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

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

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

    
301
            return item;
302
        }
303

    
304
    }
305

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

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

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

    
325
    }
326

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

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

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

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

    
355
    protected static ListBaseException launcherrors = null;
356

    
357
    protected static Theme theme = null;
358

    
359
    private List<String> deprecatedPluginNames = null;
360

    
361
    private static final class ProxyAuth extends Authenticator {
362

    
363
        private PasswordAuthentication auth;
364

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

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

    
374
    private static Launcher launcherInstance;
375

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

    
383
    public static void main(String[] args) throws Exception {
384
        arguments = new DefaultArguments(args);
385

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

    
399
    protected void downloadExtensions(String extDir) {
400
        // do nothing
401
    }
402

    
403
    public static class LaunchException extends ListBaseException {
404

    
405
        private static final long serialVersionUID = 4541192746962684705L;
406

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

    
413
    }
414

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

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

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

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

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

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

    
462
        initializeApp(args, null);
463

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
696
        splashWindow.close();
697

    
698
        frame.setCursor(Cursor.DEFAULT_CURSOR);
699

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

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

    
711
    }
712

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

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

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

    
742
    }
743

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

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

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

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

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

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

    
814
        ToolsLocator.registerDefaultToolsLibraries();
815

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

    
824
        configureLocales();
825

    
826
        logger.info("Configure LookAndFeel");
827
        configureLookAndFeel();
828
    }
829

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

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

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

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

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

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

    
908
    private class NotificationAppender extends AppenderSkeleton {
909

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

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

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

    
934
        }
935

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

    
942
    }
943

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

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

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

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

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

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

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

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

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

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

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

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

    
1082
        System.getProperties().put("http.proxyHost", host);
1083
        System.getProperties().put("http.proxyPort", port);
1084

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

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

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

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

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

    
1170
    private void loadPluginsPersistence() throws ConfigurationException {
1171
        XMLEntity entity = persistenceFromXML();
1172

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

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

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

    
1200
        XMLEntity entity = new XMLEntity();
1201

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

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

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

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

    
1236
            LabelSet[] ls = pc.getLabelSet();
1237

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

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

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

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

    
1273
        Class<? extends IExtension> skinClass;
1274

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

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

    
1304
    }
1305

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

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

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

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

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

    
1367
    }
1368

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

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

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

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

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

    
1399
    private void initializeExtensions() {
1400

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

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

    
1430
            Extension[] exts = pc.getExtensions().getExtension();
1431

    
1432
            TreeSet<Extension> orderedExtensions = new TreeSet<Extension>(
1433
                    new ExtensionComparator());
1434

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

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

    
1445
                orderedExtensions.add(exts[j]);
1446
            }
1447

    
1448
            Iterator<Extension> e = orderedExtensions.iterator();
1449

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

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

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

    
1487
                    extensionInstance.initialize();
1488
                    extensions.add(extensionInstance);
1489

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

    
1501
    private void postInitializeExtensions() {
1502
        logger.info("PostInitializing extensions: ");
1503

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

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

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

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

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

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

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

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

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

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

    
1644
            logger.info("registerActions of plugin '" + pluginName + "'.");
1645

    
1646
            Extensions extensionConfig = pluginConfig.getExtensions();
1647

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

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

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

    
1681
        }
1682
    }
1683

    
1684
    private TreeSet<SortableMenu> getOrderedMenus() {
1685

    
1686
        TreeSet<SortableMenu> orderedMenus = new TreeSet<SortableMenu>(
1687
                new MenuComparator());
1688

    
1689
        Iterator<String> i = pluginsConfig.keySet().iterator();
1690

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

    
1697
                Extension[] exts = pc.getExtensions().getExtension();
1698

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

    
1704
                    Menu[] menus = exts[j].getMenu();
1705

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

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

    
1719
                        orderedMenus.add(sm);
1720
                    }
1721
                }
1722

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

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

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

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

    
1742
                            orderedMenus.add(sm);
1743
                        }
1744
                    }
1745
                }
1746

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

    
1752
        }
1753

    
1754
        return orderedMenus;
1755
    }
1756

    
1757
    private void installPluginsMenus() {
1758
        logger.info("installPluginsMenus");
1759

    
1760
        TreeSet<SortableMenu> orderedMenus = getOrderedMenus();
1761

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

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

    
1780
    public class PluginMenuItem {
1781

    
1782
        private Menu menu;
1783
        private PluginClassLoader loader;
1784
        private SkinExtensionType extension;
1785

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

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

    
1798
        public String getExtensionName() {
1799
            return this.extension.getClassName();
1800
        }
1801

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

    
1812
        public String getText() {
1813
            return this.menu.getText();
1814
        }
1815

    
1816
        public long getPosition() {
1817
            return this.menu.getPosition();
1818
        }
1819

    
1820
        public String getName() {
1821
            return this.menu.getName();
1822
        }
1823

    
1824
        public boolean isParent() {
1825
            return menu.getIs_separator();
1826
        }
1827

    
1828
        public String getPluginName() {
1829
            return this.loader.getPluginName();
1830
        }
1831

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

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

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

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

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

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

    
1903
        Iterator<String> pluginNames = pluginsConfig.keySet().iterator();
1904

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

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

    
1920
                Extension[] exts = pc.getExtensions().getExtension();
1921

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

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

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

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

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

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

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

    
1984
                    SelectableTool[] sTools = toolbars[k].getSelectableTool();
1985

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

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

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

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

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

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

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

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

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

    
2119
                            SelectableTool[] sTools = toolbars[k]
2120
                                    .getSelectableTool();
2121

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

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

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

    
2183
        Plugin[] plugins = andamiConfig.getPlugin();
2184

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

    
2189
        Iterator<PluginServices> i = pluginsServices.values().iterator();
2190

    
2191
        while (i.hasNext()) {
2192
            PluginServices ps = i.next();
2193

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

    
2199
                andamiConfig.addPlugin(p);
2200
            }
2201
        }
2202
    }
2203

    
2204
    private URL[] getPluginClasspathURLs(PluginConfig pluginConfig) {
2205
        URL[] urls = null;
2206

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

    
2210
        File[] files = libFolderFile.listFiles(new FileFilter() {
2211

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

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

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

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

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

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

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

    
2422
    static String getPluginsDir() {
2423
        return andamiConfig.getPluginsDirectory();
2424
    }
2425

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

    
2430
    static void setPluginsDir(String s) {
2431
        andamiConfig.setPluginsDirectory(s);
2432
    }
2433

    
2434
    static MDIFrame getMDIFrame() {
2435
        return frame;
2436
    }
2437

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

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

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

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

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

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

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

    
2490
                }
2491
            }
2492
        }
2493
        return pluginsConfig;
2494
    }
2495

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

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

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

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

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

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

    
2577
    private static AndamiConfig getDefaultAndamiConfig() {
2578
        AndamiConfig andamiConfig = new AndamiConfig();
2579

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

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

    
2598
        andamiConfig.setPlugin(new Plugin[0]);
2599
        return andamiConfig;
2600
    }
2601

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

    
2605
        if (xml.exists()) {
2606
            InputStreamReader reader = null;
2607

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

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

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

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

    
2672
    }
2673

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

    
2681
        File xml = getPluginsPersistenceFile(false);
2682
        OutputStreamWriter writer = null;
2683

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

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

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

    
2722
    static MDIFrame getFrame() {
2723
        return frame;
2724
    }
2725

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

    
2736
    static HashMap getClassesExtensions() {
2737
        return classesExtensions;
2738
    }
2739

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

    
2761
        while (iter.hasNext()) {
2762
            array.add(iter.next().getExtensions());
2763
        }
2764

    
2765
        return array.toArray(new Extensions[array.size()]);
2766
    }
2767

    
2768
    public static Iterator getExtensionIterator() {
2769
        return extensions.iterator();
2770
    }
2771

    
2772
    public static HashMap getPluginConfig() {
2773
        return pluginsConfig;
2774
    }
2775

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

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

    
2787
        return null;
2788
    }
2789

    
2790
    public static AndamiConfig getAndamiConfig() {
2791
        return andamiConfig;
2792
    }
2793

    
2794
    private static class ExtensionComparator implements Comparator {
2795

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

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

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

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

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

    
2820
    private static class MenuComparator implements Comparator<SortableMenu> {
2821

    
2822
        private static ExtensionComparator extComp = new ExtensionComparator();
2823

    
2824
        public int compare(SortableMenu e1, SortableMenu e2) {
2825

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

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

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

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

    
2854
        }
2855
    }
2856

    
2857
    private static class SortableMenu {
2858

    
2859
        public PluginClassLoader loader;
2860
        public Menu menu;
2861
        public SkinExtensionType extension;
2862

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

    
2870
    }
2871

    
2872
    private static class SortableTool {
2873

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

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

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

    
2899
    private static class ToolBarComparator implements Comparator<SortableTool> {
2900

    
2901
        private static ExtensionComparator extComp = new ExtensionComparator();
2902

    
2903
        public int compare(SortableTool e1, SortableTool e2) {
2904

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

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

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

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

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

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

    
2965
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2966

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

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

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

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

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

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

    
3025
        return UIManager.getSystemLookAndFeelClassName();
3026
    }
3027

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

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

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

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

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

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

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

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

    
3205
    public static File getApplicationHomeFolder() {
3206
        return new File(getAppHomeDir());
3207
    }
3208

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

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

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

    
3259
        logger
3260
                .error(Messages
3261
                        .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
3262
                        + " '" + name + "'");
3263
    }
3264

    
3265
    public static void initIconThemes() {
3266
        PluginsManager pluginsManager = PluginsLocator.getManager();
3267
        IconThemeManager iconManager = ToolsSwingLocator.getIconThemeManager();
3268

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

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

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

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

    
3304
        panel.addActionListener(panel.new UnsavedDataPanelListener() {
3305

    
3306
            public void cancel(UnsavedDataPanel panel) {
3307
                panel.setVisible(false);
3308
            }
3309

    
3310
            public void discard(UnsavedDataPanel panel) {
3311
                panel.setVisible(false);
3312
            }
3313

    
3314
            public void accept(UnsavedDataPanel panel) {
3315
                panel.setVisible(false);
3316

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

    
3335
        //TODO: mostrar panel WindowManager
3336
        ToolsSwingLocator.getWindowManager().showWindow(
3337
                panel,
3338
                PluginServices.getText(panel, "Resource_was_not_saved"),
3339
                MODE.DIALOG);
3340

    
3341
    }
3342

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

    
3350
        private boolean proceed = false;
3351
        private UnsavedDataPanel panel = null;
3352

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

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

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

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

    
3397
            // Finalize all the extensions
3398
            finalizeExtensions();
3399

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

    
3410
            logger.info("Quiting application.");
3411

    
3412
            // Para la depuraci?n de memory leaks
3413
            System.gc();
3414

    
3415
            System.exit(0);
3416
        }
3417

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

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

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

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

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

    
3516
        public UnsavedDataPanel getUnsavedDataPanel() {
3517
            if (panel == null) {
3518
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
3519
            }
3520
            return panel;
3521
        }
3522

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

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

    
3543
            UnsavedDataPanel panel = getUnsavedDataPanel();
3544
            panel.setUnsavedDataArray(unsavedData);
3545

    
3546
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
3547

    
3548
                public void cancel(UnsavedDataPanel panel) {
3549
                    proceed(false);
3550
                    PluginServices.getMDIManager().closeWindow(panel);
3551

    
3552
                }
3553

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

    
3558
                }
3559

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

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

    
3605
            PluginServices.getMDIManager().addWindow(panel);
3606
            if (proceed) {
3607
                return JOptionPane.YES_OPTION;
3608
            } else {
3609
                return JOptionPane.NO_OPTION;
3610
            }
3611
        }
3612

    
3613
        private void proceed(boolean proceed) {
3614
            this.proceed = proceed;
3615
        }
3616

    
3617
    }
3618

    
3619
    public static TerminationProcess getTerminationProcess() {
3620
        return (new Launcher()).new TerminationProcess();
3621
    }
3622

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

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

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

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

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

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

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

    
3708
            if (line.hasOption("installURLFile")) {
3709
                installURLFile = line.getOptionValue("installURLFile");
3710
            } else {
3711
                installURLFile = "gvsig-installer-urls.config";
3712
            }
3713

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

    
3730
        initializeApp(myArgs, "installer");
3731

    
3732
        new DefaultLibrariesInitializer().fullInitialize(true);
3733

    
3734
        initializeInstallerManager();
3735

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

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

    
3752
        AndamiConfig config = getAndamiConfig();
3753

    
3754
        initializeIdentityManagement(new File(config.getPluginsDirectory()).getAbsoluteFile());
3755

    
3756
        initializeLibraries();
3757

    
3758
        packageInfo = getPackageInfo(myArgs[1]);
3759

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

    
3778
        SwingInstallerLocator.getSwingInstallerManager().setDefaultDownloadURL(new File(installURLFile));
3779

    
3780
        // Launch installer
3781
        PluginsManager manager = PluginsLocator.getManager();
3782

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

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

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

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

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

    
3829
        frame.setVisible(true);
3830
    }
3831

    
3832
    public static String getInformation() {
3833
        return getInformation(null);
3834
    }
3835

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

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

    
3885
        String values[] = new String[INFO_TEMP_FOLDER + 1];
3886

    
3887
        PluginsManager pluginmgr = PluginsLocator.getManager();
3888
        LocaleManager localemgr = PluginsLocator.getLocaleManager();
3889

    
3890
        Properties props = System.getProperties();
3891

    
3892
        // OS information
3893
        values[INFO_OS_NAME] = props.getProperty("os.name");
3894
        values[INFO_OS_ARCH] = props.getProperty("os.arch");
3895
        values[INFO_OS_VERSION] = props.getProperty("os.version");
3896

    
3897
        if (values[INFO_OS_NAME].startsWith("Linux")) {
3898
            try {
3899
                StringWriter writer = new StringWriter();
3900

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

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

    
3922
        if (props.get("http.proxyPassword") == null) {
3923
            values[INFO_PROXY_PASSWORD] = "(null)";
3924
        } else {
3925
            values[INFO_PROXY_PASSWORD] = "***********";
3926
        }
3927

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

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

    
3954
        } catch (Throwable e) {
3955
            logger.warn("Can't get installed package information.", e);
3956
        }
3957

    
3958
        String s = MessageFormat.format(template, (Object[])values);
3959
        return s;
3960
    }
3961

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

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

    
3979
    private void fixIncompatiblePlugins(PackageInfo[] installedPackages) {
3980
        final Set<String> incompatiblePlugins = new HashSet<String>();
3981

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

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

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

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

    
4052
    private class DisablePluginsConflictingDialog extends JDialog {
4053

    
4054
        public static final int CONTINUE = 0;
4055
        public static final int CLOSE = 1;
4056

    
4057
        private DisablePluginsConflictingLayoutPanel contents;
4058
        private int action = 0;
4059
        private List<Item> incompatiblePlugins = null;
4060
        private Map<String, PackageInfo> packages;
4061

    
4062
        private class Item {
4063

    
4064
            private String code;
4065
            private PackageInfo pkg;
4066

    
4067
            public Item(String code, PackageInfo pkg) {
4068
                this.code = code;
4069
                this.pkg = pkg;
4070
            }
4071

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

    
4079
            public String getCode() {
4080
                if (pkg == null) {
4081
                    return code;
4082
                }
4083
                return pkg.getCode();
4084
            }
4085
        }
4086

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

    
4091
            this.packages = packages;
4092

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

    
4105
        private void initComponents() {
4106
            this.contents = new DisablePluginsConflictingLayoutPanel();
4107

    
4108
            doTranslations();
4109

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

    
4126
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
4127
            setLocation((screenSize.width / 2) - (this.getWidth() / 2),
4128
                    (screenSize.height / 2) - (this.getHeight() / 2));
4129
        }
4130

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

    
4141
        private String translate(String msg) {
4142
            return PluginServices.getText(this, msg);
4143
        }
4144

    
4145
        private void doClose() {
4146
            this.action = CLOSE;
4147
            this.setVisible(false);
4148
        }
4149

    
4150
        private void doContinue() {
4151
            this.action = CONTINUE;
4152
            this.setVisible(false);
4153
        }
4154

    
4155
        public int getAction() {
4156
            return this.action;
4157
        }
4158

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

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

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

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

    
4235
}