Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / frameworks / _fwAndami / src / org / gvsig / andami / Launcher.java @ 37489

History | View | Annotate | Download (110 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.slf4j.Logger;
106
import org.slf4j.LoggerFactory;
107

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

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

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

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

    
211
    protected static ListBaseException launcherrors = null;
212

    
213
    protected static Theme theme = null;
214

    
215
    private static final class ProxyAuth extends Authenticator {
216

    
217
        private PasswordAuthentication auth;
218

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

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

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

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

    
252
    public static class LaunchException extends ListBaseException {
253

    
254
        private static final long serialVersionUID = 4541192746962684705L;
255

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

    
261
    }
262

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

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

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

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

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

    
286
        initializeApp(args);
287

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

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

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

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

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

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

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

    
344
        // 2.5. Initialize andami libraries
345
        splashWindow.process(25, PluginServices.getText(Launcher.class,
346
            "SplashWindow.initialize_andami_libraries"));
347
        new DefaultLibrariesInitializer().fullInitialize(true);
348
        logger.info("Dump system information");
349
        logger_info(getInformation());
350

    
351
        // 3. Se leen los config.xml de los plugins -----++++
352
        splashWindow.process(30, PluginServices.getText(Launcher.class,
353
            "SplashWindow.reading_plugins_config.xml"));
354
        try {
355
                logger.info("Load plugins information");
356
            this.loadPlugins(andamiConfig.getPluginsDirectory());
357
        } catch (Exception ex) {
358
            this.addError("Can't load plugins", ex);
359
        }
360

    
361
        // 4. Se configura el classloader del plugin
362
        splashWindow.process(40, PluginServices.getText(Launcher.class,
363
            "SplashWindow.setting_up_class_loaders"));
364
        try {
365
                logger.info("Configure plugins class loader");
366
            this.pluginsClassLoaders();
367
        } catch (Exception ex) {
368
            this.addError("Can't initialize plugin's classloaders  ", ex);
369
        }
370

    
371
        // 5. Initialize libraries
372
        splashWindow.process(50, PluginServices.getText(Launcher.class,
373
            "SplashWindow.initialize_libraries"));
374
        initializeLibraries();
375

    
376
        // 6. Se carga un Skin si alguno ide los plugins trae informaci?n
377
        // para ello
378
        splashWindow.process(60, PluginServices.getText(Launcher.class,
379
            "SplashWindow.looking_for_a_skin"));
380
        // skinPlugin( "com.iver.core.mdiManager.NewSkin");
381
        logger.info("Initialize skin");
382
        skinPlugin(null);
383
        
384
        // 7. Se configura la cola de eventos
385
        splashWindow.process(70,
386
            PluginServices.getText(Launcher.class,
387
            "setting_up_event_queue"));
388
        EventQueue waitQueue = new AndamiEventQueue();
389
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue);
390

    
391
        // 8. Se configura la mensajer?a del plugin
392
        splashWindow.process(80, PluginServices.getText(Launcher.class,
393
            "SplashWindow.starting_plugin_internationalization_system"));
394
        pluginsMessages();
395

    
396
        // 9. Se modifica el andami-config con los plugins nuevos
397
        splashWindow.process(90, PluginServices.getText(Launcher.class,
398
            "SplashWindow.looking_for_a_skin"));
399
        updateAndamiConfig();
400

    
401
        frame = new MDIFrame();
402
        // 10. Se configura el nombre e icono de la aplicaci?n
403
        splashWindow.process(100, PluginServices.getText(Launcher.class,
404
            "SplashWindow.setting_up_applications_name_and_icons"));
405
        frameIcon(theme);
406

    
407
        // 11. Se prepara el MainFrame para albergar las extensiones
408
        splashWindow.process(110, PluginServices.getText(Launcher.class,
409
            "SplashWindow.preparing_workbench"));
410
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
411

    
412
        SwingUtilities.invokeAndWait(new Runnable() {
413

    
414
            public void run() {
415
                frame.init();
416
            }
417
        });
418
        ToolsSwingLocator.registerWindowManager(ToolsWindowManager.class);
419

    
420
        // 12. Leer el fichero de persistencia
421
        // info de los plugins
422
        // bookmarks de los plugins
423
        splashWindow.process(120, PluginServices.getText(Launcher.class,
424
            "SplashWindow.loading_plugin_settings"));
425
        loadPluginsPersistence();
426

    
427
        // Se instalan los controles del skin
428
        // 13. Se inicializan todas las extensiones de todos los plugins
429
        splashWindow.process(130, PluginServices.getText(Launcher.class,
430
            "SplashWindow.initializing_extensions"));
431
        SwingUtilities.invokeAndWait(new Runnable() {
432

    
433
            public void run() {
434
                initializeExtensions();
435
            }
436
        });
437

    
438
        // 14. Se inicializan la extensi?n exclusiva
439
        splashWindow.process(140, PluginServices.getText(Launcher.class,
440
            "SplashWindow.setting_up_master_extension"));
441
        SwingUtilities.invokeAndWait(new Runnable() {
442

    
443
            public void run() {
444
                initializeExclusiveUIExtension();
445
            }
446
        });
447
        frame.setClassesExtensions(classesExtensions);
448

    
449
        // 15. Se instalan los controles de las extensiones de los plugins
450
        splashWindow.process(150, PluginServices.getText(Launcher.class,
451
            "SplashWindow.installing_extensions_controls"));
452
        SwingUtilities.invokeAndWait(new Runnable() {
453

    
454
            public void run() {
455
                installPluginsControls();
456

    
457
            }
458
        });
459

    
460
        // 16. Se instalan los menus de las extensiones de los plugins
461
        splashWindow.process(160, PluginServices.getText(Launcher.class,
462
            "SplashWindow.installing_extensions_menus"));
463
        SwingUtilities.invokeAndWait(new Runnable() {
464

    
465
            public void run() {
466
                installPluginsMenus();
467

    
468
            }
469
        });
470

    
471
        // 17. Se instalan las etiquetas de las extensiones de los plugins
472
        splashWindow.process(170, PluginServices.getText(Launcher.class,
473
            "SplashWindow.installing_extensions_labels"));
474
        SwingUtilities.invokeAndWait(new Runnable() {
475

    
476
            public void run() {
477
                installPluginsLabels();
478

    
479
            }
480
        });
481

    
482
        // 18. Se instalan los bookmarks de los plugins
483

    
484
        // 19. Se muestra el frame principal
485
        splashWindow.process(180, PluginServices.getText(Launcher.class,
486
            "creating_main_window"));
487
        frame.setVisible(true);
488

    
489
        // 19. Se ejecuta el postInitialize
490
        splashWindow.process(190, PluginServices.getText(Launcher.class,
491
            "SplashWindow.post_initializing_extensions"));
492
        SwingUtilities.invokeAndWait(new Runnable() {
493

    
494
            public void run() {
495
                postInitializeExtensions();
496

    
497
            }
498
        });
499

    
500
        // Definimos un KeyEventDispatcher global para que las extensiones
501
        // puedan registrar sus "teclas r?pidas".
502
        GlobalKeyEventDispatcher keyDispatcher =
503
            GlobalKeyEventDispatcher.getInstance();
504
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
505
            .addKeyEventDispatcher(keyDispatcher);
506

    
507
        SwingUtilities.invokeAndWait(new Runnable() {
508

    
509
            public void run() {
510
                frame.enableControls();
511
            }
512
        });
513
        splashWindow.close();
514
        if (launcherrors != null) {
515
            NotificationManager.addError(launcherrors);
516
        }
517
        
518
        org.apache.log4j.Logger.getRootLogger().addAppender(new NotificationAppender());
519

    
520
        
521
    }
