Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2040 / frameworks / _fwAndami / src / org / gvsig / andami / Launcher.java @ 37231

History | View | Annotate | Download (109 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004-2007 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.andami;
42

    
43
import java.awt.BorderLayout;
44
import java.awt.Component;
45
import java.awt.Dimension;
46
import java.awt.EventQueue;
47
import java.awt.Frame;
48
import java.awt.KeyboardFocusManager;
49
import java.awt.Point;
50
import java.awt.Toolkit;
51
import java.io.BufferedOutputStream;
52
import java.io.BufferedReader;
53
import java.io.File;
54
import java.io.FileFilter;
55
import java.io.FileInputStream;
56
import java.io.FileNotFoundException;
57
import java.io.FileOutputStream;
58
import java.io.FileReader;
59
import java.io.IOException;
60
import java.io.InputStream;
61
import java.io.InputStreamReader;
62
import java.io.OutputStreamWriter;
63
import java.io.Reader;
64
import java.io.StringWriter;
65
import java.net.Authenticator;
66
import java.net.MalformedURLException;
67
import java.net.PasswordAuthentication;
68
import java.net.URL;
69
import java.nio.channels.FileChannel;
70
import java.security.AllPermission;
71
import java.security.CodeSource;
72
import java.security.PermissionCollection;
73
import java.security.Permissions;
74
import java.security.Policy;
75
import java.text.MessageFormat;
76
import java.util.ArrayList;
77
import java.util.Comparator;
78
import java.util.HashMap;
79
import java.util.HashSet;
80
import java.util.Iterator;
81
import java.util.List;
82
import java.util.Locale;
83
import java.util.Map;
84
import java.util.Properties;
85
import java.util.Set;
86
import java.util.TreeSet;
87
import java.util.prefs.Preferences;
88

    
89
import javax.swing.ImageIcon;
90
import javax.swing.JButton;
91
import javax.swing.JComponent;
92
import javax.swing.JFrame;
93
import javax.swing.JOptionPane;
94
import javax.swing.JPopupMenu;
95
import javax.swing.SwingUtilities;
96
import javax.swing.UIManager;
97

    
98
import org.apache.log4j.AppenderSkeleton;
99
import org.apache.log4j.PatternLayout;
100
import org.apache.log4j.PropertyConfigurator;
101
import org.apache.log4j.RollingFileAppender;
102
import org.apache.log4j.spi.LoggingEvent;
103
import org.exolab.castor.xml.MarshalException;
104
import org.exolab.castor.xml.ValidationException;
105
import org.gvsig.andami.authentication.IAuthentication;
106
import org.gvsig.andami.authentication.LoginUI;
107
import org.gvsig.andami.config.generate.Andami;
108
import org.gvsig.andami.config.generate.AndamiConfig;
109
import org.gvsig.andami.config.generate.Plugin;
110
import org.gvsig.andami.iconthemes.IIconTheme;
111
import org.gvsig.andami.iconthemes.IconThemeManager;
112
import org.gvsig.andami.messages.Messages;
113
import org.gvsig.andami.messages.NotificationManager;
114
import org.gvsig.andami.plugins.ExclusiveUIExtension;
115
import org.gvsig.andami.plugins.ExtensionDecorator;
116
import org.gvsig.andami.plugins.IExtension;
117
import org.gvsig.andami.plugins.PluginClassLoader;
118
import org.gvsig.andami.plugins.config.generate.ActionTool;
119
import org.gvsig.andami.plugins.config.generate.ComboButton;
120
import org.gvsig.andami.plugins.config.generate.ComboButtonElement;
121
import org.gvsig.andami.plugins.config.generate.ComboScale;
122
import org.gvsig.andami.plugins.config.generate.Depends;
123
import org.gvsig.andami.plugins.config.generate.Extension;
124
import org.gvsig.andami.plugins.config.generate.Extensions;
125
import org.gvsig.andami.plugins.config.generate.LabelSet;
126
import org.gvsig.andami.plugins.config.generate.Menu;
127
import org.gvsig.andami.plugins.config.generate.PluginConfig;
128
import org.gvsig.andami.plugins.config.generate.PopupMenu;
129
import org.gvsig.andami.plugins.config.generate.PopupMenus;
130
import org.gvsig.andami.plugins.config.generate.SelectableTool;
131
import org.gvsig.andami.plugins.config.generate.SkinExtension;
132
import org.gvsig.andami.plugins.config.generate.SkinExtensionType;
133
import org.gvsig.andami.plugins.config.generate.ToolBar;
134
import org.gvsig.andami.plugins.status.IExtensionStatus;
135
import org.gvsig.andami.plugins.status.IUnsavedData;
136
import org.gvsig.andami.ui.AndamiEventQueue;
137
import org.gvsig.andami.ui.MDIManagerLoadException;
138
import org.gvsig.andami.ui.ToolsWindowManager;
139
import org.gvsig.andami.ui.fonts.FontUtils;
140
import org.gvsig.andami.ui.mdiFrame.MDIFrame;
141
import org.gvsig.andami.ui.mdiFrame.NewStatusBar;
142
import org.gvsig.andami.ui.mdiManager.MDIManagerFactory;
143
import org.gvsig.andami.ui.splash.MultiSplashWindow;
144
import org.gvsig.andami.ui.theme.Theme;
145
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
146
import org.gvsig.installer.lib.api.InstallerLocator;
147
import org.gvsig.installer.lib.api.InstallerManager;
148
import org.gvsig.installer.lib.api.PackageInfo;
149
import org.gvsig.installer.swing.api.SwingInstallerLocator;
150
import org.gvsig.installer.swing.api.execution.AbstractInstallPackageWizard;
151
import org.gvsig.installer.swing.api.wizard.InstallerWizardActionListener;
152
import org.gvsig.installer.swing.api.wizard.InstallerWizardPanel;
153
import org.gvsig.tools.exception.ListBaseException;
154
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
155
import org.gvsig.tools.swing.api.ToolsSwingLocator;
156
import org.gvsig.utils.DateTime;
157
import org.gvsig.utils.XMLEntity;
158
import org.gvsig.utils.xml.XMLEncodingUtils;
159
import org.gvsig.utils.xmlEntity.generate.XmlTag;
160
import org.slf4j.Logger;
161
import org.slf4j.LoggerFactory;
162

    
163
/**
164
 * <p>
165
 * Andami's launching class. This is the class used to create the Andami's
166
 * plugin environment.<br>
167
 * </p>
168
 * 
169
 * <p>
170
 * <b>Syntax:</b> <br>
171
 * java [-Xmx512M (for 512MB of RAM)] [-classpath={a colon-separated(unix) or
172
 * semicolon-separated(windows) list of files containg base library of classes}]
173
 * [-Djava.library.path=PATH_TO_NATIVE_LIBRARIES]
174
 * PATH_TO_APPLICATION_HOME_DIRECTORY PATH_TO_APPLICATION_PLUGINS_DIRECTORY
175
 * [{list of additional custom application arguments separated by spaces}]
176
 * </p>
177
 * 
178
 * 
179
 * @author $author$
180
 * @version $Revision: 37231 $
181
 */
182
public class Launcher {
183

    
184
    protected static Logger logger =
185
        LoggerFactory.getLogger(Launcher.class.getName());
186
    protected static Preferences prefs =
187
        Preferences.userRoot().node("gvsig.connection");
188
    protected static AndamiConfig andamiConfig;
189
    protected static MultiSplashWindow splashWindow;
190
    protected static String appName;
191
    protected static Locale locale;
192
    protected static HashMap<String, PluginConfig> pluginsConfig =
193
        new HashMap<String, PluginConfig>();
194
    protected static HashMap<String, PluginServices> pluginsServices =
195
        new HashMap<String, PluginServices>();
196
    protected static MDIFrame frame;
197
    protected static HashMap<Class<? extends IExtension>, ExtensionDecorator> classesExtensions =
198
        new HashMap<Class<? extends IExtension>, ExtensionDecorator>();
199
    protected static String andamiConfigPath;
200
    protected static final String nonWinDefaultLookAndFeel =
201
        "com.jgoodies.looks.plastic.PlasticXPLookAndFeel";
202

    
203
    protected static ArrayList<String> pluginsOrdered = new ArrayList<String>();
204
    protected static ArrayList<IExtension> extensions =
205
        new ArrayList<IExtension>();
206
    protected static String appHomeDir = null;
207
    // it seems castor uses this encoding
208
    protected static final String CASTORENCODING = "UTF8";
209

    
210
    protected static ListBaseException launcherrors = null;
211

    
212
    protected static Theme theme = null;
213

    
214
    private static final class ProxyAuth extends Authenticator {
215

    
216
        private PasswordAuthentication auth;
217

    
218
        private ProxyAuth(String user, String pass) {
219
            auth = new PasswordAuthentication(user, pass.toCharArray());
220
        }
221

    
222
        protected PasswordAuthentication getPasswordAuthentication() {
223
            return auth;
224
        }
225
    }
226

    
227
    public static void main(String[] args) throws Exception {
228
        Launcher launcher = new Launcher();
229
        boolean install = false;
230
        for (int i = 0; i < args.length; i++) {
231
            if (args[i].equalsIgnoreCase("--install")) {
232
                install = true;
233
            }
234
        }
235
        try {
236
            if (install) {
237
                launcher.doInstall(args);
238
            } else {
239
                launcher.doMain(args);
240
            }
241
        } catch (Exception e) {
242
            logger.error("excepci?n al arrancar", e);
243
            System.exit(-1);
244
        }
245
    }
246

    
247
    protected void downloadExtensions(String extDir) {
248
        // do nothing
249
    }
250

    
251
    public static class LaunchException extends ListBaseException {
252

    
253
        private static final long serialVersionUID = 4541192746962684705L;
254

    
255
        public LaunchException() {
256
            super("Errors in initialization of application.",
257
                "_errors_in_initialization_of_application", serialVersionUID);
258
        }
259

    
260
    }
261

    
262
    protected void addError(Throwable ex) {
263
        if (launcherrors == null) {
264
            launcherrors = new LaunchException();
265
        }
266
        launcherrors.add(ex);
267
    }
268

    
269
    protected void addError(String msg, Throwable cause) {
270
        logger.error(msg, cause);
271
        this.addError(new RuntimeException(msg, cause));
272
    }
273

    
274
    protected void addError(String msg) {
275
        this.addError(msg, null);
276
    }
277

    
278
    public void doMain(String[] args) throws Exception {
279

    
280
        if (args.length < 1) {
281
            System.err
282
                .println("Uso: Launcher appName plugins-directory [language=locale]");
283
        }
284

    
285
        initializeApp(args);
286

    
287
        // Solucionamos el problema de permisos que se produc?a con Java
288
        // Web Start con este c?digo.
289
        // System.setSecurityManager(null);
290
        Policy.setPolicy(new Policy() {
291

    
292
            public PermissionCollection getPermissions(CodeSource codesource) {
293
                Permissions perms = new Permissions();
294
                perms.add(new AllPermission());
295
                return (perms);
296
            }
297

    
298
            public void refresh() {
299
            }
300
        });
301

    
302
        try {
303
            initIconThemes();
304
        } catch (Exception ex) {
305
            this.addError("Can't initialize icon theme", ex);
306
        }
307
        // Registramos los iconos base
308
        try {
309
            registerIcons();
310
        } catch (Exception ex) {
311
            this.addError("Can't register icons", ex);
312
        }
313
        validate();
314

    
315
        // Obtener la personalizaci?n de la aplicaci?n.
316
        try {
317
                logger.info("Initialize andami theme");
318
            theme = getTheme(andamiConfig.getPluginsDirectory());
319
        } catch (Exception ex) {
320
            this.addError("Can't get personalized theme for the application",
321
                ex);
322
        }
323

    
324
        // Mostrar la ventana de inicio
325
        Frame f = new Frame();
326
        splashWindow = new MultiSplashWindow(f, theme, 190);
327

    
328
        // 1. Ponemos los datos del proxy
329
        splashWindow.process(10, PluginServices.getText(Launcher.class,
330
            "SplashWindow.configuring_proxy"));
331
        logger.info("Configute http proxy");
332
        configureProxy();
333
        
334
        // 2. TODO Buscar actualizaciones de los plugins
335
        splashWindow.process(20, PluginServices.getText(Launcher.class,
336
            "SplashWindow.looking_for_updates"));
337
        try {
338
            this.downloadExtensions(andamiConfig.getPluginsDirectory());
339
        } catch (Exception ex) {
340
            this.addError("Can't downloads plugins", ex);
341
        }
342

    
343
        // 3. Se leen los config.xml de los plugins -----++++
344
        splashWindow.process(30, PluginServices.getText(Launcher.class,
345
            "SplashWindow.reading_plugins_config.xml"));
346
        try {
347
                logger.info("Load plugins information");
348
            this.loadPlugins(andamiConfig.getPluginsDirectory());
349
        } catch (Exception ex) {
350
            this.addError("Can't load plugins", ex);
351
        }
352

    
353
        // 4. Se configura el classloader del plugin
354
        splashWindow.process(40, PluginServices.getText(Launcher.class,
355
            "SplashWindow.setting_up_class_loaders"));
356
        try {
357
                logger.info("Configure plugins class loader");
358
            this.pluginsClassLoaders();
359
        } catch (Exception ex) {
360
            this.addError("Can't initialize plugin's classloaders  ", ex);
361
        }
362

    
363
        // 5. Initialize libraries
364
        splashWindow.process(50, PluginServices.getText(Launcher.class,
365
            "SplashWindow.initialize_libraries"));
366
        initializeLibraries();
367

    
368
        // 6. Se carga un Skin si alguno ide los plugins trae informaci?n
369
        // para ello
370
        splashWindow.process(60, PluginServices.getText(Launcher.class,
371
            "SplashWindow.looking_for_a_skin"));
372
        // skinPlugin( "com.iver.core.mdiManager.NewSkin");
373
        logger.info("Initialize skin");
374
        skinPlugin(null);
375

    
376
        logger.info("Dump system information");
377
        logger_info(getInformation());
378
        
379
        // 7. Se configura la cola de eventos
380
        splashWindow.process(70,
381
            PluginServices.getText(Launcher.class,
382
            "setting_up_event_queue"));
383
        EventQueue waitQueue = new AndamiEventQueue();
384
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue);
385

    
386
        // 8. Se configura la mensajer?a del plugin
387
        splashWindow.process(80, PluginServices.getText(Launcher.class,
388
            "SplashWindow.starting_plugin_internationalization_system"));
389
        pluginsMessages();
390

    
391
        // 9. Se modifica el andami-config con los plugins nuevos
392
        splashWindow.process(90, PluginServices.getText(Launcher.class,
393
            "SplashWindow.looking_for_a_skin"));
394
        updateAndamiConfig();
395

    
396
        frame = new MDIFrame();
397
        // 10. Se configura el nombre e icono de la aplicaci?n
398
        splashWindow.process(100, PluginServices.getText(Launcher.class,
399
            "SplashWindow.setting_up_applications_name_and_icons"));
400
        frameIcon(theme);
401

    
402
        // 11. Se prepara el MainFrame para albergar las extensiones
403
        splashWindow.process(110, PluginServices.getText(Launcher.class,
404
            "SplashWindow.preparing_workbench"));
405
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
406

    
407
        SwingUtilities.invokeAndWait(new Runnable() {
408

    
409
            public void run() {
410
                frame.init();
411
            }
412
        });
413
        ToolsSwingLocator.registerWindowManager(ToolsWindowManager.class);
414

    
415
        // 12. Leer el fichero de persistencia
416
        // info de los plugins
417
        // bookmarks de los plugins
418
        splashWindow.process(120, PluginServices.getText(Launcher.class,
419
            "SplashWindow.loading_plugin_settings"));
420
        loadPluginsPersistence();
421

    
422
        // Se instalan los controles del skin
423
        // 13. Se inicializan todas las extensiones de todos los plugins
424
        splashWindow.process(130, PluginServices.getText(Launcher.class,
425
            "SplashWindow.initializing_extensions"));
426
        SwingUtilities.invokeAndWait(new Runnable() {
427

    
428
            public void run() {
429
                initializeExtensions();
430
            }
431
        });
432

    
433
        // 14. Se inicializan la extensi?n exclusiva
434
        splashWindow.process(140, PluginServices.getText(Launcher.class,
435
            "SplashWindow.setting_up_master_extension"));
436
        SwingUtilities.invokeAndWait(new Runnable() {
437

    
438
            public void run() {
439
                initializeExclusiveUIExtension();
440
            }
441
        });
442
        frame.setClassesExtensions(classesExtensions);
443

    
444
        // 15. Se instalan los controles de las extensiones de los plugins
445
        splashWindow.process(150, PluginServices.getText(Launcher.class,
446
            "SplashWindow.installing_extensions_controls"));
447
        SwingUtilities.invokeAndWait(new Runnable() {
448

    
449
            public void run() {
450
                installPluginsControls();
451

    
452
            }
453
        });
454

    
455
        // 16. Se instalan los menus de las extensiones de los plugins
456
        splashWindow.process(160, PluginServices.getText(Launcher.class,
457
            "SplashWindow.installing_extensions_menus"));
458
        SwingUtilities.invokeAndWait(new Runnable() {
459

    
460
            public void run() {
461
                installPluginsMenus();
462

    
463
            }
464
        });
465

    
466
        // 17. Se instalan las etiquetas de las extensiones de los plugins
467
        splashWindow.process(170, PluginServices.getText(Launcher.class,
468
            "SplashWindow.installing_extensions_labels"));
469
        SwingUtilities.invokeAndWait(new Runnable() {
470

    
471
            public void run() {
472
                installPluginsLabels();
473

    
474
            }
475
        });
476

    
477
        // 18. Se instalan los bookmarks de los plugins
478

    
479
        // 19. Se muestra el frame principal
480
        splashWindow.process(180, PluginServices.getText(Launcher.class,
481
            "creating_main_window"));
482
        frame.setVisible(true);
483

    
484
        // 19. Se ejecuta el postInitialize
485
        splashWindow.process(190, PluginServices.getText(Launcher.class,
486
            "SplashWindow.post_initializing_extensions"));
487
        SwingUtilities.invokeAndWait(new Runnable() {
488

    
489
            public void run() {
490
                postInitializeExtensions();
491

    
492
            }
493
        });
494

    
495
        // Definimos un KeyEventDispatcher global para que las extensiones
496
        // puedan registrar sus "teclas r?pidas".
497
        GlobalKeyEventDispatcher keyDispatcher =
498
            GlobalKeyEventDispatcher.getInstance();
499
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
500
            .addKeyEventDispatcher(keyDispatcher);
501

    
502
        SwingUtilities.invokeAndWait(new Runnable() {
503

    
504
            public void run() {
505
                frame.enableControls();
506
            }
507
        });
508
        splashWindow.close();
509
        if (launcherrors != null) {
510
            NotificationManager.addError(launcherrors);
511
        }
512
        
513
        org.apache.log4j.Logger.getRootLogger().addAppender(new NotificationAppender());
514

    
515
        
516
    }
517

    
518
    /**
519
     * 
520
     */
521
    private void initializeLibraries() {
522
        List<ClassLoader> classLoaders =
523
            new ArrayList<ClassLoader>(pluginsOrdered.size() + 1);
524
        classLoaders.add(getClass().getClassLoader());
525
        Iterator<String> iter = pluginsOrdered.iterator();
526

    
527
        logger.debug("Initializing plugins libraries: ");
528
        while (iter.hasNext()) {
529
            String pName = (String) iter.next();
530
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
531
            classLoaders.add(ps.getClassLoader());
532
        }
533

    
534
        // Create the libraries initializer and
535
        // initialize the plugin libraries
536
        new DefaultLibrariesInitializer(
537
            classLoaders.toArray(new ClassLoader[classLoaders.size()]))
538
            .fullInitialize(true);
539

    
540
        // Remove them all, we don't need them anymore
541
        classLoaders.clear();
542
        classLoaders = null;
543
    }
544

    
545
    /**
546
     * @param args
547
     * @throws IOException
548
     * @throws ConfigurationException
549
     */
550
    private void initializeApp(String[] args) throws IOException,
551
        ConfigurationException {
552
        if (!validJVM()) {
553
            System.exit(-1);
554
        }
555

    
556
        // Clean temporal files
557
        Utilities.cleanUpTempFiles();
558

    
559
        appName = args[0];
560

    
561
        getOrCreateConfigFolder();
562

    
563
        configureLogging(appName);
564

    
565
        loadAndamiConfig(args[1]);
566

    
567
        // Hacemos visibles los argumentos como una propiedad est?tica
568
        // de plugin services para quien lo quiera usar (por ejemplo, para
569
        // cargar un proyecto por l?nea de comandos)
570
        PluginServices.setArguments(args);
571

    
572
        configureLocales(args);
573

    
574
        logger.info("Load and initialize andami and plugins libraries");
575
        // LibrariesInitializer libsInitializer =
576
        // new DefaultLibrariesInitializer();
577
        // libsInitializer.initialize(true);
578
        // libsInitializer.postInitialize(true);
579

    
580
        logger.info("Configure LookAndFeel");
581
        configureLookAndFeel();
582
    }
583

    
584
    /**
585
     * 
586
     */
587
    private void configureLookAndFeel() {
588
        // Se pone el lookAndFeel
589
        try {
590
            String lookAndFeel = getAndamiConfig().getLookAndFeel();
591
            if (lookAndFeel == null) {
592
                lookAndFeel = getDefaultLookAndFeel();
593
            }
594
            UIManager.setLookAndFeel(lookAndFeel);
595
        } catch (Exception e) {
596
            logger.warn(Messages.getString("Launcher.look_and_feel"), e);
597
        }
598
        FontUtils.initFonts();
599
    }
600

    
601
    /**
602
     * @param args
603
     * @throws ConfigurationException
604
     */
605
    private void loadAndamiConfig(String pluginFolder)
606
        throws ConfigurationException {
607
        // Leer el fichero de configuraci?n de andami (andami-config.xsd)
608
        // locale
609
        // Buscar actualizaci?nes al comenzar
610
        // Andami
611
        // Plugins
612
        // Directorio de las extensiones
613
        andamiConfigPath = appHomeDir + File.separator + "andami-config.xml";
614
        andamiConfigFromXML(andamiConfigPath);
615
        andamiConfig.setPluginsDirectory(pluginFolder);
616
    }
617

    
618
    /**
619
     * 
620
     */
621
    private void getOrCreateConfigFolder() {
622
        // Create application configuration folder
623
        appHomeDir = System.getProperty(appName + ".home");
624
        if (appHomeDir == null) {
625
            appHomeDir = System.getProperty("user.home");
626
        }
627

    
628
        appHomeDir += File.separator + appName;
629
        File parent = new File(appHomeDir);
630
        parent.mkdirs();
631
    }
632

    
633
    /**
634
     * @param args
635
     * @throws IOException
636
     */
637
    private void configureLogging(String appName) throws IOException {
638
        // Configurar el log4j
639
        Launcher.class.getClassLoader().getResource(".");
640
        PropertyConfigurator.configure("log4j.properties");
641

    
642
        PatternLayout l = new PatternLayout("%p %t %C - %m%n");
643
        RollingFileAppender fa =
644
            new RollingFileAppender(l, appHomeDir + File.separator + appName
645
                + ".log", false);
646
        fa.setMaxFileSize("512KB");
647
        fa.setMaxBackupIndex(3);
648
        org.apache.log4j.Logger.getRootLogger().addAppender(fa);
649
    }
650

    
651
    
652
    private class NotificationAppender extends AppenderSkeleton{
653

    
654
        @Override
655
        protected void append(LoggingEvent event) {
656
            if (event.getLevel() == org.apache.log4j.Level.ERROR
657
                || event.getLevel() == org.apache.log4j.Level.FATAL) {
658
                NotificationManager.dispatchError(event.getRenderedMessage(), null);
659
                return;
660
            }
661
//            if (event.getLevel() == org.apache.log4j.Level.WARN) {
662
//                NotificationManager.dispatchWarning(event.getRenderedMessage(), null);
663
//                return;
664
//            }
665
        }
666

    
667
        @Override
668
        public void close() {
669
            // TODO Auto-generated method stub
670
            
671
        }
672

    
673
        @Override
674
        public boolean requiresLayout() {
675
            // TODO Auto-generated method stub
676
            return false;
677
        }
678
        
679
    }
680

    
681
    /**
682
     * Return the directory applicaction is installed.
683
     */
684
    public static String getApplicationDirectory() {
685
        return new File("").getAbsolutePath();
686
    }
687

    
688
    private void registerIcons() {
689
        PluginServices.getIconTheme().registerDefault(
690
            "login-gvsig",
691
            LoginUI.class.getClassLoader()
692
                .getResource("images/login_gvsig.png"));
693
        PluginServices.getIconTheme().registerDefault(
694
            "splash-gvsig",
695
            MultiSplashWindow.class.getClassLoader().getResource(
696
                "images/splash.png"));
697
        PluginServices.getIconTheme().registerDefault("info-icon",
698
            NewStatusBar.class.getClassLoader().getResource("images/info.gif"));
699
        PluginServices.getIconTheme()
700
            .registerDefault(
701
                "error-icon",
702
                NewStatusBar.class.getClassLoader().getResource(
703
                    "images/error.gif"));
704
        PluginServices.getIconTheme().registerDefault(
705
            "warning-icon",
706
            NewStatusBar.class.getClassLoader().getResource(
707
                "images/warning.gif"));
708
        PluginServices.getIconTheme().registerDefault(
709
            "no-icon",
710
            NewStatusBar.class.getClassLoader().getResource(
711
                "images/no_icon.png"));
712
    }
713

    
714
    /**
715
     * Obtiene la personalizaci?n de los iconos, splash, fondo y el nombre de
716
     * la aplicaci?n.
717
     * 
718
     * @return Theme
719
     */
720
    private Theme getTheme(String pluginsDirectory) {
721
        File themeFile = null;
722
        Theme theme = new Theme();
723

    
724
        // Try to get theme from args
725
        String name = PluginServices.getArgumentByName("andamiTheme");
726
        if (name != null) {
727
            themeFile = new File(name);
728
            logger.info("search andami-theme in {}", themeFile
729
                .getAbsolutePath());
730
            if (themeFile.exists()) {
731
                theme.readTheme(themeFile);
732
                logger.info("andami-theme found in {}", themeFile
733
                    .getAbsolutePath());
734
                return theme;
735
            }
736
        }
737

    
738
        // Try to get theme from a plugin
739
        File pluginsDir = new File(pluginsDirectory);
740
        if( !pluginsDir.isAbsolute() ) {
741
                pluginsDir = new File(System.getProperty("user.dir"),  pluginsDirectory);
742
        }
743
        if (pluginsDir.exists()) {
744
            logger.info("search andami-theme in plugins folder.");
745
            File[] pluginDirs = pluginsDir.listFiles();
746
            if (pluginDirs.length > 0) {
747
                for (int i = 0; i < pluginDirs.length; i++) {
748
                    File pluginThemeFile =
749
                        new File( pluginDirs[i], "theme" + File.separator
750
                            + "andami-theme.xml");
751
                    if (pluginThemeFile.exists()) {
752
                        themeFile = pluginThemeFile;
753
                        // This if is a hack to allow more themes than the
754
                        // one available in org.gvsig.app. Remove this
755
                        // when a the theme format is changed to allow for
756
                        // priorities
757
                        if (!"org.gvsig.app".equals(pluginDirs[i].getName())  ) {
758
                            break;
759
                        }
760
                    }
761
                }
762
            }
763
        }
764

    
765
        // The theme file will be the one into a plugin or by default the one
766
        // in the org.gvsig.app plugin
767
        if (themeFile != null && themeFile.exists()) {
768
            theme.readTheme(themeFile);
769
            logger.info("andami-theme found in plugin {}",
770
                themeFile.getAbsolutePath());
771
            return theme;
772
        }
773

    
774
        // Try to get theme from dir gvSIG in user home
775
        themeFile =
776
            new File(getAppHomeDir(), "theme" + File.separator
777
                + "andami-theme.xml");
778
        logger.info("search andami-theme in user's home {}", themeFile
779
            .getAbsolutePath());
780
        if (themeFile.exists()) {
781
            theme.readTheme(themeFile);
782
            logger.info("andami-theme found in user's home {}", themeFile
783
                .getAbsolutePath());
784
            return theme;
785
        }
786

    
787
        // Try to get theme from the instalation dir of gvSIG.
788
        themeFile =
789
            new File(getApplicationDirectory(), "theme" + File.separator
790
                + "andami-theme.xml");
791
        logger.info("search andami-theme in installation folder {}", themeFile
792
            .getAbsolutePath());
793
        if (themeFile.exists()) {
794
            theme.readTheme(themeFile);
795
            logger.info("andami-theme found in instalation folder {}",
796
                themeFile.getAbsolutePath());
797
            return theme;
798
        }
799
        logger.info("Apply default andami-theme.");
800
        return theme;
801
    }
802

    
803
    /**
804
     * Establece los datos que ten?amos guardados respecto de la configuraci?n
805
     * del proxy.
806
     */
807
    private void configureProxy() {
808
        String host = prefs.get("firewall.http.host", "");
809
        String port = prefs.get("firewall.http.port", "");
810

    
811
        System.getProperties().put("http.proxyHost", host);
812
        System.getProperties().put("http.proxyPort", port);
813

    
814
        // Ponemos el usuario y clave del proxy, si existe
815
        String proxyUser = prefs.get("firewall.http.user", null);
816
        String proxyPassword = prefs.get("firewall.http.password", null);
817
        if (proxyUser != null) {
818
            System.getProperties().put("http.proxyUserName", proxyUser);
819
            System.getProperties().put("http.proxyPassword", proxyPassword);
820

    
821
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
822
        } else {
823
            Authenticator.setDefault(new ProxyAuth("", ""));
824
        }
825
    }
826

    
827
    /**
828
     * Recupera la geometr?a (tama?o, posic?n y estado) de la ventana principal
829
     * de Andami.
830
     * TODO Pendiente de ver como se asigna un pluginServices para el launcher.
831
     * 
832
     * @author LWS
833
     */
834
    private void restoreMDIStatus(XMLEntity xml) {
835
        if (xml == null) {
836
            xml = new XMLEntity();
837
        }
838
        // restore frame size
839
        Dimension sz = new Dimension(700, 580);
840
        if (xml.contains("MDIFrameSize")) {
841
            int[] wh = xml.getIntArrayProperty("MDIFrameSize");
842
            sz = new Dimension(wh[0], wh[1]);
843
        }
844
        frame.setSize(sz);
845
        // restore frame location
846
        Point pos = new Point(10, 10);
847
        if (xml.contains("MDIFramePos")) {
848
            int[] xy = xml.getIntArrayProperty("MDIFramePos");
849
            pos = new Point(xy[0], xy[1]);
850
        }
851
        frame.setLocation(pos);
852

    
853
        // restore frame status (Maximized, minimized, etc);
854
        int state = java.awt.Frame.MAXIMIZED_BOTH;
855
        if (xml.contains("MDIFrameState")) {
856
            state = xml.getIntProperty("MDIFrameState");
857
        }
858
        frame.setExtendedState(state);
859
    }
860

    
861
    private XMLEntity saveMDIStatus() {
862
        XMLEntity xml = new XMLEntity();
863
        // save frame size
864
        int[] wh = new int[2];
865
        wh[0] = frame.getWidth();
866
        wh[1] = frame.getHeight();
867
        xml.putProperty("MDIFrameSize", wh);
868
        // save frame location
869
        int[] xy = new int[2];
870
        xy[0] = frame.getX();
871
        xy[1] = frame.getY();
872
        xml.putProperty("MDIFramePos", xy);
873
        // save frame status
874
        xml.putProperty("MDIFrameState", frame.getExtendedState());
875
        return xml;
876
    }
877

    
878
    private boolean validJVM() {
879
        char thirdCharacter = System.getProperty("java.version").charAt(2);
880
        if (thirdCharacter < '4') {
881
            return false;
882
        } else {
883
            return true;
884
        }
885
    }
886

    
887
    private void loadPluginsPersistence() throws ConfigurationException {
888
        XMLEntity entity = persistenceFromXML();
889

    
890
        for (int i = 0; i < entity.getChildrenCount(); i++) {
891
            XMLEntity plugin = entity.getChild(i);
892
            String pName =
893
                plugin.getStringProperty("com.iver.andami.pluginName");
894

    
895
            if (pName.compareToIgnoreCase("com.iver.cit.gvsig") == 0) {
896
                pName = "org.gvsig.app";
897
            }
898
            if (pluginsServices.get(pName) != null) {
899
                ((PluginServices) pluginsServices.get(pName))
900
                    .setPersistentXML(plugin);
901
            } else {
902
                if (pName.startsWith("Andami.Launcher")) {
903
                    restoreMDIStatus(plugin);
904
                }
905
            }
906
        }
907
    }
908

    
909
    /**
910
     * Salva la persistencia de los plugins.
911
     * 
912
     * @author LWS
913
     */
914
    private void savePluginPersistence() {
915
        Iterator<String> i = pluginsConfig.keySet().iterator();
916

    
917
        XMLEntity entity = new XMLEntity();
918

    
919
        while (i.hasNext()) {
920
            String pName = i.next();
921
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
922
            XMLEntity ent = ps.getPersistentXML();
923

    
924
            if (ent != null) {
925
                ent.putProperty("com.iver.andami.pluginName", pName);
926
                entity.addChild(ent);
927
            }
928
        }
929
        XMLEntity ent = saveMDIStatus();
930
        if (ent != null) {
931
            ent.putProperty("com.iver.andami.pluginName", "Andami.Launcher");
932
            entity.addChild(ent);
933
        }
934
        try {
935
            persistenceToXML(entity);
936
        } catch (ConfigurationException e1) {
937
            this
938
                .addError(
939
                    Messages
940
                        .getString("Launcher.Se_produjo_un_error_guardando_la_configuracion_de_los_plugins"),
941
                    e1);
942
        }
943
    }
944

    
945
    private void installPluginsLabels() {
946
        Iterator<String> i = pluginsConfig.keySet().iterator();
947

    
948
        while (i.hasNext()) {
949
            String name = i.next();
950
            PluginConfig pc = pluginsConfig.get(name);
951
            PluginServices ps = (PluginServices) pluginsServices.get(name);
952

    
953
            LabelSet[] ls = pc.getLabelSet();
954

    
955
            for (int j = 0; j < ls.length; j++) {
956
                PluginClassLoader loader = ps.getClassLoader();
957

    
958
                try {
959
                    Class clase = loader.loadClass(ls[j].getClassName());
960
                    frame.setStatusBarLabels(clase, ls[j].getLabel());
961
                } catch (ClassNotFoundException e) {
962
                    this.addError(
963
                        Messages.getString("Launcher.labelset_class"), e);
964
                }
965
            }
966
        }
967
    }
968

    
969
    private String configureSkin(XMLEntity xml, String defaultSkin) {
970
        if (defaultSkin == null) {
971
            for (int i = 0; i < xml.getChildrenCount(); i++) {
972
                if (xml.getChild(i).contains("Skin-Selected")) {
973
                    String className =
974
                        xml.getChild(i).getStringProperty("Skin-Selected");
975
                    return className;
976
                }
977
            }
978
        }
979
        // return "com.iver.core.mdiManager.NewSkin";
980
        return defaultSkin;
981
    }
982

    
983
    private void fixSkin(SkinExtension skinExtension,
984
        PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
985
        // now insert the skin selected.
986
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
987
        // MDIManagerFactory.setSkinExtension(se,
988
        // ps.getClassLoader());
989

    
990
        Class<? extends IExtension> skinClass;
991

    
992
        try {
993
            skinClass =
994
                (Class<? extends IExtension>) pluginClassLoader
995
                    .loadClass(skinExtension.getClassName());
996

    
997
            IExtension skinInstance = skinClass.newInstance();
998
            ExtensionDecorator newExtensionDecorator =
999
                new ExtensionDecorator(skinInstance,
1000
                    ExtensionDecorator.INACTIVE);
1001
            classesExtensions.put(skinClass, newExtensionDecorator);
1002
        } catch (ClassNotFoundException e) {
1003
            logger.error(Messages
1004
                .getString("Launcher.No_se_encontro_la_clase_mdi_manager"), e);
1005
            throw new MDIManagerLoadException(e);
1006
        } catch (InstantiationException e) {
1007
            logger
1008
                .error(
1009
                    Messages
1010
                        .getString("Launcher.No_se_pudo_instanciar_la_clase_mdi_manager"),
1011
                    e);
1012
            throw new MDIManagerLoadException(e);
1013
        } catch (IllegalAccessException e) {
1014
            logger
1015
                .error(
1016
                    Messages
1017
                        .getString("Launcher.No_se_pudo_acceder_a_la_clase_mdi_manager"),
1018
                    e);
1019
            throw new MDIManagerLoadException(e);
1020
        }
1021

    
1022
    }
1023

    
1024
    /**
1025
     * DOCUMENT ME!
1026
     * 
1027
     * @throws MDIManagerLoadException
1028
     */
1029
    private void skinPlugin(String defaultSkin) throws MDIManagerLoadException {
1030
        XMLEntity entity = null;
1031
        try {
1032
            entity = persistenceFromXML();
1033
        } catch (ConfigurationException e1) {
1034
            // TODO Auto-generated catch block
1035
            e1.printStackTrace();
1036
        }
1037
        Iterator<String> i = pluginsConfig.keySet().iterator();
1038

    
1039
        SkinExtension skinExtension = null;
1040
        PluginClassLoader pluginClassLoader = null;
1041
        List<SkinExtension> skinExtensions = new ArrayList<SkinExtension>();
1042
        while (i.hasNext()) {
1043
            String name = i.next();
1044
            PluginConfig pc = pluginsConfig.get(name);
1045
            PluginServices ps = pluginsServices.get(name);
1046

    
1047
            if (pc.getExtensions().getSkinExtension() != null) {
1048
                // if (MDIManagerFactory.getSkinExtension() != null) {
1049
                // logger.warn(Messages.getString(
1050
                // "Launcher.Dos_skin_extension"));
1051
                // }
1052

    
1053
                SkinExtension[] se = pc.getExtensions().getSkinExtension();
1054
                for (int numExten = 0; numExten < se.length; numExten++) {
1055
                    skinExtensions.add(se[numExten]);
1056
                }
1057
                for (int j = 0; j < se.length; j++) {
1058
                    String configuredSkin =
1059
                        this.configureSkin(entity, defaultSkin);
1060
                    if ((configuredSkin != null)
1061
                        && configuredSkin.equals(se[j].getClassName())) {
1062
                        skinExtension = se[j];
1063
                        pluginClassLoader = ps.getClassLoader();
1064
                    }
1065
                }
1066
            }
1067
        }
1068

    
1069
        if ((skinExtension != null) && (pluginClassLoader != null)) {
1070
            // configured skin was found
1071
            fixSkin(skinExtension, pluginClassLoader);
1072
        } else {
1073
            if (skinExtensions.contains("com.iver.core.mdiManager.NewSkin")) {
1074
                // try first NewSkin (from CorePlugin)
1075
                skinPlugin("com.iver.core.mdiManager.NewSkin");
1076
            } else
1077
                if (skinExtensions.size() > 0) {
1078
                    // try to load the first skin found
1079
                    SkinExtension se = (SkinExtension) skinExtensions.get(0);
1080
                    skinPlugin((String) se.getClassName());
1081
                } else {
1082
                    throw new MDIManagerLoadException(
1083
                        "No Skin-Extension installed");
1084
                }
1085
        }
1086

    
1087
    }
1088

    
1089
    private static void frameIcon(Theme theme) {
1090
        Iterator<String> i = pluginsConfig.keySet().iterator();
1091

    
1092
        while (i.hasNext()) {
1093
            String pName = i.next();
1094
            PluginConfig pc = pluginsConfig.get(pName);
1095
            if (pc.getIcon() != null) {
1096
                if (theme.getIcon() != null) {
1097
                    frame.setIconImage(theme.getIcon().getImage());
1098
                } else {
1099

    
1100
                    ImageIcon icon =
1101
                        PluginServices.getIconTheme()
1102
                            .get(pc.getIcon().getSrc());
1103
                    frame.setIconImage(icon.getImage());
1104

    
1105
                }
1106
                if (theme.getName() != null) {
1107
                    frame.setTitlePrefix(theme.getName());
1108
                } else {
1109
                    frame.setTitlePrefix(pc.getIcon().getText());
1110
                }
1111
                if (theme.getBackgroundImage() != null) {
1112

    
1113
                    PluginServices.getMDIManager().setBackgroundImage(
1114
                        theme.getBackgroundImage(), theme.getTypeDesktop());
1115
                }
1116
            }
1117
        }
1118
    }
1119

    
1120
    private void initializeExtensions() {
1121

    
1122
        List<ClassLoader> classLoaders =
1123
            new ArrayList<ClassLoader>(pluginsOrdered.size());
1124
        classLoaders.add(getClass().getClassLoader());
1125
        Iterator<String> iter = pluginsOrdered.iterator();
1126

    
1127
        // logger.debug("Initializing plugins libraries: ");
1128
        // while (iter.hasNext()) {
1129
        // String pName = (String) iter.next();
1130
        // PluginServices ps = (PluginServices) pluginsServices.get(pName);
1131
        // classLoaders.add(ps.getClassLoader());
1132
        // }
1133
        //
1134
        // // Create the libraries initializer and
1135
        // // initialize the plugin libraries
1136
        // new DefaultLibrariesInitializer(
1137
        // classLoaders.toArray(new ClassLoader[classLoaders.size()]))
1138
        // .fullInitialize();
1139
        //
1140
        // // Remove them all, we don't need them anymore
1141
        // classLoaders.clear();
1142
        // classLoaders = null;
1143

    
1144
        logger.info("Initializing plugins: ");
1145
        // iter = pluginsOrdered.iterator();
1146
        while (iter.hasNext()) {
1147
            String pName = (String) iter.next();
1148
            logger.info("Initializing plugin " + pName);
1149
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1150
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1151

    
1152
            Extension[] exts = pc.getExtensions().getExtension();
1153

    
1154
            TreeSet<Extension> orderedExtensions =
1155
                new TreeSet<Extension>(new ExtensionComparator());
1156

    
1157
            for (int j = 0; j < exts.length; j++) {
1158
                if (!exts[j].getActive()) {
1159
                    continue;
1160
                }
1161

    
1162
                if (orderedExtensions.contains(exts[j])) {
1163
                    logger.warn("Two extensions with the same priority ("
1164
                        + exts[j].getClassName() + ")");
1165
                }
1166

    
1167
                orderedExtensions.add(exts[j]);
1168
            }
1169

    
1170
            Iterator<Extension> e = orderedExtensions.iterator();
1171

    
1172
            logger.info("Initializing extensions of plugin "+pName+": ");
1173
            while (e.hasNext()) {
1174
                Extension extension = e.next();
1175
                org.gvsig.andami.plugins.IExtension extensionInstance;
1176

    
1177
                try {
1178
                    logger.info("Initializing " + extension.getClassName()
1179
                        + "...");
1180
                    Class<? extends IExtension> extensionClass =
1181
                        (Class<? extends IExtension>) ps.getClassLoader()
1182
                            .loadClass(extension.getClassName());
1183
                    extensionInstance = extensionClass.newInstance();
1184

    
1185
                    // CON DECORATOR
1186
                    // ANTES: classesExtensions.put(extensionClass,
1187
                    // extensionInstance);
1188
                    // AHORA: CREAMOS UNA ExtensionDecorator y asignamos esta
1189
                    // instancia para
1190
                    // poder ampliar con nuevas propiedades (AlwaysVisible, por
1191
                    // ejemplo)
1192
                    // Para crear la nueva clase ExtensionDecorator, le pasamos
1193
                    // como par?metro
1194
                    // la extensi?n original que acabamos de crear
1195
                    // 0-> Inactivo, controla la extension
1196
                    // 1-> Siempre visible
1197
                    // 2-> Invisible
1198
                    ExtensionDecorator newExtensionDecorator =
1199
                        new ExtensionDecorator(extensionInstance,
1200
                            ExtensionDecorator.INACTIVE);
1201
                    classesExtensions
1202
                        .put(extensionClass, newExtensionDecorator);
1203

    
1204
                    extensionInstance.initialize();
1205
                    extensions.add(extensionInstance);
1206

    
1207
                } catch (NoClassDefFoundError e1) {
1208
                    this.addError("Can't find class extension ("
1209
                        + extension.getClassName() + ")", e1);
1210
                } catch (Throwable e1) {
1211
                    this.addError("Can't initialize extension '"
1212
                        + extension.getClassName() + "'.", e1);
1213
                }
1214
            }
1215
        }
1216
    }
1217

    
1218
    private void postInitializeExtensions() {
1219
        logger.info("PostInitializing extensions: ");
1220

    
1221
        for (int i = 0; i < extensions.size(); i++) {
1222
            org.gvsig.andami.plugins.IExtension extensionInstance =
1223
                (org.gvsig.andami.plugins.IExtension) extensions.get(i);
1224
            logger.info("PostInitializing "
1225
                + extensionInstance.getClass().getName() + "...");
1226
            try {
1227
                extensionInstance.postInitialize();
1228
            } catch (Throwable ex) {
1229
                this.addError("postInitialize of extension '"
1230
                    + extensionInstance.getClass().getName() + "' failed", ex);
1231
            }
1232
        }
1233
    }
1234

    
1235
    private void installPluginsMenus() {
1236
        TreeSet<SortableMenu> orderedMenus =
1237
            new TreeSet<SortableMenu>(new MenuComparator());
1238

    
1239
        Iterator<String> i = pluginsConfig.keySet().iterator();
1240

    
1241
        while (i.hasNext()) {
1242
            String pName = i.next();
1243
                try {
1244
            PluginServices ps = pluginsServices.get(pName);
1245
            PluginConfig pc = pluginsConfig.get(pName);
1246

    
1247
            Extension[] exts = pc.getExtensions().getExtension();
1248

    
1249
            for (int j = 0; j < exts.length; j++) {
1250
                if (!exts[j].getActive()) {
1251
                    continue;
1252
                }
1253

    
1254
                Menu[] menus = exts[j].getMenu();
1255

    
1256
                for (int k = 0; k < menus.length; k++) {
1257
                    SortableMenu sm =
1258
                        new SortableMenu(ps.getClassLoader(), exts[j], menus[k]);
1259

    
1260
                    if (orderedMenus.contains(sm)) {
1261
                        this
1262
                            .addError(Messages
1263
                                .getString("Launcher.Two_menus_with_the_same_position")
1264
                                + " - "
1265
                                + menus[k].getText()
1266
                                + " - "
1267
                                + exts[j].getClassName());
1268
                    }
1269

    
1270
                    orderedMenus.add(sm);
1271
                }
1272
            }
1273

    
1274
            // Se instalan las extensiones de MDI
1275
            SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1276
            for (int j = 0; j < skinExts.length; j++) {
1277

    
1278
                if (skinExts[j] != null) {
1279
                    Menu[] menu = skinExts[j].getMenu();
1280

    
1281
                    for (int k = 0; k < menu.length; k++) {
1282
                        SortableMenu sm =
1283
                            new SortableMenu(ps.getClassLoader(), skinExts[j],
1284
                                menu[k]);
1285

    
1286
                        if (orderedMenus.contains(sm)) {
1287
                            this
1288
                                .addError(Messages
1289
                                    .getString("Launcher.Two_menus_with_the_same_position")
1290
                                    + skinExts[j].getClassName());
1291
                        }
1292

    
1293
                        orderedMenus.add(sm);
1294
                    }
1295
                }
1296
            }
1297
            
1298
            
1299
                } catch (Throwable e) {
1300
                        addError("Error initializing menus of plugin '"+pName+"'", e);
1301
                        }
1302
            
1303
            
1304
        }
1305

    
1306
        // Se itera por los menus ordenados
1307
        Iterator<SortableMenu> e = orderedMenus.iterator();
1308

    
1309
        // Se ordenan los menues
1310
        while (e.hasNext()) {
1311
            try {
1312
                SortableMenu sm = e.next();
1313

    
1314
                frame.addMenu(sm.loader, sm.extension, sm.menu);
1315

    
1316
            } catch (ClassNotFoundException ex) {
1317
                this
1318
                    .addError(
1319
                        Messages
1320
                            .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1321
                        ex);
1322
            } catch (NoClassDefFoundError ex) {
1323
                this
1324
                .addError(
1325
                    Messages
1326
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1327
                    ex);
1328
            } catch (Throwable ex) {
1329
                this
1330
                .addError(
1331
                    Messages
1332
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1333
                    ex);
1334
            }
1335
        }
1336
    }
1337

    
1338
    /**
1339
     * Installs the menus, toolbars, actiontools, selectable toolbars and
1340
     * combos.
1341
     * The order in which they are shown is determined here.
1342
     */
1343
    private void installPluginsControls() {
1344
        Iterator<String> i = pluginsConfig.keySet().iterator();
1345

    
1346
        Map<Extension, PluginServices> extensionPluginServices =
1347
            new HashMap<Extension, PluginServices>();
1348
        Map<Extension, PluginConfig> extensionPluginConfig =
1349
            new HashMap<Extension, PluginConfig>();
1350
        Set<Extension> orderedExtensions =
1351
            new TreeSet<Extension>(new ExtensionComparator());
1352

    
1353
        // First of all, sort the extensions.
1354
        // We need to iterate on the plugins, and iterate on each plugin's
1355
        // extensions
1356
        // (each plugin may contain one or more extensions)
1357
        while (i.hasNext()) { // iterate on the plugins
1358
                    String pName = i.next();
1359
                try {
1360
                        PluginConfig pc = pluginsConfig.get(pName);
1361
                        PluginServices ps = pluginsServices.get(pName);
1362

    
1363
                        Extension[] exts = pc.getExtensions().getExtension();
1364

    
1365
                        for (int j = 0; j < exts.length; j++) { // iterate on the extensions
1366
                                String cname = "unknow";
1367
                                try {
1368
                                    cname = exts[j].getClassName();
1369
                                        if (exts[j].getActive()  && !cname.equals(LibraryExtension.class.getName()) ) {
1370
                                                if (orderedExtensions.contains(exts[j])) {
1371
                                                        this
1372
                                                        .addError(Messages
1373
                                                                        .getString("Launcher.Two_extensions_with_the_same_priority")
1374
                                                                        + cname);
1375
                                                }
1376

    
1377
                                                orderedExtensions.add(exts[j]);
1378
                                                extensionPluginServices.put(exts[j], ps);
1379
                                                extensionPluginConfig.put(exts[j], pc);
1380
                                        }
1381
                                } catch (Exception e) {
1382
                                addError("Error initializing controls of plugin '"+pName+"' extension '"+cname+"'", e);
1383
                                        }
1384
                        }
1385
                } catch (Throwable e) {
1386
                        addError("Error initializing controls of plugin '"+pName+"'", e);
1387
                }
1388
        }
1389

    
1390
        TreeSet<SortableTool> orderedTools =
1391
            new TreeSet<SortableTool>(new ToolComparator());
1392
        Iterator<Extension> e = orderedExtensions.iterator();
1393

    
1394
        // sort the toolbars and tools from 'normal' extensions (actiontools,
1395
        // selectabletools)
1396
        // and load the combo-scales and combo-buttons for the status bar
1397
        while (e.hasNext()) {
1398
                    Extension ext = e.next();
1399
                    String extName = "unknow";
1400
                try {
1401
                        extName = ext.getClassName();
1402
                        ToolBar[] toolbars = ext.getToolBar();
1403

    
1404
                        // get tools from toolbars
1405
                        for (int k = 0; k < toolbars.length; k++) {
1406
                                ActionTool[] tools = toolbars[k].getActionTool();
1407

    
1408
                                for (int t = 0; t < tools.length; t++) {
1409
                                        SortableTool sm =
1410
                                                new SortableTool((extensionPluginServices.get(ext))
1411
                                                                .getClassLoader(), ext, toolbars[k], tools[t]);
1412
                                        orderedTools.add(sm);
1413
                                }
1414

    
1415
                                SelectableTool[] sTools = toolbars[k].getSelectableTool();
1416

    
1417
                                for (int t = 0; t < sTools.length; t++) {
1418
                                        SortableTool sm =
1419
                                                new SortableTool((extensionPluginServices.get(ext))
1420
                                                                .getClassLoader(), ext, toolbars[k], sTools[t]);
1421
                                        orderedTools.add(sm);
1422
                                }
1423
                        }
1424

    
1425
                        // get controls for statusBar
1426
                        PluginServices ps = extensionPluginServices.get(ext);
1427
                        PluginClassLoader loader = ps.getClassLoader();
1428

    
1429
                        // ArrayList componentList = new ArrayList();
1430
                        ComboScale[] comboScaleArray = ext.getComboScale();
1431
                        for (int k = 0; k < comboScaleArray.length; k++) {
1432
                                org.gvsig.gui.beans.controls.comboscale.ComboScale combo =
1433
                                        new org.gvsig.gui.beans.controls.comboscale.ComboScale();
1434
                                String label = comboScaleArray[k].getLabel();
1435
                                if (label != null) {
1436
                                        combo.setLabel(label);
1437
                                }
1438
                                String name = comboScaleArray[k].getName();
1439
                                if (name != null) {
1440
                                        combo.setName(name);
1441
                                }
1442
                                String[] elementsString =
1443
                                        ((String) comboScaleArray[k].getElements()).split(";");
1444
                                long[] elements = new long[elementsString.length];
1445
                                for (int currentElem = 0; currentElem < elementsString.length; currentElem++) {
1446
                                        try {
1447
                                                elements[currentElem] =
1448
                                                        Long.parseLong(elementsString[currentElem]);
1449
                                        } catch (NumberFormatException nfex1) {
1450
                                                this
1451
                                                .addError(ext.getClassName()
1452
                                                                + " -- "
1453
                                                                + Messages
1454
                                                                .getString("error_parsing_comboscale_elements"));
1455
                                                elements[currentElem] = 0;
1456
                                        }
1457
                                }
1458
                                combo.setItems(elements);
1459
                                try {
1460
                                        long value =
1461
                                                Long.parseLong((String) comboScaleArray[k].getValue());
1462
                                        combo.setScale(value);
1463
                                } catch (NumberFormatException nfex2) {
1464
                                        this.addError(ext.getClassName() + " -- "
1465
                                                        + Messages.getString("error_parsing_comboscale_value"));
1466
                                }
1467
                                try {
1468
                                        frame.addStatusBarControl(loader.loadClass(ext
1469
                                                        .getClassName()), combo);
1470
                                } catch (ClassNotFoundException e1) {
1471
                                        this
1472
                                        .addError(
1473
                                                        Messages
1474
                                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
1475
                                                        e1);
1476
                                }
1477
                        }
1478

    
1479
                        ComboButton[] comboButtonArray = ext.getComboButton();
1480
                        for (int k = 0; k < comboButtonArray.length; k++) {
1481
                                ComboButtonElement[] elementList =
1482
                                        comboButtonArray[k].getComboButtonElement();
1483
                                org.gvsig.gui.beans.controls.combobutton.ComboButton combo =
1484
                                        new org.gvsig.gui.beans.controls.combobutton.ComboButton();
1485
                                String name = comboButtonArray[k].getName();
1486
                                if (name != null) {
1487
                                        combo.setName(name);
1488
                                }
1489
                                for (int currentElement = 0; currentElement < elementList.length; currentElement++) {
1490
                                        ComboButtonElement element = elementList[currentElement];
1491
                                        ImageIcon icon;
1492
                                        URL iconLocation = loader.getResource(element.getIcon());
1493
                                        if (iconLocation == null) {
1494
                                                this.addError(Messages.getString("Icon_not_found_")
1495
                                                                + element.getIcon());
1496
                                        } else {
1497
                                                icon = new ImageIcon(iconLocation);
1498
                                                JButton button = new JButton(icon);
1499
                                                combo.addButton(button);
1500
                                                button.setActionCommand(element.getActionCommand());
1501
                                        }
1502
                                }
1503
                                try {
1504
                                        frame.addStatusBarControl(loader.loadClass(ext
1505
                                                        .getClassName()), combo);
1506
                                } catch (ClassNotFoundException e1) {
1507
                                        this
1508
                                        .addError(
1509
                                                        Messages
1510
                                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
1511
                                                        e1);
1512
                                }
1513
                        }
1514
                } catch (Throwable e2) {
1515
                        addError("Error initializing tools and status bars of extension '"+extName+"'", e2);
1516
                }
1517
        }
1518

    
1519
        // Add the tools from MDI extensions to the ordered tool-list, so that
1520
        // we get a sorted list containing all the tools
1521
        i = pluginsConfig.keySet().iterator();
1522
        while (i.hasNext()) {
1523
                String pName = (String) i.next();
1524
                try {
1525
                        PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1526
                        PluginServices ps = (PluginServices) pluginsServices.get(pName);
1527

    
1528
                        SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1529
                        for (int j = 0; j < skinExts.length; j++) {
1530

    
1531
                                if (skinExts[j] != null) {
1532
                                        ToolBar[] toolbars = skinExts[j].getToolBar();
1533

    
1534
                                        for (int k = 0; k < toolbars.length; k++) {
1535
                                                ActionTool[] tools = toolbars[k].getActionTool();
1536

    
1537
                                                for (int t = 0; t < tools.length; t++) {
1538
                                                        SortableTool stb =
1539
                                                                new SortableTool(ps.getClassLoader(),
1540
                                                                                skinExts[j], toolbars[k], tools[t]);
1541
                                                        orderedTools.add(stb);
1542
                                                }
1543

    
1544
                                                SelectableTool[] sTools =
1545
                                                        toolbars[k].getSelectableTool();
1546

    
1547
                                                for (int t = 0; t < sTools.length; t++) {
1548
                                                        SortableTool stb =
1549
                                                                new SortableTool(ps.getClassLoader(),
1550
                                                                                skinExts[j], toolbars[k], sTools[t]);
1551
                                                        orderedTools.add(stb);
1552
                                                }
1553
                                        }
1554
                                }
1555
                        }
1556
                        // Install popup menus
1557
                        PopupMenus pus = pc.getPopupMenus();
1558

    
1559
                        if (pus != null) {
1560
                                PopupMenu[] menus = pus.getPopupMenu();
1561

    
1562
                                for (int j = 0; j < menus.length; j++) {
1563
                                        frame.addPopupMenu(ps.getClassLoader(), menus[j]);
1564
                                }
1565
                        }
1566
                } catch (Throwable e3) {
1567
                        addError("Error initializing skins of the plugin '"+pName+"'", e3);
1568
                }
1569
        }
1570

    
1571
        // loop on the ordered extension list, to add them to the interface in
1572
        // an ordered way
1573
        Iterator<SortableTool> t = orderedTools.iterator();
1574
        while (t.hasNext()) {
1575
            SortableTool stb = t.next();
1576
            try {
1577
                if (stb.actiontool != null) {
1578
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
1579
                        stb.actiontool);
1580
                } else {
1581
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
1582
                        stb.selectabletool);
1583
                }
1584
            } catch (ClassNotFoundException ex) {
1585
                this
1586
                    .addError(
1587
                        Messages
1588
                            .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1589
                        ex);
1590
            } catch (Throwable e2) {
1591
                    addError("Error adding tools to the interface of extension '"+ stb.extension.getClassName() + "'", e2);
1592
                        }
1593
        }
1594
    }
1595

    
1596
    /**
1597
     * Adds new plugins to the the andami-config file.
1598
     */
1599
    private void updateAndamiConfig() {
1600
        Set<String> olds = new HashSet<String>();
1601

    
1602
        Plugin[] plugins = andamiConfig.getPlugin();
1603

    
1604
        for (int i = 0; i < plugins.length; i++) {
1605
            olds.add(plugins[i].getName());
1606
        }
1607

    
1608
        Iterator<PluginServices> i = pluginsServices.values().iterator();
1609

    
1610
        while (i.hasNext()) {
1611
            PluginServices ps = i.next();
1612

    
1613
            if (!olds.contains(ps.getPluginName())) {
1614
                Plugin p = new Plugin();
1615
                p.setName(ps.getPluginName());
1616
                p.setUpdate(false);
1617

    
1618
                andamiConfig.addPlugin(p);
1619
            }
1620
        }
1621
    }
1622

    
1623
    private void pluginsClassLoaders() {
1624
        Set<String> installed = new HashSet<String>();
1625

    
1626
        // Se itera hasta que est?n todos instalados
1627
        while (installed.size() != pluginsConfig.size()) {
1628
            boolean circle = true;
1629

    
1630
            // Hacemos una pasada por todos los plugins
1631
            Iterator<String> i = pluginsConfig.keySet().iterator();
1632

    
1633
            while (i.hasNext()) {
1634
                String pluginName = i.next();
1635
                PluginConfig config =
1636
                    (PluginConfig) pluginsConfig.get(pluginName);
1637

    
1638
                if (installed.contains(pluginName)) {
1639
                    continue;
1640
                }
1641

    
1642
                // Se obtienen las dependencias y sus class loaders
1643
                boolean ready = true;
1644
                Depends[] dependencies = config.getDepends();
1645
                PluginClassLoader[] loaders =
1646
                    new PluginClassLoader[dependencies.length];
1647

    
1648
                for (int j = 0; j < dependencies.length; j++) {
1649
                    if (pluginsConfig.get(dependencies[j].getPluginName()) == null) {
1650
                        this
1651
                            .addError(Messages
1652
                                .getString("Launcher.Dependencia_no_resuelta_en_plugin")
1653
                                + " "
1654
                                + pluginName
1655
                                + ": "
1656
                                + dependencies[j].getPluginName());
1657

    
1658
                        continue;
1659
                    }
1660

    
1661
                    if (!installed.contains(dependencies[j].getPluginName())) {
1662
                        ready = false;
1663
                    } else {
1664
                        loaders[j] =
1665
                            (pluginsServices.get(dependencies[j]
1666
                                .getPluginName())).getClassLoader();
1667
                    }
1668
                }
1669

    
1670
                // Si no est?n sus dependencias satisfechas se aborta la
1671
                // instalaci?n
1672
                if (!ready) {
1673
                    continue;
1674
                }
1675

    
1676
                // Se genera el class loader
1677
                String jardir = config.getLibraries().getLibraryDir();
1678
                File jarDir =
1679
                    new File(andamiConfig.getPluginsDirectory(), pluginName
1680
                        + File.separator + jardir);
1681
                File[] jarFiles = jarDir.listFiles(new FileFilter() {
1682

    
1683
                    public boolean accept(File pathname) {
1684
                        return (pathname.getName().toUpperCase()
1685
                            .endsWith(".JAR"))
1686
                            || (pathname.getName().toUpperCase()
1687
                                .endsWith(".ZIP"));
1688
                    }
1689
                });
1690

    
1691
                URL[] urls = new URL[jarFiles.length];
1692

    
1693
                for (int j = 0; j < jarFiles.length; j++) {
1694
                    try {
1695
                        urls[j] = new URL("file:" + jarFiles[j]);
1696
                    } catch (MalformedURLException e) {
1697
                        this.addError(Messages
1698
                            .getString("Launcher.No_se_puede_acceder_a")
1699
                            + " " + jarFiles[j]);
1700
                    }
1701
                }
1702

    
1703
                PluginClassLoader loader;
1704

    
1705
                try {
1706
                    loader =
1707
                        new PluginClassLoader(urls, andamiConfig
1708
                            .getPluginsDirectory()
1709
                            + File.separator + pluginName, Launcher.class
1710
                            .getClassLoader(), loaders);
1711

    
1712
                    PluginServices ps = new PluginServices(loader);
1713

    
1714
                    pluginsServices.put(ps.getPluginName(), ps);
1715

    
1716
                    installed.add(pluginName);
1717
                    // FJP: Los metemos ordenados para luego no cargar uno que
1718
                    // necesita de otro antes de tiempo. Esto lo usaremos al
1719
                    // inicializar los plugins
1720
                    pluginsOrdered.add(pluginName);
1721

    
1722
                    circle = false;
1723
                } catch (IOException e) {
1724
                    this
1725
                        .addError(
1726
                            Messages
1727
                                .getString("Launcher.Error_con_las_librerias_del_plugin"),
1728
                            e);
1729
                    pluginsConfig.remove(pluginName);
1730
                    i = pluginsConfig.keySet().iterator();
1731
                }
1732
            }
1733

    
1734
            if (circle) {
1735
                this.addError(Messages
1736
                    .getString("Launcher.Hay_dependencias_circulares"));
1737

    
1738
                break;
1739
            }
1740
        }
1741

    
1742
        // Se eliminan los plugins que no fueron instalados
1743
        Iterator<String> i = pluginsConfig.keySet().iterator();
1744

    
1745
        while (i.hasNext()) {
1746
            String pluginName = i.next();
1747
            PluginServices ps =
1748
                (PluginServices) pluginsServices.get(pluginName);
1749

    
1750
            if (ps == null) {
1751
                pluginsConfig.remove(pluginName);
1752
                i = pluginsConfig.keySet().iterator();
1753
            }
1754
        }
1755
    }