522

    
523
    /**
524
     * 
525
     */
526
    private void initializeLibraries() {
527
        List<ClassLoader> classLoaders =
528
            new ArrayList<ClassLoader>(pluginsOrdered.size() + 1);
529
        classLoaders.add(getClass().getClassLoader());
530
        Iterator<String> iter = pluginsOrdered.iterator();
531

    
532
        logger.debug("Initializing plugins libraries: ");
533
        while (iter.hasNext()) {
534
            String pName = (String) iter.next();
535
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
536
            classLoaders.add(ps.getClassLoader());
537
        }
538

    
539
        // Create the libraries initializer and
540
        // initialize the plugin libraries
541
        new DefaultLibrariesInitializer(
542
            classLoaders.toArray(new ClassLoader[classLoaders.size()]))
543
            .fullInitialize(true);
544

    
545
        // Remove them all, we don't need them anymore
546
        classLoaders.clear();
547
        classLoaders = null;
548
    }
549

    
550
    /**
551
     * @param args
552
     * @throws IOException
553
     * @throws ConfigurationException
554
     */
555
    private void initializeApp(String[] args) throws IOException,
556
        ConfigurationException {
557
        if (!validJVM()) {
558
            System.exit(-1);
559
        }
560

    
561
        // Clean temporal files
562
        Utilities.cleanUpTempFiles();
563

    
564
        appName = args[0];
565

    
566
        getOrCreateConfigFolder();
567

    
568
        configureLogging(appName);
569

    
570
        loadAndamiConfig(args[1]);
571

    
572
        // Hacemos visibles los argumentos como una propiedad est?tica
573
        // de plugin services para quien lo quiera usar (por ejemplo, para
574
        // cargar un proyecto por l?nea de comandos)
575
        PluginServices.setArguments(args);
576

    
577
        configureLocales(args);
578

    
579
        logger.info("Load and initialize andami and plugins libraries");
580
        // LibrariesInitializer libsInitializer =
581
        // new DefaultLibrariesInitializer();
582
        // libsInitializer.initialize(true);
583
        // libsInitializer.postInitialize(true);
584

    
585
        logger.info("Configure LookAndFeel");
586
        configureLookAndFeel();
587
    }
588

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

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

    
623
    /**
624
     * 
625
     */
626
    private void getOrCreateConfigFolder() {
627
        // Create application configuration folder
628
        appHomeDir = System.getProperty(appName + ".home");
629
        if (appHomeDir == null) {
630
            appHomeDir = System.getProperty("user.home");
631
        }
632

    
633
        appHomeDir += File.separator + appName;
634
        File parent = new File(appHomeDir);
635
        parent.mkdirs();
636
    }
637

    
638
    /**
639
     * @param args
640
     * @throws IOException
641
     */
642
    private void configureLogging(String appName) throws IOException {
643
        // Configurar el log4j
644
        Launcher.class.getClassLoader().getResource(".");
645
        PropertyConfigurator.configure("log4j.properties");
646

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

    
656
    
657
    private class NotificationAppender extends AppenderSkeleton{
658

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

    
672
        @Override
673
        public void close() {
674
            // TODO Auto-generated method stub
675
            
676
        }
677

    
678
        @Override
679
        public boolean requiresLayout() {
680
            // TODO Auto-generated method stub
681
            return false;
682
        }
683
        
684
    }
685

    
686
    /**
687
     * Return the directory applicaction is installed.
688
     */
689
    public static String getApplicationDirectory() {
690
        return new File("").getAbsolutePath();
691
    }
692

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

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

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

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

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

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

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

    
808
    /**
809
     * Establece los datos que ten?amos guardados respecto de la configuraci?n
810
     * del proxy.
811
     */
812
    private void configureProxy() {
813
        String host = prefs.get("firewall.http.host", "");
814
        String port = prefs.get("firewall.http.port", "");
815

    
816
        System.getProperties().put("http.proxyHost", host);
817
        System.getProperties().put("http.proxyPort", port);
818

    
819
        // Ponemos el usuario y clave del proxy, si existe
820
        String proxyUser = prefs.get("firewall.http.user", null);
821
        String proxyPassword = prefs.get("firewall.http.password", null);
822
        if (proxyUser != null) {
823
            System.getProperties().put("http.proxyUserName", proxyUser);
824
            System.getProperties().put("http.proxyPassword", proxyPassword);
825

    
826
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
827
        } else {
828
            Authenticator.setDefault(new ProxyAuth("", ""));
829
        }
830
    }
831

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

    
858
        // restore frame status (Maximized, minimized, etc);
859
        int state = java.awt.Frame.MAXIMIZED_BOTH;
860
        if (xml.contains("MDIFrameState")) {
861
            state = xml.getIntProperty("MDIFrameState");
862
        }
863
        frame.setExtendedState(state);
864
    }
865

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

    
883
    private boolean validJVM() {
884
        char thirdCharacter = System.getProperty("java.version").charAt(2);
885
        if (thirdCharacter < '4') {
886
            return false;
887
        } else {
888
            return true;
889
        }
890
    }
891

    
892
    private void loadPluginsPersistence() throws ConfigurationException {
893
        XMLEntity entity = persistenceFromXML();
894

    
895
        for (int i = 0; i < entity.getChildrenCount(); i++) {
896
            XMLEntity plugin = entity.getChild(i);
897
            String pName =
898
                plugin.getStringProperty("com.iver.andami.pluginName");
899

    
900
            if (pName.compareToIgnoreCase("com.iver.cit.gvsig") == 0) {
901
                pName = "org.gvsig.app";
902
            }
903
            if (pluginsServices.get(pName) != null) {
904
                ((PluginServices) pluginsServices.get(pName))
905
                    .setPersistentXML(plugin);
906
            } else {
907
                if (pName.startsWith("Andami.Launcher")) {
908
                    restoreMDIStatus(plugin);
909
                }
910
            }
911
        }
912
    }