1756

    
1757
    private void pluginsMessages() {
1758
        Iterator<String> iterator = pluginsOrdered.iterator();
1759
        PluginConfig config;
1760
        PluginServices ps;
1761

    
1762
        while (iterator.hasNext()) {
1763
            String pluginName = iterator.next();
1764
            config = pluginsConfig.get(pluginName);
1765
            ps = pluginsServices.get(pluginName);
1766

    
1767
            if ((config.getResourceBundle() != null)
1768
                && !config.getResourceBundle().getName().equals("")) {
1769
                // add the locale files associated with the plugin
1770
                org.gvsig.i18n.Messages.addResourceFamily(config
1771
                    .getResourceBundle().getName(), ps.getClassLoader(),
1772
                    pluginName);
1773
            }
1774
        }
1775
    }
1776

    
1777
    static public PluginServices getPluginServices(String name) {
1778
        return (PluginServices) pluginsServices.get(name);
1779
    }
1780

    
1781
    static String getPluginsDir() {
1782
        return andamiConfig.getPluginsDirectory();
1783
    }
1784

    
1785
    static void setPluginsDir(String s) {
1786
        andamiConfig.setPluginsDirectory(s);
1787
    }
1788

    
1789
    static MDIFrame getMDIFrame() {
1790
        return frame;
1791
    }
1792

    
1793
    private void loadPlugins(String pluginsDirectory) {
1794
        File pDir = new File(pluginsDirectory);
1795

    
1796
        if (!pDir.exists()) {
1797
            logger
1798
                .error("\n\tPlugins directory not found: "
1799
                    + pDir.getAbsolutePath()
1800
                    + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1801
            System.exit(-1);
1802
            return;
1803
        }
1804

    
1805
        File[] pluginDirs = pDir.listFiles();
1806
        if (pluginDirs.length == 0) {
1807
            logger
1808
                .error("\n\tPlugins directory is empty: "
1809
                    + pDir.getAbsolutePath()
1810
                    + "Did you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1811
            System.exit(-1);
1812
            return;
1813
        }
1814

    
1815
        for (int i = 0; i < pluginDirs.length; i++) {
1816
            if (pluginDirs[i].isDirectory()) {
1817
                File configXml =
1818
                    new File(pluginDirs[i].getAbsolutePath(), "config.xml");
1819

    
1820
                try {
1821
                    FileInputStream is = new FileInputStream(configXml);
1822
                    Reader xml =
1823
                        org.gvsig.utils.xml.XMLEncodingUtils.getReader(is);
1824
                    if (xml == null) {
1825
                        // the encoding was not correctly detected, use system
1826
                        // default
1827
                        xml = new FileReader(configXml);
1828
                    } else {
1829
                        // use a buffered reader to improve performance
1830
                        xml = new BufferedReader(xml);
1831
                    }
1832
                    PluginConfig pConfig =
1833
                        (PluginConfig) PluginConfig.unmarshal(xml);
1834
                    pluginsConfig.put(pluginDirs[i].getName(), pConfig);
1835
                } catch (FileNotFoundException e) {
1836
                    logger
1837
                        .info("Plugin folder without config.xml. Skip plugin '"
1838
                            + pluginDirs[i].getAbsolutePath() + "'.");
1839
                } catch (MarshalException e) {
1840
                    this.addError("Can't load plugin '"
1841
                        + pluginDirs[i].getAbsolutePath() + "'.", e);
1842
                } catch (ValidationException e) {
1843
                    this.addError("Can't load plugin '"
1844
                        + pluginDirs[i].getAbsolutePath() + "'.", e);
1845
                }
1846
            }
1847
        }
1848

    
1849
        if (pluginsConfig.size() == 0) {
1850
            logger
1851
                .error("No valid plugin was found. The plugins directory currently is: "
1852
                    + pDir.getAbsolutePath()
1853
                    + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1854
            System.exit(-1);
1855
            return;
1856
        }
1857
    }
1858

    
1859
    private static Locale getLocale(String language, String country,
1860
        String variant) {
1861
        if (variant != null) {
1862
            return new Locale(language, country, variant);
1863
        } else
1864
            if (country != null) {
1865
                return new Locale(language, country);
1866
            } else
1867
                if (language != null) {
1868
                    return new Locale(language);
1869
                } else {
1870
                    return new Locale("es");
1871
                }
1872
    }
1873

    
1874
    private static void andamiConfigToXML(String file) throws IOException,
1875
        MarshalException, ValidationException {
1876
        // write on a temporary file in order to not destroy current file if
1877
        // there is some problem while marshaling
1878
        File tmpFile =
1879
            new File(file + "-" + DateTime.getCurrentDate().getTime());
1880
        File xml = new File(file);
1881
        File parent = xml.getParentFile();
1882
        parent.mkdirs();
1883

    
1884
        BufferedOutputStream os =
1885
            new BufferedOutputStream(new FileOutputStream(tmpFile));
1886
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
1887
        andamiConfig.marshal(writer);
1888
        writer.close();
1889

    
1890
        // if marshaling process finished correctly, move the file to the
1891
        // correct one
1892
        xml.delete();
1893
        if (!tmpFile.renameTo(xml)) {
1894
            // if rename was not succesful, try copying it
1895
            FileChannel sourceChannel =
1896
                new FileInputStream(tmpFile).getChannel();
1897
            FileChannel destinationChannel =
1898
                new FileOutputStream(xml).getChannel();
1899
            sourceChannel.transferTo(0, sourceChannel.size(),
1900
                destinationChannel);
1901
            sourceChannel.close();
1902
            destinationChannel.close();
1903
        }
1904
    }
1905

    
1906
    private static void andamiConfigFromXML(String file)
1907
        throws ConfigurationException {
1908
        File xml = new File(file);
1909

    
1910
        InputStreamReader reader = null;
1911
        try {
1912
            // Se lee la configuraci?n
1913
            reader = XMLEncodingUtils.getReader(xml);
1914
            andamiConfig = (AndamiConfig) AndamiConfig.unmarshal(reader);
1915
        } catch (FileNotFoundException e) {
1916
            // Si no existe se ponen los valores por defecto
1917
            andamiConfig = getDefaultAndamiConfig();
1918
        } catch (MarshalException e) {
1919
            // try to close the stream, maybe it remains open
1920
            if (reader != null) {
1921
                try {
1922
                    reader.close();
1923
                } catch (IOException e1) {
1924
                }
1925
            }
1926
            // if there was a problem reading the file, backup it and create a
1927
            // new one with default values
1928
            String backupFile =
1929
                file + "-" + DateTime.getCurrentDate().getTime();
1930
            NotificationManager
1931
                .addError(
1932
                    Messages
1933
                        .getString("Error_reading_andami_config_New_file_created_A_backup_was_made_on_")
1934
                        + backupFile, new ConfigurationException(e));
1935
            xml.renameTo(new File(backupFile));
1936
            andamiConfig = getDefaultAndamiConfig();
1937
        } catch (ValidationException e) {
1938
            throw new ConfigurationException(e);
1939
        }
1940
    }
1941

    
1942
    private static AndamiConfig getDefaultAndamiConfig() {
1943
        AndamiConfig andamiConfig = new AndamiConfig();
1944

    
1945
        Andami andami = new Andami();
1946
        andami.setUpdate(true);
1947
        andamiConfig.setAndami(andami);
1948
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
1949
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
1950
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
1951

    
1952
        if (System.getProperty("javawebstart.version") != null) // Es java web
1953
        // start)
1954
        {
1955
            andamiConfig
1956
                .setPluginsDirectory(new File(appHomeDir, "extensiones")
1957
                    .getAbsolutePath());
1958
        } else {
1959
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
1960
                .getAbsolutePath());
1961
        }
1962

    
1963
        andamiConfig.setPlugin(new Plugin[0]);
1964
        return andamiConfig;
1965
    }
1966

    
1967
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
1968
        File xml = getPluginsPersistenceFile(true);
1969

    
1970
        if (xml.exists()) {
1971
            InputStreamReader reader = null;
1972

    
1973
            try {
1974
                reader = XMLEncodingUtils.getReader(xml);
1975
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1976
                return new XMLEntity(tag);
1977
            } catch (FileNotFoundException e) {
1978
                throw new ConfigurationException(e);
1979
            } catch (MarshalException e) {
1980

    
1981
                // try to reopen with default encoding (for backward
1982
                // compatibility)
1983
                try {
1984
                    reader = new FileReader(xml);
1985
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1986
                    return new XMLEntity(tag);
1987

    
1988
                } catch (MarshalException ex) {
1989
                    // try to close the stream, maybe it remains open
1990
                    if (reader != null) {
1991
                        try {
1992
                            reader.close();
1993
                        } catch (IOException e1) {
1994
                        }
1995
                    }
1996
                    // backup the old file
1997
                    String backupFile =
1998
                        getPluginsPersistenceFile(true).getPath() + "-"
1999
                            + DateTime.getCurrentDate().getTime();
2000
                    NotificationManager
2001
                        .addError(
2002
                            Messages
2003
                                .getString("Error_reading_plugin_persinstence_New_file_created_A_backup_was_made_on_")
2004
                                + backupFile, new ConfigurationException(e));
2005
                    xml.renameTo(new File(backupFile));
2006
                    // create a new, empty configuration
2007
                    return new XMLEntity();
2008
                } catch (FileNotFoundException ex) {
2009
                    return new XMLEntity();
2010
                } catch (ValidationException ex) {
2011
                    throw new ConfigurationException(e);
2012
                }
2013
            } catch (ValidationException e) {
2014
                throw new ConfigurationException(e);
2015
            }
2016
        } else {
2017
            return new XMLEntity();
2018
        }
2019
    }
2020

    
2021
    private static File getPluginsPersistenceFile(boolean read) {
2022
        if (read) {
2023
            File pluginsPersistenceFile =
2024
                new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2025
            if (pluginsPersistenceFile.exists()) {
2026
                return pluginsPersistenceFile;
2027
            }
2028
            pluginsPersistenceFile =
2029
                new File(getAppHomeDir(), "plugins-persistence.xml");
2030
            if (pluginsPersistenceFile.exists()) {
2031
                return pluginsPersistenceFile;
2032
            }
2033
        }
2034
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2035

    
2036
    }
2037

    
2038
    private static void persistenceToXML(XMLEntity entity)
2039
        throws ConfigurationException {
2040
        // write on a temporary file in order to not destroy current file if
2041
        // there is some problem while marshaling
2042
        File tmpFile =
2043
            new File(getPluginsPersistenceFile(false).getPath() + "-"
2044
                + DateTime.getCurrentDate().getTime());
2045

    
2046
        File xml = getPluginsPersistenceFile(false);
2047
        OutputStreamWriter writer = null;
2048

    
2049
        try {
2050
            writer =
2051
                new OutputStreamWriter(new FileOutputStream(tmpFile),
2052
                    CASTORENCODING);
2053
            entity.getXmlTag().marshal(writer);
2054
            writer.close();
2055

    
2056
            // if marshaling process finished correctly, move the file to the
2057
            // correct one
2058
            xml.delete();
2059
            if (!tmpFile.renameTo(xml)) {
2060
                // if rename was not succesful, try copying it
2061
                FileChannel sourceChannel =
2062
                    new FileInputStream(tmpFile).getChannel();
2063
                FileChannel destinationChannel =
2064
                    new FileOutputStream(xml).getChannel();
2065
                sourceChannel.transferTo(0, sourceChannel.size(),
2066
                    destinationChannel);
2067
                sourceChannel.close();
2068
                destinationChannel.close();
2069

    
2070
            }
2071
        } catch (FileNotFoundException e) {
2072
            throw new ConfigurationException(e);
2073
        } catch (MarshalException e) {
2074
            // try to close the stream, maybe it remains open
2075
            if (writer != null) {
2076
                try {
2077
                    writer.close();
2078
                } catch (IOException e1) {
2079
                }
2080
            }
2081
        } catch (ValidationException e) {
2082
            throw new ConfigurationException(e);
2083
        } catch (IOException e) {
2084
            throw new ConfigurationException(e);
2085
        }
2086
    }
2087

    
2088
    static MDIFrame getFrame() {
2089
        return frame;
2090
    }
2091

    
2092
    /**
2093
     * Gracefully closes the application. It shows dialogs to save data,
2094
     * finish processes, etc, then it terminates the extensions, removes
2095
     * temporal files and finally exits.
2096
     */
2097
    public synchronized static void closeApplication() {
2098
        TerminationProcess terminationProcess =
2099
            (new Launcher()).new TerminationProcess();
2100
        terminationProcess.run();
2101
    }
2102

    
2103
    static HashMap getClassesExtensions() {
2104
        return classesExtensions;
2105
    }
2106

    
2107
    private static Extensions[] getExtensions() {
2108
        List<Extensions> array = new ArrayList<Extensions>();
2109
        Iterator<PluginConfig> iter = pluginsConfig.values().iterator();
2110

    
2111
        while (iter.hasNext()) {
2112
            array.add(iter.next().getExtensions());
2113
        }
2114

    
2115
        return array.toArray(new Extensions[array.size()]);
2116
    }
2117

    
2118
    public static Iterator getExtensionIterator() {
2119
        return extensions.iterator();
2120
    }
2121

    
2122
    public static HashMap getPluginConfig() {
2123
        return pluginsConfig;
2124
    }
2125

    
2126
    public static Extension getExtension(String s) {
2127
        Extensions[] exts = getExtensions();
2128

    
2129
        for (int i = 0; i < exts.length; i++) {
2130
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2131
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2132
                    return exts[i].getExtension(j);
2133
                }
2134
            }
2135
        }