913

    
914
    /**
915
     * Salva la persistencia de los plugins.
916
     * 
917
     * @author LWS
918
     */
919
    private void savePluginPersistence() {
920
        Iterator<String> i = pluginsConfig.keySet().iterator();
921

    
922
        XMLEntity entity = new XMLEntity();
923

    
924
        while (i.hasNext()) {
925
            String pName = i.next();
926
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
927
            XMLEntity ent = ps.getPersistentXML();
928

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

    
950
    private void installPluginsLabels() {
951
        Iterator<String> i = pluginsConfig.keySet().iterator();
952

    
953
        while (i.hasNext()) {
954
            String name = i.next();
955
            PluginConfig pc = pluginsConfig.get(name);
956
            PluginServices ps = (PluginServices) pluginsServices.get(name);
957

    
958
            LabelSet[] ls = pc.getLabelSet();
959

    
960
            for (int j = 0; j < ls.length; j++) {
961
                PluginClassLoader loader = ps.getClassLoader();
962

    
963
                try {
964
                    Class clase = loader.loadClass(ls[j].getClassName());
965
                    frame.setStatusBarLabels(clase, ls[j].getLabel());
966
                } catch (ClassNotFoundException e) {
967
                    this.addError(
968
                        Messages.getString("Launcher.labelset_class"), e);
969
                }
970
            }
971
        }
972
    }
973

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

    
988
    private void fixSkin(SkinExtension skinExtension,
989
        PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
990
        // now insert the skin selected.
991
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
992
        // MDIManagerFactory.setSkinExtension(se,
993
        // ps.getClassLoader());
994

    
995
        Class<? extends IExtension> skinClass;
996

    
997
        try {
998
            skinClass =
999
                (Class<? extends IExtension>) pluginClassLoader
1000
                    .loadClass(skinExtension.getClassName());
1001

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

    
1027
    }
1028

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

    
1044
        SkinExtension skinExtension = null;
1045
        PluginClassLoader pluginClassLoader = null;
1046
        List<SkinExtension> skinExtensions = new ArrayList<SkinExtension>();
1047
        while (i.hasNext()) {
1048
            String name = i.next();
1049
            PluginConfig pc = pluginsConfig.get(name);
1050
            PluginServices ps = pluginsServices.get(name);
1051

    
1052
            if (pc.getExtensions().getSkinExtension() != null) {
1053
                // if (MDIManagerFactory.getSkinExtension() != null) {
1054
                // logger.warn(Messages.getString(
1055
                // "Launcher.Dos_skin_extension"));
1056
                // }
1057

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

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

    
1092
    }
1093

    
1094
    private static void frameIcon(Theme theme) {
1095
        Iterator<String> i = pluginsConfig.keySet().iterator();
1096

    
1097
        while (i.hasNext()) {
1098
            String pName = i.next();
1099
            PluginConfig pc = pluginsConfig.get(pName);
1100
            if (pc.getIcon() != null) {
1101
                if (theme.getIcon() != null) {
1102
                    frame.setIconImage(theme.getIcon().getImage());
1103
                } else {
1104

    
1105
                    ImageIcon icon =
1106
                        PluginServices.getIconTheme()
1107
                            .get(pc.getIcon().getSrc());
1108
                    frame.setIconImage(icon.getImage());
1109

    
1110
                }
1111
                if (theme.getName() != null) {
1112
                    frame.setTitlePrefix(theme.getName());
1113
                } else {
1114
                    frame.setTitlePrefix(pc.getIcon().getText());
1115
                }
1116
                if (theme.getBackgroundImage() != null) {
1117

    
1118
                    PluginServices.getMDIManager().setBackgroundImage(
1119
                        theme.getBackgroundImage(), theme.getTypeDesktop());
1120
                }
1121
            }
1122
        }
1123
    }
1124

    
1125
    private void initializeExtensions() {
1126

    
1127
        List<ClassLoader> classLoaders =
1128
            new ArrayList<ClassLoader>(pluginsOrdered.size());
1129
        classLoaders.add(getClass().getClassLoader());
1130
        Iterator<String> iter = pluginsOrdered.iterator();
1131

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

    
1149
        logger.info("Initializing plugins: ");
1150
        // iter = pluginsOrdered.iterator();
1151
        while (iter.hasNext()) {
1152
            String pName = (String) iter.next();
1153
            logger.info("Initializing plugin " + pName);
1154
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1155
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1156

    
1157
            Extension[] exts = pc.getExtensions().getExtension();
1158

    
1159
            TreeSet<Extension> orderedExtensions =
1160
                new TreeSet<Extension>(new ExtensionComparator());
1161

    
1162
            for (int j = 0; j < exts.length; j++) {
1163
                if (!exts[j].getActive()) {
1164
                    continue;
1165
                }
1166

    
1167
                if (orderedExtensions.contains(exts[j])) {
1168
                    logger.warn("Two extensions with the same priority ("
1169
                        + exts[j].getClassName() + ")");
1170
                }
1171

    
1172
                orderedExtensions.add(exts[j]);
1173
            }
1174

    
1175
            Iterator<Extension> e = orderedExtensions.iterator();
1176

    
1177
            logger.info("Initializing extensions of plugin "+pName+": ");
1178
            while (e.hasNext()) {
1179
                Extension extension = e.next();
1180
                org.gvsig.andami.plugins.IExtension extensionInstance;
1181

    
1182
                try {
1183
                    logger.info("Initializing " + extension.getClassName()
1184
                        + "...");
1185
                    Class<? extends IExtension> extensionClass =
1186
                        (Class<? extends IExtension>) ps.getClassLoader()
1187
                            .loadClass(extension.getClassName());
1188
                    extensionInstance = extensionClass.newInstance();
1189

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

    
1209
                    extensionInstance.initialize();
1210
                    extensions.add(extensionInstance);
1211

    
1212
                } catch (NoClassDefFoundError e1) {
1213
                    this.addError("Can't find class extension ("
1214
                        + extension.getClassName() + ")", e1);
1215
                } catch (Throwable e1) {
1216
                    this.addError("Can't initialize extension '"
1217
                        + extension.getClassName() + "'.", e1);
1218
                }
1219
            }
1220
        }
1221
    }
1222

    
1223
    private void postInitializeExtensions() {
1224
        logger.info("PostInitializing extensions: ");
1225

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

    
1240
    private void installPluginsMenus() {
1241
        TreeSet<SortableMenu> orderedMenus =
1242
            new TreeSet<SortableMenu>(new MenuComparator());
1243

    
1244
        Iterator<String> i = pluginsConfig.keySet().iterator();
1245

    
1246
        while (i.hasNext()) {
1247
            String pName = i.next();
1248
                try {
1249
            PluginServices ps = pluginsServices.get(pName);
1250
            PluginConfig pc = pluginsConfig.get(pName);
1251

    
1252
            Extension[] exts = pc.getExtensions().getExtension();
1253

    
1254
            for (int j = 0; j < exts.length; j++) {
1255
                if (!exts[j].getActive()) {
1256
                    continue;
1257
                }
1258

    
1259
                Menu[] menus = exts[j].getMenu();
1260

    
1261
                for (int k = 0; k < menus.length; k++) {
1262
                    SortableMenu sm =
1263
                        new SortableMenu(ps.getClassLoader(), exts[j], menus[k]);
1264

    
1265
                    if (orderedMenus.contains(sm)) {
1266
                        this
1267
                            .addError(Messages
1268
                                .getString("Launcher.Two_menus_with_the_same_position")
1269
                                + " - "
1270
                                + menus[k].getText()
1271
                                + " - "
1272
                                + exts[j].getClassName());
1273
                    }
1274

    
1275
                    orderedMenus.add(sm);
1276
                }
1277
            }
1278

    
1279
            // Se instalan las extensiones de MDI
1280
            SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1281
            for (int j = 0; j < skinExts.length; j++) {
1282

    
1283
                if (skinExts[j] != null) {
1284
                    Menu[] menu = skinExts[j].getMenu();
1285

    
1286
                    for (int k = 0; k < menu.length; k++) {
1287
                        SortableMenu sm =
1288
                            new SortableMenu(ps.getClassLoader(), skinExts[j],
1289
                                menu[k]);
1290

    
1291
                        if (orderedMenus.contains(sm)) {
1292
                            this
1293
                                .addError(Messages
1294
                                    .getString("Launcher.Two_menus_with_the_same_position")
1295
                                    + skinExts[j].getClassName());
1296
                        }
1297

    
1298
                        orderedMenus.add(sm);
1299
                    }
1300
                }
1301
            }
1302
            
1303
            
1304
                } catch (Throwable e) {
1305
                        addError("Error initializing menus of plugin '"+pName+"'", e);
1306
                        }
1307
            
1308
            
1309
        }
1310

    
1311
        // Se itera por los menus ordenados
1312
        Iterator<SortableMenu> e = orderedMenus.iterator();
1313

    
1314
        // Se ordenan los menues
1315
        while (e.hasNext()) {
1316
            try {
1317
                SortableMenu sm = e.next();
1318

    
1319
                frame.addMenu(sm.loader, sm.extension, sm.menu);
1320

    
1321
            } catch (ClassNotFoundException ex) {
1322
                this
1323
                    .addError(
1324
                        Messages
1325
                            .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1326
                        ex);
1327
            } catch (NoClassDefFoundError ex) {
1328
                this
1329
                .addError(
1330
                    Messages
1331
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1332
                    ex);
1333
            } catch (Throwable ex) {
1334
                this
1335
                .addError(
1336
                    Messages
1337
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1338
                    ex);
1339
            }
1340
        }
1341
    }
1342

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

    
1351
        Map<Extension, PluginServices> extensionPluginServices =
1352
            new HashMap<Extension, PluginServices>();
1353
        Map<Extension, PluginConfig> extensionPluginConfig =
1354
            new HashMap<Extension, PluginConfig>();
1355
        Set<Extension> orderedExtensions =
1356
            new TreeSet<Extension>(new ExtensionComparator());
1357

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

    
1368
                        Extension[] exts = pc.getExtensions().getExtension();
1369

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

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

    
1395
        TreeSet<SortableTool> orderedTools =
1396
            new TreeSet<SortableTool>(new ToolComparator());
1397
        Iterator<Extension> e = orderedExtensions.iterator();
1398

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

    
1409
                        // get tools from toolbars
1410
                        for (int k = 0; k < toolbars.length; k++) {
1411
                                ActionTool[] tools = toolbars[k].getActionTool();
1412

    
1413
                                for (int t = 0; t < tools.length; t++) {
1414
                                        SortableTool sm =
1415
                                                new SortableTool((extensionPluginServices.get(ext))
1416
                                                                .getClassLoader(), ext, toolbars[k], tools[t]);
1417
                                        orderedTools.add(sm);
1418
                                }
1419

    
1420
                                SelectableTool[] sTools = toolbars[k].getSelectableTool();
1421

    
1422
                                for (int t = 0; t < sTools.length; t++) {
1423
                                        SortableTool sm =
1424
                                                new SortableTool((extensionPluginServices.get(ext))
1425
                                                                .getClassLoader(), ext, toolbars[k], sTools[t]);
1426
                                        orderedTools.add(sm);
1427
                                }
1428
                        }
1429

    
1430
                        // get controls for statusBar
1431
                        PluginServices ps = extensionPluginServices.get(ext);
1432
                        PluginClassLoader loader = ps.getClassLoader();
1433

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

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

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

    
1533
                        SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1534
                        for (int j = 0; j < skinExts.length; j++) {
1535

    
1536
                                if (skinExts[j] != null) {
1537
                                        ToolBar[] toolbars = skinExts[j].getToolBar();
1538

    
1539
                                        for (int k = 0; k < toolbars.length; k++) {
1540
                                                ActionTool[] tools = toolbars[k].getActionTool();
1541

    
1542
                                                for (int t = 0; t < tools.length; t++) {
1543
                                                        SortableTool stb =
1544
                                                                new SortableTool(ps.getClassLoader(),
1545
                                                                                skinExts[j], toolbars[k], tools[t]);
1546
                                                        orderedTools.add(stb);
1547
                                                }
1548

    
1549
                                                SelectableTool[] sTools =
1550
                                                        toolbars[k].getSelectableTool();
1551

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

    
1564
                        if (pus != null) {
1565
                                PopupMenu[] menus = pus.getPopupMenu();
1566

    
1567
                                for (int j = 0; j < menus.length; j++) {
1568
                                        frame.addPopupMenu(ps.getClassLoader(), menus[j]);
1569
                                }
1570
                        }
1571
                } catch (Throwable e3) {
1572
                        addError("Error initializing skins of the plugin '"+pName+"'", e3);
1573
                }
1574
        }
1575

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

    
1601
    /**
1602
     * Adds new plugins to the the andami-config file.
1603
     */
1604
    private void updateAndamiConfig() {
1605
        Set<String> olds = new HashSet<String>();
1606

    
1607
        Plugin[] plugins = andamiConfig.getPlugin();
1608

    
1609
        for (int i = 0; i < plugins.length; i++) {
1610
            olds.add(plugins[i].getName());
1611
        }
1612

    
1613
        Iterator<PluginServices> i = pluginsServices.values().iterator();
1614

    
1615
        while (i.hasNext()) {
1616
            PluginServices ps = i.next();
1617

    
1618
            if (!olds.contains(ps.getPluginName())) {
1619
                Plugin p = new Plugin();
1620
                p.setName(ps.getPluginName());
1621
                p.setUpdate(false);
1622

    
1623
                andamiConfig.addPlugin(p);
1624
            }
1625
        }
1626
    }
1627

    
1628
    private void pluginsClassLoaders() {
1629
        Set<String> installed = new HashSet<String>();
1630

    
1631
        // Se itera hasta que est?n todos instalados
1632
        while (installed.size() != pluginsConfig.size()) {
1633
            boolean circle = true;
1634

    
1635
            // Hacemos una pasada por todos los plugins
1636
            Iterator<String> i = pluginsConfig.keySet().iterator();
1637

    
1638
            while (i.hasNext()) {
1639
                String pluginName = i.next();
1640
                PluginConfig config =
1641
                    (PluginConfig) pluginsConfig.get(pluginName);
1642

    
1643
                if (installed.contains(pluginName)) {
1644
                    continue;
1645
                }
1646

    
1647
                // Se obtienen las dependencias y sus class loaders
1648
                boolean ready = true;
1649
                Depends[] dependencies = config.getDepends();
1650
                PluginClassLoader[] loaders =
1651
                    new PluginClassLoader[dependencies.length];
1652

    
1653
                for (int j = 0; j < dependencies.length; j++) {
1654
                    if (pluginsConfig.get(dependencies[j].getPluginName()) == null) {
1655
                        this
1656
                            .addError(Messages
1657
                                .getString("Launcher.Dependencia_no_resuelta_en_plugin")
1658
                                + " "
1659
                                + pluginName
1660
                                + ": "
1661
                                + dependencies[j].getPluginName());
1662

    
1663
                        continue;
1664
                    }
1665

    
1666
                    if (!installed.contains(dependencies[j].getPluginName())) {
1667
                        ready = false;
1668
                    } else {
1669
                        loaders[j] =
1670
                            (pluginsServices.get(dependencies[j]
1671
                                .getPluginName())).getClassLoader();
1672
                    }
1673
                }
1674

    
1675
                // Si no est?n sus dependencias satisfechas se aborta la
1676
                // instalaci?n
1677
                if (!ready) {
1678
                    continue;
1679
                }
1680

    
1681
                // Se genera el class loader
1682
                String jardir = config.getLibraries().getLibraryDir();
1683
                File jarDir =
1684
                    new File(andamiConfig.getPluginsDirectory(), pluginName
1685
                        + File.separator + jardir);
1686
                File[] jarFiles = jarDir.listFiles(new FileFilter() {
1687

    
1688
                    public boolean accept(File pathname) {
1689
                        return (pathname.getName().toUpperCase()
1690
                            .endsWith(".JAR"))
1691
                            || (pathname.getName().toUpperCase()
1692
                                .endsWith(".ZIP"));
1693
                    }
1694
                });
1695

    
1696
                URL[] urls = new URL[jarFiles.length];
1697

    
1698
                for (int j = 0; j < jarFiles.length; j++) {
1699
                    try {
1700
                        urls[j] = new URL("file:" + jarFiles[j]);
1701
                    } catch (MalformedURLException e) {
1702
                        this.addError(Messages
1703
                            .getString("Launcher.No_se_puede_acceder_a")
1704
                            + " " + jarFiles[j]);
1705
                    }
1706
                }
1707

    
1708
                PluginClassLoader loader;
1709

    
1710
                try {
1711
                    loader =
1712
                        new PluginClassLoader(urls, andamiConfig
1713
                            .getPluginsDirectory()
1714
                            + File.separator + pluginName, Launcher.class
1715
                            .getClassLoader(), loaders);
1716

    
1717
                    PluginServices ps = new PluginServices(loader);
1718

    
1719
                    pluginsServices.put(ps.getPluginName(), ps);
1720

    
1721
                    installed.add(pluginName);
1722
                    // FJP: Los metemos ordenados para luego no cargar uno que
1723
                    // necesita de otro antes de tiempo. Esto lo usaremos al
1724
                    // inicializar los plugins
1725
                    pluginsOrdered.add(pluginName);
1726

    
1727
                    circle = false;
1728
                } catch (IOException e) {
1729
                    this
1730
                        .addError(
1731
                            Messages
1732
                                .getString("Launcher.Error_con_las_librerias_del_plugin"),
1733
                            e);
1734
                    pluginsConfig.remove(pluginName);
1735
                    i = pluginsConfig.keySet().iterator();
1736
                }
1737
            }
1738

    
1739
            if (circle) {
1740
                this.addError(Messages
1741
                    .getString("Launcher.Hay_dependencias_circulares"));
1742

    
1743
                break;
1744
            }
1745
        }
1746

    
1747
        // Se eliminan los plugins que no fueron instalados
1748
        Iterator<String> i = pluginsConfig.keySet().iterator();
1749

    
1750
        while (i.hasNext()) {
1751
            String pluginName = i.next();
1752
            PluginServices ps =
1753
                (PluginServices) pluginsServices.get(pluginName);
1754

    
1755
            if (ps == null) {
1756
                pluginsConfig.remove(pluginName);
1757
                i = pluginsConfig.keySet().iterator();
1758
            }
1759
        }
1760
    }
1761

    
1762
    private void pluginsMessages() {
1763
        Iterator<String> iterator = pluginsOrdered.iterator();
1764
        PluginConfig config;
1765
        PluginServices ps;
1766

    
1767
        while (iterator.hasNext()) {
1768
            String pluginName = iterator.next();
1769
            config = pluginsConfig.get(pluginName);
1770
            ps = pluginsServices.get(pluginName);
1771

    
1772
            if ((config.getResourceBundle() != null)
1773
                && !config.getResourceBundle().getName().equals("")) {
1774
                // add the locale files associated with the plugin
1775
                org.gvsig.i18n.Messages.addResourceFamily(config
1776
                    .getResourceBundle().getName(), ps.getClassLoader(),
1777
                    pluginName);
1778
            }
1779
        }
1780
    }
1781

    
1782
    static public PluginServices getPluginServices(String name) {
1783
        return (PluginServices) pluginsServices.get(name);
1784
    }
1785

    
1786
    static String getPluginsDir() {
1787
        return andamiConfig.getPluginsDirectory();
1788
    }
1789

    
1790
    static void setPluginsDir(String s) {
1791
        andamiConfig.setPluginsDirectory(s);
1792
    }
1793

    
1794
    static MDIFrame getMDIFrame() {
1795
        return frame;
1796
    }
1797

    
1798
    private void loadPlugins(String pluginsDirectory) {
1799
        File pDir = new File(pluginsDirectory);
1800

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

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

    
1820
        for (int i = 0; i < pluginDirs.length; i++) {
1821
            if (pluginDirs[i].isDirectory()) {
1822
                File configXml =
1823
                    new File(pluginDirs[i].getAbsolutePath(), "config.xml");
1824

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

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

    
1864
    private static Locale getLocale(String language, String country,
1865
        String variant) {
1866
        if (variant != null) {
1867
            return new Locale(language, country, variant);
1868
        } else
1869
            if (country != null) {
1870
                return new Locale(language, country);
1871
            } else
1872
                if (language != null) {
1873
                    return new Locale(language);
1874
                } else {
1875
                    return new Locale("es");
1876
                }
1877
    }
1878

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

    
1889
        BufferedOutputStream os =
1890
            new BufferedOutputStream(new FileOutputStream(tmpFile));
1891
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
1892
        andamiConfig.marshal(writer);
1893
        writer.close();
1894

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

    
1911
    private static void andamiConfigFromXML(String file)
1912
        throws ConfigurationException {
1913
        File xml = new File(file);
1914

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

    
1947
    private static AndamiConfig getDefaultAndamiConfig() {
1948
        AndamiConfig andamiConfig = new AndamiConfig();
1949

    
1950
        Andami andami = new Andami();
1951
        andami.setUpdate(true);
1952
        andamiConfig.setAndami(andami);
1953
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
1954
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
1955
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
1956

    
1957
        if (System.getProperty("javawebstart.version") != null) // Es java web
1958
        // start)
1959
        {
1960
            andamiConfig
1961
                .setPluginsDirectory(new File(appHomeDir, "extensiones")
1962
                    .getAbsolutePath());
1963
        } else {
1964
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
1965
                .getAbsolutePath());
1966
        }
1967

    
1968
        andamiConfig.setPlugin(new Plugin[0]);
1969
        return andamiConfig;
1970
    }
1971

    
1972
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
1973
        File xml = getPluginsPersistenceFile(true);
1974

    
1975
        if (xml.exists()) {
1976
            InputStreamReader reader = null;
1977

    
1978
            try {
1979
                reader = XMLEncodingUtils.getReader(xml);
1980
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1981
                return new XMLEntity(tag);
1982
            } catch (FileNotFoundException e) {
1983
                throw new ConfigurationException(e);
1984
            } catch (MarshalException e) {
1985

    
1986
                // try to reopen with default encoding (for backward
1987
                // compatibility)
1988
                try {
1989
                    reader = new FileReader(xml);
1990
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1991
                    return new XMLEntity(tag);
1992

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

    
2026
    private static File getPluginsPersistenceFile(boolean read) {
2027
        if (read) {
2028
            File pluginsPersistenceFile =
2029
                new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2030
            if (pluginsPersistenceFile.exists()) {
2031
                return pluginsPersistenceFile;
2032
            }
2033
            pluginsPersistenceFile =
2034
                new File(getAppHomeDir(), "plugins-persistence.xml");
2035
            if (pluginsPersistenceFile.exists()) {
2036
                return pluginsPersistenceFile;
2037
            }
2038
        }
2039
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2040

    
2041
    }
2042

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

    
2051
        File xml = getPluginsPersistenceFile(false);
2052
        OutputStreamWriter writer = null;
2053

    
2054
        try {
2055
            writer =
2056
                new OutputStreamWriter(new FileOutputStream(tmpFile),
2057
                    CASTORENCODING);
2058
            entity.getXmlTag().marshal(writer);
2059
            writer.close();
2060

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

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

    
2093
    static MDIFrame getFrame() {
2094
        return frame;
2095
    }
2096

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

    
2108
    static HashMap getClassesExtensions() {
2109
        return classesExtensions;
2110
    }
2111

    
2112
    private static Extensions[] getExtensions() {
2113
        List<Extensions> array = new ArrayList<Extensions>();
2114
        Iterator<PluginConfig> iter = pluginsConfig.values().iterator();
2115

    
2116
        while (iter.hasNext()) {
2117
            array.add(iter.next().getExtensions());
2118
        }
2119

    
2120
        return array.toArray(new Extensions[array.size()]);
2121
    }
2122

    
2123
    public static Iterator getExtensionIterator() {
2124
        return extensions.iterator();
2125
    }
2126

    
2127
    public static HashMap getPluginConfig() {
2128
        return pluginsConfig;
2129
    }
2130

    
2131
    public static Extension getExtension(String s) {
2132
        Extensions[] exts = getExtensions();
2133

    
2134
        for (int i = 0; i < exts.length; i++) {
2135
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2136
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2137
                    return exts[i].getExtension(j);
2138
                }
2139
            }
2140
        }
2141

    
2142
        return null;
2143
    }
2144

    
2145
    public static AndamiConfig getAndamiConfig() {
2146
        return andamiConfig;
2147
    }
2148

    
2149
    private static class ExtensionComparator implements Comparator {
2150

    
2151
        public int compare(Object o1, Object o2) {
2152
            Extension e1 = (Extension) o1;
2153
            Extension e2 = (Extension) o2;
2154

    
2155
            if (!e1.hasPriority() && !e2.hasPriority()) {
2156
                return -1;
2157
            }
2158

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

    
2163
            if (e2.hasPriority() && !e1.hasPriority()) {
2164
                return Integer.MAX_VALUE;
2165
            }
2166

    
2167
            if (e1.getPriority() != e2.getPriority()) {
2168
                return e2.getPriority() - e1.getPriority();
2169
            } else {
2170
                return (e2.toString().compareTo(e1.toString()));
2171
            }
2172
        }
2173
    }
2174

    
2175
    private static class MenuComparator implements Comparator<SortableMenu> {
2176

    
2177
        private static ExtensionComparator extComp = new ExtensionComparator();
2178

    
2179
        public int compare(SortableMenu e1, SortableMenu e2) {
2180

    
2181
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2182
                if (e1.extension instanceof SkinExtensionType) {
2183
                    return 1;
2184
                } else
2185
                    if (e2.extension instanceof SkinExtensionType) {
2186
                        return -1;
2187
                    } else {
2188
                        return extComp.compare(e1.extension, e2.extension);
2189
                    }
2190
            }
2191

    
2192
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2193
                return Integer.MIN_VALUE;
2194
            }
2195

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

    
2209
    private static class SortableMenu {
2210

    
2211
        public PluginClassLoader loader;
2212
        public Menu menu;
2213
        public SkinExtensionType extension;
2214

    
2215
        public SortableMenu(PluginClassLoader loader,
2216
            SkinExtensionType skinExt, Menu menu2) {
2217
            extension = skinExt;
2218
            menu = menu2;
2219
            this.loader = loader;
2220
        }
2221
    }
2222

    
2223
    private static class SortableTool {
2224

    
2225
        public PluginClassLoader loader;
2226
        public ToolBar toolbar;
2227
        public ActionTool actiontool;
2228
        public SelectableTool selectabletool;
2229
        public SkinExtensionType extension;
2230

    
2231
        public SortableTool(PluginClassLoader loader,
2232
            SkinExtensionType skinExt, ToolBar toolbar2, ActionTool actiontool2) {
2233
            extension = skinExt;
2234
            toolbar = toolbar2;
2235
            actiontool = actiontool2;
2236
            this.loader = loader;
2237
        }
2238

    
2239
        public SortableTool(PluginClassLoader loader,
2240
            SkinExtensionType skinExt, ToolBar toolbar2,
2241
            SelectableTool selectabletool2) {
2242
            extension = skinExt;
2243
            toolbar = toolbar2;
2244
            selectabletool = selectabletool2;
2245
            this.loader = loader;
2246
        }
2247
    }
2248

    
2249
    private static class ToolBarComparator implements Comparator<SortableTool> {
2250

    
2251
        private static ExtensionComparator extComp = new ExtensionComparator();
2252

    
2253
        public int compare(SortableTool e1, SortableTool e2) {
2254

    
2255
            // if the toolbars have the same name, they are considered to be
2256
            // the same toolbar, so we don't need to do further comparing
2257
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2258
                return 0;
2259
            }
2260

    
2261
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2262
                if (e1.extension instanceof SkinExtensionType) {
2263
                    return 1;
2264
                } else
2265
                    if (e2.extension instanceof SkinExtensionType) {
2266
                        return -1;
2267
                    } else {
2268
                        return extComp.compare(e1.extension, e2.extension);
2269
                    }
2270
            }
2271

    
2272
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2273
                return Integer.MIN_VALUE;
2274
            }
2275

    
2276
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2277
                return Integer.MAX_VALUE;
2278
            }
2279
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2280
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2281
            }
2282

    
2283
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2284
                && e1.toolbar.getSelectableTool().equals(
2285
                    e2.toolbar.getSelectableTool())) {
2286
                return 0;
2287
            }
2288
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2289
        }
2290
    }
2291

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

    
2315
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2316

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

    
2326
            if (e1.actiontool != null) {
2327
                if (e1.actiontool.hasPosition()) {
2328
                    e1Position = e1.actiontool.getPosition();
2329
                }
2330
            } else
2331
                if (e1.selectabletool != null) {
2332
                    if (e1.selectabletool.hasPosition()) {
2333
                        e1Position = e1.selectabletool.getPosition();
2334
                    }
2335
                }
2336

    
2337
            if (e2.actiontool != null) {
2338
                if (e2.actiontool.hasPosition()) {
2339
                    e2Position = e2.actiontool.getPosition();
2340
                }
2341
            } else
2342
                if (e2.selectabletool != null) {
2343
                    if (e2.selectabletool.hasPosition()) {
2344
                        e2Position = e2.selectabletool.getPosition();
2345
                    }
2346
                }
2347

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

    
2366
    /**
2367
     * validates the user before starting gvsig
2368
     * 
2369
     */
2370
    private static void validate() {
2371

    
2372
        IAuthentication session = null;
2373
        try {
2374
            session =
2375
                (IAuthentication) Class.forName(
2376
                    "com.iver.andami.authentication.Session").newInstance();
2377

    
2378
        } catch (ClassNotFoundException e) {
2379
            return;
2380
        } catch (InstantiationException e) {
2381
            return;
2382
        } catch (IllegalAccessException e) {
2383
            return;
2384
        }
2385

    
2386
        session.setPluginDirectory(andamiConfig.getPluginsDirectory());
2387
        if (session.validationRequired()) {
2388
            if (session.Login()) {
2389
                logger.info("You are logged in");
2390
            } else {
2391
                JOptionPane.showMessageDialog((Component) PluginServices
2392
                    .getMainFrame(), "You are not logged in");
2393
            }
2394
            PluginServices.setAuthentication(session);
2395
        }
2396
    }
2397

    
2398
    public static String getDefaultLookAndFeel() {
2399
        String osName = (String) System.getProperty("os.name");
2400

    
2401
        if ((osName.length() > 4)
2402
            && osName.substring(0, 5).toLowerCase().equals("linux")) {
2403
            return nonWinDefaultLookAndFeel;
2404
        }
2405
        if (osName.toLowerCase().startsWith("mac os x")) {
2406
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
2407
        }
2408

    
2409
        return UIManager.getSystemLookAndFeelClassName();
2410
    }
2411

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

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

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

    
2523
    }
2524

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

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

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

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

    
2589
        logger
2590
            .error(Messages
2591
                .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
2592
                + " '" + name + "'");
2593
    }
2594

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

    
2633
    public static void initIconThemes() {
2634
        IconThemeManager iconManager = IconThemeManager.getIconThemeManager();
2635
        IIconTheme icontheme = iconManager.getIconThemeFromConfig();
2636
        if (icontheme != null) {
2637
            iconManager.setCurrent(icontheme);
2638
        }
2639
    }
2640

    
2641
    /**
2642
     * Manages Andami termination process
2643
     * 
2644
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
2645
     */
2646
    public class TerminationProcess {
2647

    
2648
        private boolean proceed = false;
2649
        private UnsavedDataPanel panel = null;
2650

    
2651
        public void run() {
2652
            int exit = manageUnsavedData();
2653
            if ((exit == JOptionPane.NO_OPTION)
2654
                || (exit == JOptionPane.CLOSED_OPTION)) {
2655
                // the user doesn't want to exit
2656
                return;
2657
            }
2658

    
2659
            closeAndami();
2660
        }
2661

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

    
2673
            
2674
            try {
2675
                // Persistencia de los plugins
2676
                savePluginPersistence();
2677
                savePluginsProperties();
2678
            } catch(Exception ex) {
2679
                logger.error("There was an error exiting application, can't save plugins properties", ex);
2680
            }
2681

    
2682
            // Finalize all the extensions
2683
            finalizeExtensions();
2684

    
2685
            try {
2686
                // Clean any temp data created
2687
                Utilities.cleanUpTempFiles();
2688
            } catch(Exception ex) {
2689
                logger.error("There was an error exiting application, can't remove temporary files", ex);
2690
            }
2691

    
2692
            logger.info("Quiting application.");
2693
            
2694
            // Para la depuraci?n de memory leaks
2695
            System.gc();
2696

    
2697
            System.exit(0);
2698
        }
2699

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

    
2728
        private void savePluginsProperties() {
2729
            PluginsManager manager = PluginsLocator.getManager();
2730
            List<PluginServices> plugins = manager.getPlugins();
2731
            for (PluginServices plugin : plugins) {
2732
                if (plugin != null) {
2733
                    plugin.savePluginProperties();
2734
                }
2735
            }
2736
        }
2737

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

    
2759
        private IUnsavedData[] getUnsavedData() {
2760
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
2761
            IExtension exclusiveExtension =
2762
                PluginServices.getExclusiveUIExtension();
2763

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

    
2786
        public UnsavedDataPanel getUnsavedDataPanel() {
2787
            if (panel == null) {
2788
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
2789
            }
2790
            return panel;
2791
        }
2792

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

    
2802
            // there was no unsaved data
2803
            if (unsavedData.length == 0) {
2804
                int option =
2805
                    JOptionPane
2806
                        .showConfirmDialog(frame, Messages
2807
                            .getString("MDIFrame.quiere_salir"), Messages
2808
                            .getString("MDIFrame.salir"),
2809
                            JOptionPane.YES_NO_OPTION);
2810
                return option;
2811
            }
2812

    
2813
            UnsavedDataPanel panel = getUnsavedDataPanel();
2814
            panel.setUnsavedDataArray(unsavedData);
2815

    
2816
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
2817

    
2818
                public void cancel(UnsavedDataPanel panel) {
2819
                    proceed(false);
2820
                    PluginServices.getMDIManager().closeWindow(panel);
2821

    
2822
                }
2823

    
2824
                public void discard(UnsavedDataPanel panel) {
2825
                    proceed(true);
2826
                    PluginServices.getMDIManager().closeWindow(panel);
2827

    
2828
                }
2829

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

    
2861
                            unsavedDataArray = getUnsavedData();
2862
                            panel.setUnsavedDataArray(unsavedDataArray);
2863
                            return;
2864
                        }
2865
                    }
2866
                    proceed(true);
2867
                    PluginServices.getMDIManager().closeWindow(panel);
2868
                }
2869
            });