2136

    
2137
        return null;
2138
    }
2139

    
2140
    public static AndamiConfig getAndamiConfig() {
2141
        return andamiConfig;
2142
    }
2143

    
2144
    private static class ExtensionComparator implements Comparator {
2145

    
2146
        public int compare(Object o1, Object o2) {
2147
            Extension e1 = (Extension) o1;
2148
            Extension e2 = (Extension) o2;
2149

    
2150
            if (!e1.hasPriority() && !e2.hasPriority()) {
2151
                return -1;
2152
            }
2153

    
2154
            if (e1.hasPriority() && !e2.hasPriority()) {
2155
                return Integer.MIN_VALUE;
2156
            }
2157

    
2158
            if (e2.hasPriority() && !e1.hasPriority()) {
2159
                return Integer.MAX_VALUE;
2160
            }
2161

    
2162
            if (e1.getPriority() != e2.getPriority()) {
2163
                return e2.getPriority() - e1.getPriority();
2164
            } else {
2165
                return (e2.toString().compareTo(e1.toString()));
2166
            }
2167
        }
2168
    }
2169

    
2170
    private static class MenuComparator implements Comparator<SortableMenu> {
2171

    
2172
        private static ExtensionComparator extComp = new ExtensionComparator();
2173

    
2174
        public int compare(SortableMenu e1, SortableMenu e2) {
2175

    
2176
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2177
                if (e1.extension instanceof SkinExtensionType) {
2178
                    return 1;
2179
                } else
2180
                    if (e2.extension instanceof SkinExtensionType) {
2181
                        return -1;
2182
                    } else {
2183
                        return extComp.compare(e1.extension, e2.extension);
2184
                    }
2185
            }
2186

    
2187
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2188
                return Integer.MIN_VALUE;
2189
            }
2190

    
2191
            if (e2.menu.hasPosition() && !e1.menu.hasPosition()) {
2192
                return Integer.MAX_VALUE;
2193
            }
2194
            if (e1.menu.getPosition() != e2.menu.getPosition()) {
2195
                // we don't return 0 unless both objects are the same, otherwise
2196
                // the objects get overwritten in the treemap
2197
                return e1.menu.getPosition() - e2.menu.getPosition();
2198
            } else {
2199
                return (e1.toString().compareTo(e2.toString()));
2200
            }
2201
        }
2202
    }
2203

    
2204
    private static class SortableMenu {
2205

    
2206
        public PluginClassLoader loader;
2207
        public Menu menu;
2208
        public SkinExtensionType extension;
2209

    
2210
        public SortableMenu(PluginClassLoader loader,
2211
            SkinExtensionType skinExt, Menu menu2) {
2212
            extension = skinExt;
2213
            menu = menu2;
2214
            this.loader = loader;
2215
        }
2216
    }
2217

    
2218
    private static class SortableTool {
2219

    
2220
        public PluginClassLoader loader;
2221
        public ToolBar toolbar;
2222
        public ActionTool actiontool;
2223
        public SelectableTool selectabletool;
2224
        public SkinExtensionType extension;
2225

    
2226
        public SortableTool(PluginClassLoader loader,
2227
            SkinExtensionType skinExt, ToolBar toolbar2, ActionTool actiontool2) {
2228
            extension = skinExt;
2229
            toolbar = toolbar2;
2230
            actiontool = actiontool2;
2231
            this.loader = loader;
2232
        }
2233

    
2234
        public SortableTool(PluginClassLoader loader,
2235
            SkinExtensionType skinExt, ToolBar toolbar2,
2236
            SelectableTool selectabletool2) {
2237
            extension = skinExt;
2238
            toolbar = toolbar2;
2239
            selectabletool = selectabletool2;
2240
            this.loader = loader;
2241
        }
2242
    }
2243

    
2244
    private static class ToolBarComparator implements Comparator<SortableTool> {
2245

    
2246
        private static ExtensionComparator extComp = new ExtensionComparator();
2247

    
2248
        public int compare(SortableTool e1, SortableTool e2) {
2249

    
2250
            // if the toolbars have the same name, they are considered to be
2251
            // the same toolbar, so we don't need to do further comparing
2252
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2253
                return 0;
2254
            }
2255

    
2256
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2257
                if (e1.extension instanceof SkinExtensionType) {
2258
                    return 1;
2259
                } else
2260
                    if (e2.extension instanceof SkinExtensionType) {
2261
                        return -1;
2262
                    } else {
2263
                        return extComp.compare(e1.extension, e2.extension);
2264
                    }
2265
            }
2266

    
2267
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2268
                return Integer.MIN_VALUE;
2269
            }
2270

    
2271
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2272
                return Integer.MAX_VALUE;
2273
            }
2274
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2275
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2276
            }
2277

    
2278
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2279
                && e1.toolbar.getSelectableTool().equals(
2280
                    e2.toolbar.getSelectableTool())) {
2281
                return 0;
2282
            }
2283
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2284
        }
2285
    }