2870

    
2871
            PluginServices.getMDIManager().addWindow(panel);
2872
            if (proceed) {
2873
                return JOptionPane.YES_OPTION;
2874
            } else {
2875
                return JOptionPane.NO_OPTION;
2876
            }
2877
        }
2878

    
2879
        private void proceed(boolean proceed) {
2880
            this.proceed = proceed;
2881
        }
2882

    
2883
    }
2884

    
2885
    public static TerminationProcess getTerminationProcess() {
2886
        return (new Launcher()).new TerminationProcess();
2887
    }
2888

    
2889
    /**
2890
     * Launch the gvSIG package installer.
2891
     * 
2892
     * @throws Exception
2893
     *             if there is any error
2894
     */
2895
    private void doInstall(String[] args) throws Exception {
2896
        String installURL = null;
2897
        String gvSIGVersion = null;
2898
        if (args.length >= 5) {
2899
            String installURLParam = args[3];
2900
            if (installURLParam.startsWith("--installURL=")) {
2901
                installURL =
2902
                    installURLParam.substring("--installURL=".length());
2903
            }
2904
            String gvSIGVersionParam = args[4];
2905
            if (gvSIGVersionParam.startsWith("--installVersion=")) {
2906
                gvSIGVersion =
2907
                    gvSIGVersionParam.substring("--installVersion=".length());
2908
            }
2909
        }
2910

    
2911
        if (args.length < 3) {
2912
            System.err.println(Messages.get("usage")
2913
                + ": Launcher appName plugins-directory "
2914
                + "--install [--installURL=[URL]] [language=locale]");
2915
        }
2916

    
2917
        initializeApp(args);
2918
        initializeLibraries();
2919
        AndamiConfig config = getAndamiConfig();
2920
        config.setLocaleLanguage(locale.getLanguage());
2921
        config.setLocaleCountry(locale.getCountry());
2922
        config.setLocaleVariant(locale.getVariant());
2923

    
2924
        // Configure default index download URL
2925
        if (installURL != null) {
2926
                SwingInstallerLocator.getSwingInstallerManager()
2927
                    .setDefaultDownloadURL(installURL);
2928
        }
2929

    
2930
        // Launch installer
2931

    
2932
        PluginsManager manager = PluginsLocator.getManager();
2933
        AbstractInstallPackageWizard installPackageWizard =
2934
            SwingInstallerLocator.getSwingInstallerManager()
2935
                .createInstallPackageWizard(manager.getApplicationFolder(),
2936
                    manager.getPluginsFolder().getAbsoluteFile(),
2937
                    manager.getInstallFolder());
2938
        installPackageWizard
2939
            .setWizardActionListener(new InstallerWizardActionListener() {
2940

    
2941
                public void finish(InstallerWizardPanel installerWizard) {
2942
                    System.exit(0);
2943
                }
2944

    
2945
                public void cancel(InstallerWizardPanel installerWizard) {
2946
                    System.exit(0);
2947
                }
2948
            });
2949
        
2950
        // the wizard will show the Typical or Advanced mode option.
2951
        installPackageWizard.setAskTypicalOrCustom(true);
2952
        // default packages will be selected.
2953
        installPackageWizard.setSelectDefaultPackages(true);
2954
        
2955
        // set the gvSIG version to the install manager, to compose the download
2956
        // URL:
2957
        InstallerLocator.getInstallerManager().setVersion(gvSIGVersion);
2958
        
2959
        // 1. Create the frame.
2960
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
2961

    
2962
        // 2. What happens when the frame closes?
2963
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
2964
        Runtime.getRuntime().addShutdownHook(new Thread() {
2965

    
2966
            @Override
2967
            public void run() {
2968
                getTerminationProcess().saveAndamiConfig();
2969
            }
2970
        });
2971

    
2972
        // 3. Add the installer panel to the frame
2973
        frame.getContentPane().add(installPackageWizard, BorderLayout.CENTER);
2974

    
2975
        // 4. Size the frame and center on the screen
2976
        frame.pack();
2977
        frame.setLocationRelativeTo(null);
2978

    
2979
        // 5. Show it.
2980
        frame.setVisible(true);
2981
    }
2982
    
2983
        public static String getInformation() {
2984
                PluginsManager pluginmgr = PluginsLocator.getManager();
2985
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
2986

    
2987
                StringWriter writer = new StringWriter();
2988

    
2989
                Properties props = System.getProperties();
2990

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

    
3012
                // JRE information
3013
                writer.write("JRE\n");
3014
                writer.write("    vendor : " + props.get("java.vendor") + "\n");
3015
                writer.write("    version: " +props.get("java.version")+ "\n");
3016
                writer.write("    home   : " + props.get("java.home") + "\n");
3017

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

    
3055
        private void logger_info(String msg) {
3056
                String info[] = msg.split("\n");
3057
                for (int i=0;i< info.length;i++) {
3058
                        logger.info(info[i]);
3059
                }
3060
        }
3061

    
3062

    
3063
}