2286

    
2287
    /**
2288
     * <p>
2289
     * This class is used to compare tools (selectabletool and actiontool),
2290
     * using the "position" attribute.
2291
     * </p>
2292
     * <p>
2293
     * The ordering criteria are:
2294
     * </p>
2295
     * <ul>
2296
     * <li>If the tools are placed in different toolbars, they use the toolbars'
2297
     * order. (using the ToolBarComparator).</li>
2298
     * <li></li>
2299
     * <li>If any of the tools has not 'position' attribute, the tool which
2300
     * <strong>has</strong> the attribute will be placed first.</li>
2301
     * <li>If both tools have the same position (or they don't have a 'position'
2302
     * attribute), the priority of the extensions where the tool is defined.</li>
2303
     * </ul>
2304
     * 
2305
     * @author cesar
2306
     * @version $Revision: 37231 $
2307
     */
2308
    private static class ToolComparator implements Comparator<SortableTool> {
2309

    
2310
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2311

    
2312
        public int compare(SortableTool e1, SortableTool e2) {
2313
            // compare the toolbars which contain the tools
2314
            int result = toolBarComp.compare(e1, e2);
2315
            if (result != 0) { // if the toolbars are different, use their order
2316
                return result;
2317
            }
2318
            // otherwise, compare the tools
2319
            int e1Position = -1, e2Position = -1;
2320

    
2321
            if (e1.actiontool != null) {
2322
                if (e1.actiontool.hasPosition()) {
2323
                    e1Position = e1.actiontool.getPosition();
2324
                }
2325
            } else
2326
                if (e1.selectabletool != null) {
2327
                    if (e1.selectabletool.hasPosition()) {
2328
                        e1Position = e1.selectabletool.getPosition();
2329
                    }
2330
                }
2331

    
2332
            if (e2.actiontool != null) {
2333
                if (e2.actiontool.hasPosition()) {
2334
                    e2Position = e2.actiontool.getPosition();
2335
                }
2336
            } else
2337
                if (e2.selectabletool != null) {
2338
                    if (e2.selectabletool.hasPosition()) {
2339
                        e2Position = e2.selectabletool.getPosition();
2340
                    }
2341
                }
2342

    
2343
            if ((e1Position == -1) && (e2Position != -1)) {
2344
                return 1;
2345
            }
2346
            if ((e1Position != -1) && (e2Position == -1)) {
2347
                return -1;
2348
            }
2349
            if ((e1Position != -1) && (e2Position != -1)) {
2350
                result = e1Position - e2Position;
2351
                // we don't return 0 unless both objects are the same, otherwise
2352
                // the objects get overwritten in the treemap
2353
                if (result != 0) {
2354
                    return result;
2355
                }
2356
            }
2357
            return e1.toString().compareTo(e2.toString());
2358
        }
2359
    }
2360

    
2361
    /**
2362
     * validates the user before starting gvsig
2363
     * 
2364
     */
2365
    private static void validate() {
2366

    
2367
        IAuthentication session = null;
2368
        try {
2369
            session =
2370
                (IAuthentication) Class.forName(
2371
                    "com.iver.andami.authentication.Session").newInstance();
2372

    
2373
        } catch (ClassNotFoundException e) {
2374
            return;
2375
        } catch (InstantiationException e) {
2376
            return;
2377
        } catch (IllegalAccessException e) {
2378
            return;
2379
        }
2380

    
2381
        session.setPluginDirectory(andamiConfig.getPluginsDirectory());
2382
        if (session.validationRequired()) {
2383
            if (session.Login()) {
2384
                logger.info("You are logged in");
2385
            } else {
2386
                JOptionPane.showMessageDialog((Component) PluginServices
2387
                    .getMainFrame(), "You are not logged in");
2388
            }
2389
            PluginServices.setAuthentication(session);
2390
        }
2391
    }
2392

    
2393
    public static String getDefaultLookAndFeel() {
2394
        String osName = (String) System.getProperty("os.name");
2395

    
2396
        if ((osName.length() > 4)
2397
            && osName.substring(0, 5).toLowerCase().equals("linux")) {
2398
            return nonWinDefaultLookAndFeel;
2399
        }
2400
        if (osName.toLowerCase().startsWith("mac os x")) {
2401
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
2402
        }
2403

    
2404
        return UIManager.getSystemLookAndFeelClassName();
2405
    }
2406

    
2407
    /**
2408
     * Gets the ISO 839 two-characters-long language code matching the
2409
     * provided language code (which may be an ISO 839-2/T
2410
     * three-characters-long code or an ISO 839-1 two-characters-long
2411
     * code).
2412
     * 
2413
     * If the provided parameter is already two characters long, it
2414
     * returns the parameter without any modification.
2415
     * 
2416
     * @param langCode
2417
     *            A language code representing either
2418
     *            an ISO 839-2/T language code or an ISO 839-1 code.
2419
     * @return A two-characters-long code specifying
2420
     *         an ISO 839 language code.
2421
     */
2422
    private static String normalizeLanguageCode(String langCode) {
2423
        final String fileName = "iso_639.tab";
2424
        if (langCode.length() == 2) {
2425
            return langCode;
2426
        } else
2427
            if (langCode.length() == 3) {
2428
                if (langCode.equals("va") || langCode.equals("val")) { // special
2429
                    // case
2430
                    // for
2431
                    // Valencian
2432
                    return "ca";
2433
                }
2434
                URL isoCodes =
2435
                    Launcher.class.getClassLoader().getResource(fileName);
2436
                if (isoCodes != null) {
2437
                    try {
2438
                        BufferedReader reader =
2439
                            new BufferedReader(new InputStreamReader(isoCodes
2440
                                .openStream(), "ISO-8859-1"));
2441
                        String line;
2442

    
2443
                        while ((line = reader.readLine()) != null) {
2444
                            String[] language = line.split("\t");
2445
                            if (language[0].equals(langCode)) {
2446
                                // the three
2447
                                // characters code
2448
                                return language[2]; // third column i the two
2449
                                // characters code
2450
                            }
2451
                        }
2452
                    } catch (IOException ex) {
2453
                        logger.error(Messages
2454
                            .getString("Error_reading_isocodes_file"), ex);
2455
                        return "es";
2456
                    }
2457
                } else {
2458
                    logger.error(Messages
2459
                        .getString("Error_reading_isocodes_file"));
2460
                    return "es";
2461
                }
2462
            }
2463
        return "es";
2464
    }
2465

    
2466
    /**
2467
     * Configures the locales (languages and local resources) to be used
2468
     * by the application.
2469
     * 
2470
     * First it tries to get the locale from the command line parameters,
2471
     * then the andami-config file is checked.
2472
     * 
2473
     * The locale name is normalized to get a two characters language code
2474
     * as defined by ISO-639-1 (although ISO-639-2/T three characters codes
2475
     * are also accepted from the command line or the configuration file).
2476
     * 
2477
     * Finally, the gvsig-i18n library and the default locales for Java and
2478
     * Swing are configured.
2479
     * 
2480
     */
2481
    private static void configureLocales(String[] args) {
2482
        // Configurar el locale
2483
        String localeStr = null;
2484
        /*
2485
         * for (int i=2; i < args.length; i++)
2486
         * {
2487
         * int index = args[i].indexOf("language=");
2488
         * if (index != -1)
2489
         * localeStr = args[i].substring(index+9);
2490
         * }
2491
         */
2492
        localeStr = PluginServices.getArgumentByName("language");
2493
        if (localeStr == null) {
2494
            localeStr = andamiConfig.getLocaleLanguage();
2495
        }
2496
        localeStr = normalizeLanguageCode(localeStr);
2497
        locale =
2498
            getLocale(localeStr, andamiConfig.getLocaleCountry(), andamiConfig
2499
                .getLocaleVariant());
2500
        Locale.setDefault(locale);
2501
        JComponent.setDefaultLocale(locale);
2502
        org.gvsig.i18n.Messages.addLocale(locale);
2503
        // add english and spanish as fallback languages
2504
        if (localeStr.equals("es") || localeStr.equals("ca")
2505
            || localeStr.equals("gl") || localeStr.equals("eu")
2506
            || localeStr.equals("va")) {
2507
            // prefer Spanish for languages spoken in Spain
2508
            org.gvsig.i18n.Messages.addLocale(new Locale("es"));
2509
            org.gvsig.i18n.Messages.addLocale(new Locale("en"));
2510
        } else {
2511
            // prefer English for the rest
2512
            org.gvsig.i18n.Messages.addLocale(new Locale("en"));
2513
            org.gvsig.i18n.Messages.addLocale(new Locale("es"));
2514
        }
2515
        org.gvsig.i18n.Messages.addResourceFamily("org.gvsig.andami.text",
2516
            "org.gvsig.andami.text");
2517

    
2518
    }
2519

    
2520
    /**
2521
     * Gets Home Directory location of the application into users home folder.
2522
     * 
2523
     * May be set from outside the aplication by means of
2524
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name
2525
     * of the application
2526
     * 
2527
     * @return
2528
     */
2529
    public static String getAppHomeDir() {
2530
        return appHomeDir;
2531
    }
2532

    
2533
    /**
2534
     * Sets Home Directory location of the application.
2535
     * May be set from outside the aplication by means of
2536
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name
2537
     * of the application
2538
     * 
2539
     * @param appHomeDir
2540
     */
2541
    public static void setAppHomeDir(String appHomeDir) {
2542
        Launcher.appHomeDir = appHomeDir;
2543
    }
2544

    
2545
    /**
2546
     * Initialize the extesion that have to take the control
2547
     * of the state of action controls of the UI of all extensions. <br>
2548
     * <br>
2549
     * For use this option you have to add an argument
2550
     * to the command line like this: <br>
2551
     * <br>
2552
     * -exclusiveUI={pathToExtensionClass} <br>
2553
     * 
2554
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
2555
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
2556
     */
2557
    private static void initializeExclusiveUIExtension() {
2558
        String name = PluginServices.getArgumentByName("exclusiveUI");
2559
        if (name == null) {
2560
            return;
2561
        }
2562

    
2563
        Iterator<Class<? extends IExtension>> iter =
2564
            classesExtensions.keySet().iterator();
2565
        int charIndex;
2566
        Class<? extends IExtension> key;
2567
        while (iter.hasNext()) {
2568
            key = iter.next();
2569
            charIndex = key.getName().indexOf(name);
2570
            // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex);
2571
            if (charIndex == 0) {
2572
                IExtension ext = classesExtensions.get(key);
2573
                if (ext instanceof ExtensionDecorator) {
2574
                    ext = ((ExtensionDecorator) ext).getExtension();
2575
                }
2576
                if (ext instanceof ExclusiveUIExtension) {
2577
                    PluginServices
2578
                        .setExclusiveUIExtension((ExclusiveUIExtension) ext);
2579
                }
2580
                break;
2581
            }
2582
        }
2583

    
2584
        logger
2585
            .error(Messages
2586
                .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
2587
                + " '" + name + "'");
2588
    }
2589

    
2590
    // public static void initIconThemes() {
2591
    // // load the iconTheme
2592
    // IconThemeManager iconManager = new IconThemeManager();
2593
    // PluginServices.setIconThemeManager(iconManager);
2594
    // IconThemeInfo selectedTheme = iconManager.readConfig();
2595
    // if (selectedTheme!=null) {
2596
    // iconManager.setDefault(selectedTheme);
2597
    // logger.info("Setting the icon theme: "+selectedTheme.toVerboseString());
2598
    // }
2599
    // else {
2600
    // // set the default dir and try to load the default theme
2601
    // try {
2602
    // iconManager.setThemesDir(new File("iconThemes"));
2603
    // IconThemeInfo[] list = iconManager.list();
2604
    //
2605
    // for (int i=0; i<list.length; i++) {
2606
    // if (list[i].getResourceName().equals("iconThemes/icons")) {
2607
    // iconManager.setDefault(list[i]);
2608
    // logger.info("Setting the default icon theme: "+list[i].toVerboseString());
2609
    // return;
2610
    // }
2611
    // }
2612
    // } catch (FileNotFoundException e) {
2613
    // logger.info("IconTheme basedir does not exist");
2614
    // }
2615
    // // create an empty theme
2616
    // IconThemeInfo info = new IconThemeInfo();
2617
    // info.setName("No theme loaded");
2618
    // info.setResource(null); // null resource means that no real theme is
2619
    // loaded
2620
    // info.setDescription("No theme loaded");
2621
    // info.setVersion("0");
2622
    // iconManager.setDefault(new IconTheme(info));
2623
    // logger.info("Setting an empty icon theme");
2624
    //
2625
    // }
2626
    // }
2627

    
2628
    public static void initIconThemes() {
2629
        IconThemeManager iconManager = IconThemeManager.getIconThemeManager();
2630
        IIconTheme icontheme = iconManager.getIconThemeFromConfig();
2631
        if (icontheme != null) {
2632
            iconManager.setCurrent(icontheme);
2633
        }
2634
    }
2635

    
2636
    /**
2637
     * Manages Andami termination process
2638
     * 
2639
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
2640
     */
2641
    public class TerminationProcess {
2642

    
2643
        private boolean proceed = false;
2644
        private UnsavedDataPanel panel = null;
2645

    
2646
        public void run() {
2647
            int exit = manageUnsavedData();
2648
            if ((exit == JOptionPane.NO_OPTION)
2649
                || (exit == JOptionPane.CLOSED_OPTION)) {
2650
                // the user doesn't want to exit
2651
                return;
2652
            }
2653

    
2654
            closeAndami();
2655
        }
2656

    
2657
        /**
2658
         * Finishes the application without asking user if want or not to save
2659
         * unsaved data.
2660
         */
2661
        public void closeAndami() {
2662
            try {
2663
                saveAndamiConfig();
2664
            } catch(Exception ex) {
2665
                logger.error("There was an error exiting application, can't save andami-config.xml", ex);
2666
            }
2667

    
2668
            
2669
            try {
2670
                // Persistencia de los plugins
2671
                savePluginPersistence();
2672
                savePluginsProperties();
2673
            } catch(Exception ex) {
2674
                logger.error("There was an error exiting application, can't save plugins properties", ex);
2675
            }
2676

    
2677
            // Finalize all the extensions
2678
            finalizeExtensions();
2679

    
2680
            try {
2681
                // Clean any temp data created
2682
                Utilities.cleanUpTempFiles();
2683
            } catch(Exception ex) {
2684
                logger.error("There was an error exiting application, can't remove temporary files", ex);
2685
            }
2686

    
2687
            logger.info("Quiting application.");
2688
            
2689
            // Para la depuraci?n de memory leaks
2690
            System.gc();
2691

    
2692
            System.exit(0);
2693
        }
2694

    
2695
        /**
2696
         * 
2697
         */
2698
        public void saveAndamiConfig() {
2699
            // Configuraci?n de Andami
2700
            try {
2701
                andamiConfigToXML(andamiConfigPath);
2702
            } catch (MarshalException e) {
2703
                logger
2704
                    .error(
2705
                        Messages
2706
                            .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2707
                        e);
2708
            } catch (ValidationException e) {
2709
                logger
2710
                    .error(
2711
                        Messages
2712
                            .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2713
                        e);
2714
            } catch (IOException e) {
2715
                logger
2716
                    .error(
2717
                        Messages
2718
                            .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2719
                        e);
2720
            }
2721
        }
2722

    
2723
        private void savePluginsProperties() {
2724
            PluginsManager manager = PluginsLocator.getManager();
2725
            List<PluginServices> plugins = manager.getPlugins();
2726
            for (PluginServices plugin : plugins) {
2727
                if (plugin != null) {
2728
                    plugin.savePluginProperties();
2729
                }
2730
            }
2731
        }
2732

    
2733
        /**
2734
         * Exectutes the terminate method for all the extensions, in the reverse
2735
         * order they were initialized
2736
         * 
2737
         */
2738
        private void finalizeExtensions() {
2739
            for (int i = extensions.size() - 1; i >= 0; i--) {
2740
                org.gvsig.andami.plugins.IExtension extensionInstance =
2741
                    (org.gvsig.andami.plugins.IExtension) extensions.get(i);
2742
                String extensionName = "(unknow)";
2743
                try {
2744
                    extensionName = extensionInstance.getClass().getName();
2745
                    extensionInstance.terminate();
2746
                } catch(Exception ex) {
2747
                    logger.error(
2748
                        MessageFormat.format("There was an error extension ending {0}", extensionName),
2749
                        ex);
2750
                }
2751
            }
2752
        }
2753

    
2754
        private IUnsavedData[] getUnsavedData() {
2755
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
2756
            IExtension exclusiveExtension =
2757
                PluginServices.getExclusiveUIExtension();
2758

    
2759
            for (int i = extensions.size() - 1; i >= 0; i--) {
2760
                org.gvsig.andami.plugins.IExtension extensionInstance =
2761
                    (org.gvsig.andami.plugins.IExtension) extensions.get(i);
2762
                IExtensionStatus status = null;
2763
                if (exclusiveExtension != null) {
2764
                    status = exclusiveExtension.getStatus(extensionInstance);
2765
                } else {
2766
                    status = extensionInstance.getStatus();
2767
                }
2768
                if (status != null) {
2769
                    if (status.hasUnsavedData()) {
2770
                        IUnsavedData[] array = status.getUnsavedData();
2771
                        for (int element = 0; element < array.length; element++) {
2772
                            unsavedDataList.add(array[element]);
2773
                        }
2774
                    }
2775
                }
2776
            }
2777
            return unsavedDataList.toArray(new IUnsavedData[unsavedDataList
2778
                .size()]);
2779
        }
2780

    
2781
        public UnsavedDataPanel getUnsavedDataPanel() {
2782
            if (panel == null) {
2783
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
2784
            }
2785
            return panel;
2786
        }
2787

    
2788
        /**
2789
         * Checks if the extensions have some unsaved data, and shows a dialog
2790
         * to allow saving it. This dialog also allows to don't exit Andami.
2791
         * 
2792
         * @return true if the user confirmed he wishes to exit, false otherwise
2793
         */
2794
        public int manageUnsavedData() {
2795
            IUnsavedData[] unsavedData = getUnsavedData();
2796

    
2797
            // there was no unsaved data
2798
            if (unsavedData.length == 0) {
2799
                int option =
2800
                    JOptionPane
2801
                        .showConfirmDialog(frame, Messages
2802
                            .getString("MDIFrame.quiere_salir"), Messages
2803
                            .getString("MDIFrame.salir"),
2804
                            JOptionPane.YES_NO_OPTION);
2805
                return option;
2806
            }
2807

    
2808
            UnsavedDataPanel panel = getUnsavedDataPanel();
2809
            panel.setUnsavedDataArray(unsavedData);
2810

    
2811
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
2812

    
2813
                public void cancel(UnsavedDataPanel panel) {
2814
                    proceed(false);
2815
                    PluginServices.getMDIManager().closeWindow(panel);
2816

    
2817
                }
2818

    
2819
                public void discard(UnsavedDataPanel panel) {
2820
                    proceed(true);
2821
                    PluginServices.getMDIManager().closeWindow(panel);
2822

    
2823
                }
2824

    
2825
                public void accept(UnsavedDataPanel panel) {
2826
                    IUnsavedData[] unsavedDataArray =
2827
                        panel.getSelectedsUnsavedData();
2828
                    boolean saved;
2829
                    for (int i = 0; i < unsavedDataArray.length; i++) {
2830
                        try {
2831
                            saved = unsavedDataArray[i].saveData();
2832
                        } catch (Exception ex) {
2833
                            PluginServices
2834
                                .getLogger()
2835
                                .error(
2836
                                    "Error saving"
2837
                                        + unsavedDataArray[i].getResourceName(),
2838
                                    ex);
2839
                            saved = false;
2840
                        }
2841
                        if (!saved) {
2842
                            JOptionPane
2843
                                .showMessageDialog(
2844
                                    panel,
2845
                                    PluginServices
2846
                                        .getText(this,
2847
                                            "The_following_resource_could_not_be_saved_")
2848
                                        + "\n"
2849
                                        + unsavedDataArray[i].getResourceName()
2850
                                        + " -- "
2851
                                        + unsavedDataArray[i].getDescription(),
2852
                                    PluginServices.getText(this,
2853
                                        "Resource_was_not_saved"),
2854
                                    JOptionPane.ERROR_MESSAGE);
2855

    
2856
                            unsavedDataArray = getUnsavedData();
2857
                            panel.setUnsavedDataArray(unsavedDataArray);
2858
                            return;
2859
                        }
2860
                    }
2861
                    proceed(true);
2862
                    PluginServices.getMDIManager().closeWindow(panel);
2863
                }
2864
            });
2865

    
2866
            PluginServices.getMDIManager().addWindow(panel);
2867
            if (proceed) {
2868
                return JOptionPane.YES_OPTION;
2869
            } else {
2870
                return JOptionPane.NO_OPTION;
2871
            }
2872
        }
2873

    
2874
        private void proceed(boolean proceed) {
2875
            this.proceed = proceed;
2876
        }
2877

    
2878
    }
2879

    
2880
    public static TerminationProcess getTerminationProcess() {
2881
        return (new Launcher()).new TerminationProcess();
2882
    }
2883

    
2884
    /**
2885
     * Launch the gvSIG package installer.
2886
     * 
2887
     * @throws Exception
2888
     *             if there is any error
2889
     */
2890
    private void doInstall(String[] args) throws Exception {
2891
        String installURL = null;
2892
        if (args.length >= 4) {
2893
            String installURLParam = args[3];
2894
            if (installURLParam.startsWith("--installURL=")) {
2895
                installURL =
2896
                    installURLParam.substring("--installURL=".length());
2897
            }
2898
        }
2899

    
2900
        if (args.length < 3) {
2901
            System.err.println(Messages.get("usage")
2902
                + ": Launcher appName plugins-directory "
2903
                + "--install [--installURL=[URL]] [language=locale]");
2904
        }
2905

    
2906
        initializeApp(args);
2907
        initializeLibraries();
2908
        AndamiConfig config = getAndamiConfig();
2909
        config.setLocaleLanguage(locale.getLanguage());
2910
        config.setLocaleCountry(locale.getCountry());
2911
        config.setLocaleVariant(locale.getVariant());
2912

    
2913
        // Configure default index download URL
2914
        if (installURL != null) {
2915
            try {
2916
                SwingInstallerLocator.getSwingInstallerManager()
2917
                    .setDefaultDownloadURL(new URL(installURL));
2918
            } catch (MalformedURLException e) {
2919
                logger.error(
2920
                    "Error creating the default packages download URL pointing to"
2921
                        + installURL, e);
2922
            }
2923
        }
2924

    
2925
        // Launch installer
2926

    
2927
        PluginsManager manager = PluginsLocator.getManager();
2928
        AbstractInstallPackageWizard installPackageWizard =
2929
            SwingInstallerLocator.getSwingInstallerManager()
2930
                .createInstallPackageWizard(manager.getApplicationFolder(),
2931
                    manager.getPluginsFolder().getAbsoluteFile(),
2932
                    manager.getInstallFolder());
2933
        installPackageWizard
2934
            .setWizardActionListener(new InstallerWizardActionListener() {
2935

    
2936
                public void finish(InstallerWizardPanel installerWizard) {
2937
                    System.exit(0);
2938
                }
2939

    
2940
                public void cancel(InstallerWizardPanel installerWizard) {
2941
                    System.exit(0);
2942
                }
2943
            });
2944
        
2945
        // the wizard will show the Typical or Advanced mode option.
2946
        installPackageWizard.setAskTypicalOrCustom(true);
2947
        // default packages will be selected.
2948
        installPackageWizard.setSelectDefaultPackages(true);
2949
        
2950
        // 1. Create the frame.
2951
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
2952

    
2953
        // 2. What happens when the frame closes?
2954
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
2955
        Runtime.getRuntime().addShutdownHook(new Thread() {
2956

    
2957
            @Override
2958
            public void run() {
2959
                getTerminationProcess().saveAndamiConfig();
2960
            }
2961
        });
2962

    
2963
        // 3. Add the installer panel to the frame
2964
        frame.getContentPane().add(installPackageWizard, BorderLayout.CENTER);
2965

    
2966
        // 4. Size the frame and center on the screen
2967
        frame.pack();
2968
        frame.setLocationRelativeTo(null);
2969

    
2970
        // 5. Show it.
2971
        frame.setVisible(true);
2972
    }
2973
    
2974
        public static String getInformation() {
2975
                PluginsManager pluginmgr = PluginsLocator.getManager();
2976
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
2977

    
2978
                StringWriter writer = new StringWriter();
2979

    
2980
                Properties props = System.getProperties();
2981

    
2982
                // OS information
2983
                String osName = props.getProperty("os.name");
2984
                writer.write("OS\n");
2985
                writer.write("    name   : " + osName + "\n");
2986
                writer.write("    arch   : " + props.get("os.arch") + "\n");
2987
                writer.write("    version: " + props.get("os.version") + "\n");
2988
                if (osName.startsWith("Linux")) {
2989
                        try {
2990
                                String[] command = {"lsb_release", "-a"};
2991
                                Process p = Runtime.getRuntime().exec(command);
2992
                                InputStream is = p.getInputStream();
2993
                                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
2994
                                String line;
2995
                                while ( (line = reader.readLine()) != null) {
2996
                                        writer.write("    "+line+"\n");
2997
                                }
2998
                        } catch (Exception ex) {
2999
                                writer.write("Can't get detailled os information (lsb_release -a).");
3000
                        }
3001
                }
3002

    
3003
                // JRE information
3004
                writer.write("JRE\n");
3005
                writer.write("    vendor : " + props.get("java.vendor") + "\n");
3006
                writer.write("    version: " +props.get("java.version")+ "\n");
3007
                writer.write("    home   : " + props.get("java.home") + "\n");
3008

    
3009
                writer.write("HTTP Proxy\n");
3010
                writer.write("    http.proxyHost     : " + props.get("http.proxyHost") + "\n");
3011
                writer.write("    http.proxyPort     : " + props.get("http.proxyPort") + "\n");
3012
                writer.write("    http.proxyUserName : " + props.get("http.proxyUserName") + "\n");
3013
                writer.write("    http.proxyPassword : " + props.get("http.proxyPassword") + "\n");
3014
                
3015
                String skinName = "(unknow)";
3016
                try {
3017
                        skinName = MDIManagerFactory.getSkinExtension().getClassName();
3018
                } catch (Throwable e) {
3019
                        // Ignore
3020
                }
3021
                writer.write("Application\n");
3022
                writer.write("    locale language         : " + Launcher.getAndamiConfig().getLocaleLanguage()+ "\n");
3023
                writer.write("    application forlder     : " + pluginmgr.getApplicationFolder()+ "\n");
3024
                writer.write("    install forlder         : " + pluginmgr.getInstallFolder()+ "\n");
3025
                writer.write("    application home forlder: " + pluginmgr.getApplicationHomeFolder()+ "\n");
3026
                writer.write("    plugins forlder         : " + pluginmgr.getPluginsFolder()+ "\n");
3027
                writer.write("    theme                   : " + Launcher.theme.getSource()+ "\n");
3028
                writer.write("    Skin                    : " + skinName + "\n");
3029
                
3030
                
3031
                try {
3032
                        PackageInfo[] pkgs = installmgr.getInstalledPackages(pluginmgr.getPluginsFolder());
3033
                        writer.write("Installed packages\n");
3034
                        for( int i=0; i<pkgs.length; i++) {
3035
                                writer.write("    ");
3036
                                writer.write(pkgs[i].toStringCompact());
3037
                                writer.write("\n");
3038
                        }
3039
                } catch(Throwable e) {
3040
                        writer.write("Can't get installed package information.");
3041
                }
3042
                return writer.toString();
3043
        }
3044

    
3045
        private void logger_info(String msg) {
3046
                String info[] = msg.split("\n");
3047
                for (int i=0;i< info.length;i++) {
3048
                        logger.info(info[i]);
3049
                }
3050
        }
3051

    
3052

    
3053
}