Statistics
| Revision:

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

History | View | Annotate | Download (96.8 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.Component;
44
import java.awt.Dimension;
45
import java.awt.EventQueue;
46
import java.awt.Frame;
47
import java.awt.KeyboardFocusManager;
48
import java.awt.Point;
49
import java.awt.Toolkit;
50
import java.io.BufferedOutputStream;
51
import java.io.BufferedReader;
52
import java.io.File;
53
import java.io.FileFilter;
54
import java.io.FileInputStream;
55
import java.io.FileNotFoundException;
56
import java.io.FileOutputStream;
57
import java.io.FileReader;
58
import java.io.IOException;
59
import java.io.InputStreamReader;
60
import java.io.OutputStreamWriter;
61
import java.io.Reader;
62
import java.net.Authenticator;
63
import java.net.MalformedURLException;
64
import java.net.PasswordAuthentication;
65
import java.net.URL;
66
import java.nio.channels.FileChannel;
67
import java.security.AllPermission;
68
import java.security.CodeSource;
69
import java.security.PermissionCollection;
70
import java.security.Permissions;
71
import java.security.Policy;
72
import java.util.ArrayList;
73
import java.util.Comparator;
74
import java.util.HashMap;
75
import java.util.HashSet;
76
import java.util.Iterator;
77
import java.util.List;
78
import java.util.Locale;
79
import java.util.TreeMap;
80
import java.util.prefs.Preferences;
81

    
82
import javax.swing.ImageIcon;
83
import javax.swing.JButton;
84
import javax.swing.JComponent;
85
import javax.swing.JOptionPane;
86
import javax.swing.JPopupMenu;
87
import javax.swing.SwingUtilities;
88
import javax.swing.UIManager;
89

    
90
import org.apache.log4j.PatternLayout;
91
import org.apache.log4j.PropertyConfigurator;
92
import org.apache.log4j.RollingFileAppender;
93
import org.exolab.castor.xml.MarshalException;
94
import org.exolab.castor.xml.ValidationException;
95
import org.gvsig.andami.authentication.IAuthentication;
96
import org.gvsig.andami.authentication.LoginUI;
97
import org.gvsig.andami.config.generate.Andami;
98
import org.gvsig.andami.config.generate.AndamiConfig;
99
import org.gvsig.andami.config.generate.Plugin;
100
import org.gvsig.andami.iconthemes.IIconTheme;
101
import org.gvsig.andami.iconthemes.IconThemeManager;
102
import org.gvsig.andami.impl.DefaultPluginsManager;
103
import org.gvsig.andami.messages.Messages;
104
import org.gvsig.andami.messages.NotificationManager;
105
import org.gvsig.andami.plugins.ExclusiveUIExtension;
106
import org.gvsig.andami.plugins.ExtensionDecorator;
107
import org.gvsig.andami.plugins.IExtension;
108
import org.gvsig.andami.plugins.PluginClassLoader;
109
import org.gvsig.andami.plugins.config.generate.ActionTool;
110
import org.gvsig.andami.plugins.config.generate.ComboButton;
111
import org.gvsig.andami.plugins.config.generate.ComboButtonElement;
112
import org.gvsig.andami.plugins.config.generate.ComboScale;
113
import org.gvsig.andami.plugins.config.generate.Depends;
114
import org.gvsig.andami.plugins.config.generate.Extension;
115
import org.gvsig.andami.plugins.config.generate.Extensions;
116
import org.gvsig.andami.plugins.config.generate.LabelSet;
117
import org.gvsig.andami.plugins.config.generate.Menu;
118
import org.gvsig.andami.plugins.config.generate.PluginConfig;
119
import org.gvsig.andami.plugins.config.generate.PopupMenu;
120
import org.gvsig.andami.plugins.config.generate.PopupMenus;
121
import org.gvsig.andami.plugins.config.generate.SelectableTool;
122
import org.gvsig.andami.plugins.config.generate.SkinExtension;
123
import org.gvsig.andami.plugins.config.generate.SkinExtensionType;
124
import org.gvsig.andami.plugins.config.generate.ToolBar;
125
import org.gvsig.andami.plugins.status.IExtensionStatus;
126
import org.gvsig.andami.plugins.status.IUnsavedData;
127
import org.gvsig.andami.ui.AndamiEventQueue;
128
import org.gvsig.andami.ui.MDIManagerLoadException;
129
import org.gvsig.andami.ui.fonts.FontUtils;
130
import org.gvsig.andami.ui.mdiFrame.MDIFrame;
131
import org.gvsig.andami.ui.mdiFrame.NewStatusBar;
132
import org.gvsig.andami.ui.mdiManager.MDIManagerFactory;
133
import org.gvsig.andami.ui.splash.MultiSplashWindow;
134
import org.gvsig.andami.ui.theme.Theme;
135
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
136
import org.gvsig.tools.exception.ListBaseException;
137
import org.gvsig.tools.library.LibrariesInitializer;
138
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
139
import org.gvsig.utils.DateTime;
140
import org.gvsig.utils.XMLEntity;
141
import org.gvsig.utils.xml.XMLEncodingUtils;
142
import org.gvsig.utils.xmlEntity.generate.XmlTag;
143
import org.slf4j.Logger;
144
import org.slf4j.LoggerFactory;
145

    
146
/**
147
 * <p>
148
 * Andami's launching class. This is the class used to create the Andami's
149
 * plugin environment.<br>
150
 * </p>
151
 * 
152
 * <p>
153
 * <b>Syntax:</b> <br>
154
 * java [-Xmx512M (for 512MB of RAM)] [-classpath={a colon-separated(unix) or
155
 * semicolon-separated(windows) list of files containg base library of classes}]
156
 * [-Djava.library.path=PATH_TO_NATIVE_LIBRARIES]
157
 * PATH_TO_APPLICATION_HOME_DIRECTORY PATH_TO_APPLICATION_PLUGINS_DIRECTORY
158
 * [{list of additional custom application arguments separated by spaces}]
159
 * </p>
160
 * 
161
 * 
162
 * @author $author$
163
 * @version $Revision: 34114 $
164
 */
165
public class Launcher {
166

    
167
    protected static Logger logger =
168
        LoggerFactory.getLogger(Launcher.class.getName());
169
    protected static Preferences prefs = Preferences.userRoot()
170
        .node("gvsig.connection");
171
    protected static AndamiConfig andamiConfig;
172
    protected static MultiSplashWindow splashWindow;
173
    protected static String appName;
174
    protected static Locale locale;
175
    protected static HashMap pluginsConfig = new HashMap();
176
    protected static HashMap pluginsServices = new HashMap();
177
    protected static MDIFrame frame;
178
    protected static HashMap classesExtensions = new HashMap();
179
    protected static List<LibrariesInitializer> libInitializers;
180
    protected static String andamiConfigPath;
181
    protected static final String nonWinDefaultLookAndFeel =
182
        "com.jgoodies.looks.plastic.PlasticXPLookAndFeel";
183

    
184
    protected static ArrayList pluginsOrdered = new ArrayList();
185
    protected static ArrayList extensions = new ArrayList();
186
    protected static String appHomeDir = null;
187
    // it seems castor uses this encoding
188
    protected static final String CASTORENCODING = "UTF8";
189

    
190
    protected static ListBaseException launcherrors = null;
191

    
192
    private static final class ProxyAuth extends Authenticator {
193

    
194
        private PasswordAuthentication auth;
195

    
196
        private ProxyAuth(String user, String pass) {
197
            auth = new PasswordAuthentication(user, pass.toCharArray());
198
        }
199

    
200
        protected PasswordAuthentication getPasswordAuthentication() {
201
            return auth;
202
        }
203
    }
204

    
205
    public static void main(String[] args) throws Exception {
206
        Launcher launcher = new Launcher();
207
        launcher.doMain(args);
208
    }
209

    
210
    protected void downloadExtensions(String extDir) {
211
        // do nothing
212
    }
213

    
214
    public static class LaunchException extends ListBaseException {
215

    
216
        /**
217
                 * 
218
                 */
219
        private static final long serialVersionUID = 4541192746962684705L;
220

    
221
        public LaunchException() {
222
            super("Errors in initialization of application.",
223
                "_errors_in_initialization_of_application",
224
                serialVersionUID);
225
        }
226

    
227
    }
228

    
229
    protected void addError(Throwable ex) {
230
        if (launcherrors == null) {
231
            launcherrors = new LaunchException();
232
        }
233
        launcherrors.add(ex);
234
    }
235

    
236
    protected void addError(String msg, Throwable cause) {
237
        logger.error(msg, cause);
238
        this.addError(new RuntimeException(msg, cause));
239
    }
240

    
241
    protected void addError(String msg) {
242
        this.addError(msg, null);
243
    }
244

    
245
    public void doMain(String[] args) throws Exception {
246
        try {
247

    
248
            if (!validJVM()) {
249
                System.exit(-1);
250
            }
251

    
252
            if (args.length < 1) {
253
                System.err.println("Uso: Launcher appName plugins-directory [language=locale]");
254
            }
255

    
256
            LibrariesInitializer libsInitializer =
257
                new DefaultLibrariesInitializer();
258
            libsInitializer.initialize(true);
259

    
260
            // Clean temporal files
261
            Utilities.cleanUpTempFiles();
262

    
263
            appName = args[0];
264

    
265
            // Se crea el directorio de configuraci?n de la aplicaci?n
266
            appHomeDir = System.getProperty(args[0] + ".home");
267
            if (appHomeDir == null)
268
                appHomeDir = System.getProperty("user.home");
269

    
270
            appHomeDir += File.separator + args[0] + File.separator;
271
            File parent = new File(appHomeDir);
272
            parent.mkdirs();
273

    
274
            andamiConfigPath = appHomeDir + "andami-config.xml";
275

    
276
            // Configurar el log4j
277
            Launcher.class.getClassLoader().getResource(".");
278
            PropertyConfigurator.configure("log4j.properties");
279

    
280
            PatternLayout l = new PatternLayout("%p %t %C - %m%n");
281
            RollingFileAppender fa =
282
                new RollingFileAppender(l, appHomeDir + args[0] + ".log", false);
283
            fa.setMaxFileSize("512KB");
284
            fa.setMaxBackupIndex(3);
285
            org.apache.log4j.Logger.getRootLogger().addAppender(fa);
286

    
287
            // org.apache.log4j.Logger.getRootLogger().setLevel(Level.TRACE);
288

    
289
            // Leer el fichero de configuraci?n de andami (andami-config.xsd)
290
            // locale
291
            // Buscar actualizaci?nes al comenzar
292
            // Andami
293
            // Plugins
294
            // Directorio de las extensiones
295
            andamiConfigFromXML(andamiConfigPath);
296
            andamiConfig.setPluginsDirectory(args[1]);
297

    
298
            // Hacemos visibles los argumentos como una propiedad est?tica
299
            // de plugin services para quien lo quiera usar (por ejemplo, para
300
            // cargar un proyecto por l?nea de comandos)
301
            PluginServices.setArguments(args);
302

    
303
            configureLocales(args);
304

    
305
            // Se pone el lookAndFeel
306
            try {
307
                String lookAndFeel = getAndamiConfig().getLookAndFeel();
308
                if (lookAndFeel == null)
309
                    lookAndFeel = getDefaultLookAndFeel();
310
                UIManager.setLookAndFeel(lookAndFeel);
311
            } catch (Exception e) {
312
                logger.warn(Messages.getString("Launcher.look_and_feel"), e);
313
            }
314
            FontUtils.initFonts();
315

    
316
            // Solucionamos el problema de permisos que se produc?a con Java
317
            // Web Start con este c?digo.
318
            // System.setSecurityManager(null);
319
            Policy.setPolicy(new Policy() {
320

    
321
                public PermissionCollection getPermissions(CodeSource codesource) {
322
                    Permissions perms = new Permissions();
323
                    perms.add(new AllPermission());
324
                    return (perms);
325
                }
326

    
327
                public void refresh() {
328
                }
329
            });
330

    
331
            try {
332
                initIconThemes();
333
            } catch (Exception ex) {
334
                this.addError("Can't initialize icon theme", ex);
335
            }
336
            // Registramos los iconos base
337
            try {
338
                registerIcons();
339
            } catch (Exception ex) {
340
                this.addError("Can't register icons", ex);
341
            }
342
            validate();
343

    
344
            // Obtener la personalizaci?n de la aplicaci?n.
345
            Theme theme = null;
346
            try {
347
                theme = getTheme(andamiConfig.getPluginsDirectory());
348
            } catch (Exception ex) {
349
                this.addError("Can't get personalized theme for the application",
350
                    ex);
351
            }
352

    
353
            // Mostrar la ventana de inicio
354
            Frame f = new Frame();
355
            splashWindow = new MultiSplashWindow(f, theme, 190);
356

    
357
            // 1. Ponemos los datos del proxy
358
            splashWindow.process(10, PluginServices.getText(Launcher.class,
359
                "SplashWindow.configuring_proxy"));
360
            configureProxy();
361

    
362
            // 2. TODO Buscar actualizaciones de los plugins
363
            splashWindow.process(20, PluginServices.getText(Launcher.class,
364
                "SplashWindow.looking_for_updates"));
365
            try {
366
                this.downloadExtensions(andamiConfig.getPluginsDirectory());
367
            } catch (Exception ex) {
368
                this.addError("Can't downloads plugins", ex);
369
            }
370

    
371
            // 3. Se leen los config.xml de los plugins -----++++
372
            splashWindow.process(30, PluginServices.getText(Launcher.class,
373
                "SplashWindow.reading_plugins_config.xml"));
374
            try {
375
                this.loadPlugins(andamiConfig.getPluginsDirectory());
376
            } catch (Exception ex) {
377
                this.addError("Can't load plugins", ex);
378
            }
379

    
380
            // 4. Se configura el classloader del plugin
381
            splashWindow.process(40, PluginServices.getText(Launcher.class,
382
                "SplashWindow.setting_up_class_loaders"));
383
            try {
384
                this.pluginsClassLoaders();
385
            } catch (Exception ex) {
386
                this.addError("Can't initialize plugin's classloaders  ", ex);
387
            }
388

    
389
            // 5. Se carga un Skin si alguno de los plugins trae informaci?n
390
            // para ello
391
            splashWindow.process(50, PluginServices.getText(Launcher.class,
392
                "SplashWindow.looking_for_a_skin"));
393
            // skinPlugin( "com.iver.core.mdiManager.NewSkin");
394
            skinPlugin(null);
395

    
396
            // 6. Se configura la cola de eventos
397
            splashWindow.process(60,
398
                PluginServices.getText(Launcher.class, "setting_up_event_queue"));
399
            EventQueue waitQueue = new AndamiEventQueue();
400
            Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue);
401

    
402
            // 7. Se configura la mensajer?a del plugin
403
            splashWindow.process(70, PluginServices.getText(Launcher.class,
404
                "SplashWindow.starting_plugin_internationalization_system"));
405
            pluginsMessages();
406

    
407
            // 8. Se modifica el andami-config con los plugins nuevos
408
            splashWindow.process(80, PluginServices.getText(Launcher.class,
409
                "SplashWindow.looking_for_a_skin"));
410
            updateAndamiConfig();
411

    
412
            frame = new MDIFrame();
413
            // 9. Se configura el nombre e icono de la aplicaci?n
414
            splashWindow.process(90, PluginServices.getText(Launcher.class,
415
                "SplashWindow.setting_up_applications_name_and_icons"));
416
            frameIcon(theme);
417

    
418
            // 10. Se prepara el MainFrame para albergar las extensiones
419
            splashWindow.process(100, PluginServices.getText(Launcher.class,
420
                "SplashWindow.preparing_workbench"));
421
            JPopupMenu.setDefaultLightWeightPopupEnabled(false);
422

    
423
            SwingUtilities.invokeAndWait(new Runnable() {
424

    
425
                public void run() {
426
                    frame.init();
427
                }
428
            });
429

    
430
            // 11. Leer el fichero de persistencia
431
            // info de los plugins
432
            // bookmarks de los plugins
433
            splashWindow.process(110, PluginServices.getText(Launcher.class,
434
                "SplashWindow.loading_plugin_settings"));
435
            loadPluginsPersistence();
436

    
437
            // Se instalan los controles del skin
438
            // 12. Se inicializan todas las extensiones de todos los plugins
439
            splashWindow.process(120, PluginServices.getText(Launcher.class,
440
                "SplashWindow.initializing_extensions"));
441
            SwingUtilities.invokeAndWait(new Runnable() {
442

    
443
                public void run() {
444
                    initializeExtensions();
445
                }
446
            });
447

    
448
            // 13. Se inicializan la extensi?n exclusiva
449
            splashWindow.process(130, PluginServices.getText(Launcher.class,
450
                "SplashWindow.setting_up_master_extension"));
451
            SwingUtilities.invokeAndWait(new Runnable() {
452

    
453
                public void run() {
454
                    initializeExclusiveUIExtension();
455
                }
456
            });
457
            frame.setClassesExtensions(classesExtensions);
458

    
459
            // 14. Se instalan los controles de las extensiones de los plugins
460
            splashWindow.process(140, PluginServices.getText(Launcher.class,
461
                "SplashWindow.installing_extensions_controls"));
462
            SwingUtilities.invokeAndWait(new Runnable() {
463

    
464
                public void run() {
465
                    installPluginsControls();
466

    
467
                }
468
            });
469

    
470
            // 15. Se instalan los menus de las extensiones de los plugins
471
            splashWindow.process(150, PluginServices.getText(Launcher.class,
472
                "SplashWindow.installing_extensions_menus"));
473
            SwingUtilities.invokeAndWait(new Runnable() {
474

    
475
                public void run() {
476
                    installPluginsMenus();
477

    
478
                }
479
            });
480

    
481
            // 16. Se instalan las etiquetas de las extensiones de los plugins
482
            splashWindow.process(160, PluginServices.getText(Launcher.class,
483
                "SplashWindow.installing_extensions_labels"));
484
            SwingUtilities.invokeAndWait(new Runnable() {
485

    
486
                public void run() {
487
                    installPluginsLabels();
488

    
489
                }
490
            });
491

    
492
            // 17. Se instalan los bookmarks de los plugins
493

    
494
            // 18. Se muestra el frame principal
495
            splashWindow.process(180,
496
                PluginServices.getText(Launcher.class, "creating_main_window"));
497
            frame.setVisible(true);
498

    
499
            // 19. Se ejecuta el postInitialize
500
            splashWindow.process(190, PluginServices.getText(Launcher.class,
501
                "SplashWindow.post_initializing_extensions"));
502
            SwingUtilities.invokeAndWait(new Runnable() {
503

    
504
                public void run() {
505
                    postInitializeExtensions();
506

    
507
                }
508
            });
509

    
510
            // Definimos un KeyEventDispatcher global para que las extensiones
511
            // puedan registrar sus "teclas r?pidas".
512
            GlobalKeyEventDispatcher keyDispatcher =
513
                GlobalKeyEventDispatcher.getInstance();
514
            KeyboardFocusManager.getCurrentKeyboardFocusManager()
515
                .addKeyEventDispatcher(keyDispatcher);
516

    
517
            SwingUtilities.invokeAndWait(new Runnable() {
518

    
519
                public void run() {
520
                    frame.enableControls();
521
                }
522
            });
523
            splashWindow.close();
524
            if (launcherrors != null) {
525
                NotificationManager.addError(launcherrors);
526
            }
527
        } catch (Exception e) {
528
            logger.error("excepci?n al arrancar", e);
529
            System.exit(-1);
530
        }
531

    
532
    }
533

    
534
    /**
535
     * Return the directory applicaction is installed.
536
     */
537
    public static String getApplicationDirectory() {
538
        return new File("").getAbsolutePath();
539
    }
540

    
541
    private void registerIcons() {
542
        PluginServices.getIconTheme().registerDefault("login-gvsig",
543
            LoginUI.class.getClassLoader()
544
                .getResource("images/login_gvsig.png"));
545
        PluginServices.getIconTheme().registerDefault("splash-gvsig",
546
            MultiSplashWindow.class.getClassLoader()
547
                .getResource("images/splash.png"));
548
        PluginServices.getIconTheme().registerDefault("info-icon",
549
            NewStatusBar.class.getClassLoader().getResource("images/info.gif"));
550
        PluginServices.getIconTheme()
551
            .registerDefault("error-icon",
552
                NewStatusBar.class.getClassLoader()
553
                    .getResource("images/error.gif"));
554
        PluginServices.getIconTheme().registerDefault("warning-icon",
555
            NewStatusBar.class.getClassLoader()
556
                .getResource("images/warning.gif"));
557
        PluginServices.getIconTheme().registerDefault("no-icon",
558
            NewStatusBar.class.getClassLoader()
559
                .getResource("images/no_icon.png"));
560
    }
561

    
562
    /**
563
     * Obtiene la personalizaci?n de los iconos, splash, fondo y el nombre de
564
     * la aplicaci?n.
565
     * 
566
     * @return Theme
567
     */
568
    private Theme getTheme(String pluginsDirectory) {
569
        File themeFile;
570
        Theme theme = new Theme();
571

    
572
        // Try to get theme from args
573
        String name = PluginServices.getArgumentByName("andamiTheme");
574
        if (name != null) {
575
            themeFile = new File(name);
576
            logger.info("search andami-theme in {}",
577
                themeFile.getAbsolutePath());
578
            if (themeFile.exists()) {
579
                theme.readTheme(themeFile);
580
                logger.info("andami-theme found in {}",
581
                    themeFile.getAbsolutePath());
582
                return theme;
583
            }
584
        }
585

    
586
        // Try to get theme from a plugin
587
        File pluginsDir = new File(pluginsDirectory);
588
        if (pluginsDir.exists()) {
589
            logger.info("search andami-theme in plugins folder.");
590
            File[] pluginDirs = pluginsDir.listFiles();
591
            if (pluginDirs.length > 0) {
592
                for (int i = 0; i < pluginDirs.length; i++) {
593
                    themeFile =
594
                        new File(pluginDirs[i], "theme" + File.separator
595
                            + "andami-theme.xml");
596
                    if (themeFile.exists()) {
597
                        theme.readTheme(themeFile);
598
                        logger.info("andami-theme found in plugin {}",
599
                            themeFile.getAbsolutePath());
600
                        return theme;
601
                    }
602
                }
603
            }
604
        }
605

    
606
        // Try to get theme from dir gvSIG in user home
607
        themeFile =
608
            new File(getAppHomeDir(), "theme" + File.separator
609
                + "andami-theme.xml");
610
        logger.info("search andami-theme in user's home {}",
611
            themeFile.getAbsolutePath());
612
        if (themeFile.exists()) {
613
            theme.readTheme(themeFile);
614
            logger.info("andami-theme found in user's home {}",
615
                themeFile.getAbsolutePath());
616
            return theme;
617
        }
618

    
619
        // Try to get theme from the instalation dir of gvSIG.
620
        themeFile =
621
            new File(getApplicationDirectory(), "theme" + File.separator
622
                + "andami-theme.xml");
623
        logger.info("search andami-theme in installation folder {}",
624
            themeFile.getAbsolutePath());
625
        if (themeFile.exists()) {
626
            theme.readTheme(themeFile);
627
            logger.info("andami-theme found in instalation folder {}",
628
                themeFile.getAbsolutePath());
629
            return theme;
630
        }
631
        logger.info("Apply default andami-theme.");
632
        return theme;
633
    }
634

    
635
    /**
636
     * Establece los datos que ten?amos guardados respecto de la configuraci?n
637
     * del proxy.
638
     */
639
    private void configureProxy() {
640
        String host = prefs.get("firewall.http.host", "");
641
        String port = prefs.get("firewall.http.port", "");
642

    
643
        System.getProperties().put("http.proxyHost", host);
644
        System.getProperties().put("http.proxyPort", port);
645

    
646
        // Ponemos el usuario y clave del proxy, si existe
647
        String proxyUser = prefs.get("firewall.http.user", null);
648
        String proxyPassword = prefs.get("firewall.http.password", null);
649
        if (proxyUser != null) {
650
            System.getProperties().put("http.proxyUserName", proxyUser);
651
            System.getProperties().put("http.proxyPassword", proxyPassword);
652

    
653
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
654
        } else {
655
            Authenticator.setDefault(new ProxyAuth("", ""));
656
        }
657
    }
658

    
659
    /**
660
     * Recupera la geometr?a (tama?o, posic?n y estado) de la ventana principal
661
     * de Andami.
662
     * TODO Pendiente de ver como se asigna un pluginServices para el launcher.
663
     * 
664
     * @author LWS
665
     */
666
    private void restoreMDIStatus(XMLEntity xml) {
667
        if (xml == null)
668
            xml = new XMLEntity();
669
        // restore frame size
670
        Dimension sz = new Dimension(700, 580);
671
        if (xml.contains("MDIFrameSize")) {
672
            int[] wh = xml.getIntArrayProperty("MDIFrameSize");
673
            sz = new Dimension(wh[0], wh[1]);
674
        }
675
        frame.setSize(sz);
676
        // restore frame location
677
        Point pos = new Point(10, 10);
678
        if (xml.contains("MDIFramePos")) {
679
            int[] xy = xml.getIntArrayProperty("MDIFramePos");
680
            pos = new Point(xy[0], xy[1]);
681
        }
682
        frame.setLocation(pos);
683

    
684
        // restore frame status (Maximized, minimized, etc);
685
        int state = java.awt.Frame.MAXIMIZED_BOTH;
686
        if (xml.contains("MDIFrameState")) {
687
            state = xml.getIntProperty("MDIFrameState");
688
        }
689
        frame.setExtendedState(state);
690
    }
691

    
692
    private XMLEntity saveMDIStatus() {
693
        XMLEntity xml = new XMLEntity();
694
        // save frame size
695
        int[] wh = new int[2];
696
        wh[0] = frame.getWidth();
697
        wh[1] = frame.getHeight();
698
        xml.putProperty("MDIFrameSize", wh);
699
        // save frame location
700
        int[] xy = new int[2];
701
        xy[0] = frame.getX();
702
        xy[1] = frame.getY();
703
        xml.putProperty("MDIFramePos", xy);
704
        // save frame status
705
        xml.putProperty("MDIFrameState", frame.getExtendedState());
706
        return xml;
707
    }
708

    
709
    private boolean validJVM() {
710
        char thirdCharacter = System.getProperty("java.version").charAt(2);
711
        if (thirdCharacter < '4') {
712
            return false;
713
        } else {
714
            return true;
715
        }
716
    }
717

    
718
    private void loadPluginsPersistence() throws ConfigurationException {
719
        XMLEntity entity = persistenceFromXML();
720

    
721
        for (int i = 0; i < entity.getChildrenCount(); i++) {
722
            XMLEntity plugin = entity.getChild(i);
723
            String pName =
724
                plugin.getStringProperty("com.iver.andami.pluginName");
725

    
726
            if (pName.compareToIgnoreCase("com.iver.cit.gvsig") == 0) {
727
                pName = "org.gvsig.app";
728
            }
729
            if (pluginsServices.get(pName) != null) {
730
                ((PluginServices) pluginsServices.get(pName)).setPersistentXML(plugin);
731
            } else {
732
                if (pName.startsWith("Andami.Launcher"))
733
                    restoreMDIStatus(plugin);
734
            }
735
        }
736
    }
737

    
738
    /**
739
     * Salva la persistencia de los plugins.
740
     * 
741
     * @author LWS
742
     */
743
    private void savePluginPersistence() {
744
        Iterator i = pluginsConfig.keySet().iterator();
745

    
746
        XMLEntity entity = new XMLEntity();
747

    
748
        while (i.hasNext()) {
749
            String pName = (String) i.next();
750
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
751
            XMLEntity ent = ps.getPersistentXML();
752

    
753
            if (ent != null) {
754
                ent.putProperty("com.iver.andami.pluginName", pName);
755
                entity.addChild(ent);
756
            }
757
        }
758
        XMLEntity ent = saveMDIStatus();
759
        if (ent != null) {
760
            ent.putProperty("com.iver.andami.pluginName", "Andami.Launcher");
761
            entity.addChild(ent);
762
        }
763
        try {
764
            persistenceToXML(entity);
765
        } catch (ConfigurationException e1) {
766
            this.addError(Messages.getString("Launcher.Se_produjo_un_error_guardando_la_configuracion_de_los_plugins"),
767
                e1);
768
        }
769
    }
770

    
771
    private void installPluginsLabels() {
772
        Iterator i = pluginsConfig.keySet().iterator();
773

    
774
        while (i.hasNext()) {
775
            String name = (String) i.next();
776
            PluginConfig pc = (PluginConfig) pluginsConfig.get(name);
777
            PluginServices ps = (PluginServices) pluginsServices.get(name);
778

    
779
            LabelSet[] ls = pc.getLabelSet();
780

    
781
            for (int j = 0; j < ls.length; j++) {
782
                PluginClassLoader loader = ps.getClassLoader();
783

    
784
                try {
785
                    Class clase = loader.loadClass(ls[j].getClassName());
786
                    frame.setStatusBarLabels(clase, ls[j].getLabel());
787
                } catch (ClassNotFoundException e) {
788
                    this.addError(Messages.getString("Launcher.labelset_class"),
789
                        e);
790
                }
791
            }
792
        }
793
    }
794

    
795
    private String configureSkin(XMLEntity xml, String defaultSkin) {
796
        if (defaultSkin == null) {
797
            for (int i = 0; i < xml.getChildrenCount(); i++) {
798
                if (xml.getChild(i).contains("Skin-Selected")) {
799
                    String className =
800
                        xml.getChild(i).getStringProperty("Skin-Selected");
801
                    return className;
802
                }
803
            }
804
        }
805
        // return "com.iver.core.mdiManager.NewSkin";
806
        return defaultSkin;
807
    }
808

    
809
    private void fixSkin(SkinExtension skinExtension,
810
        PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
811
        // now insert the skin selected.
812
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
813
        // MDIManagerFactory.setSkinExtension(se,
814
        // ps.getClassLoader());
815

    
816
        Class skinClass;
817

    
818
        try {
819
            skinClass =
820
                pluginClassLoader.loadClass(skinExtension.getClassName());
821

    
822
            org.gvsig.andami.plugins.IExtension skinInstance =
823
                (org.gvsig.andami.plugins.IExtension) skinClass.newInstance();
824
            // classesExtensions.put(skinClass, skinInstance);
825
            // jaume
826
            ExtensionDecorator newExtensionDecorator =
827
                new ExtensionDecorator(skinInstance,
828
                    ExtensionDecorator.INACTIVE);
829
            classesExtensions.put(skinClass, newExtensionDecorator);
830
        } catch (ClassNotFoundException e) {
831
            logger.error(Messages.getString("Launcher.No_se_encontro_la_clase_mdi_manager"),
832
                e);
833
            throw new MDIManagerLoadException(e);
834
        } catch (InstantiationException e) {
835
            logger.error(Messages.getString("Launcher.No_se_pudo_instanciar_la_clase_mdi_manager"),
836
                e);
837
            throw new MDIManagerLoadException(e);
838
        } catch (IllegalAccessException e) {
839
            logger.error(Messages.getString("Launcher.No_se_pudo_acceder_a_la_clase_mdi_manager"),
840
                e);
841
            throw new MDIManagerLoadException(e);
842
        }
843

    
844
    }
845

    
846
    /**
847
     * DOCUMENT ME!
848
     * 
849
     * @throws MDIManagerLoadException
850
     */
851
    private void skinPlugin(String defaultSkin) throws MDIManagerLoadException {
852
        XMLEntity entity = null;
853
        try {
854
            entity = persistenceFromXML();
855
        } catch (ConfigurationException e1) {
856
            // TODO Auto-generated catch block
857
            e1.printStackTrace();
858
        }
859
        Iterator i = pluginsConfig.keySet().iterator();
860

    
861
        SkinExtension skinExtension = null;
862
        PluginClassLoader pluginClassLoader = null;
863
        ArrayList skinExtensions = new ArrayList();
864
        while (i.hasNext()) {
865
            String name = (String) i.next();
866
            PluginConfig pc = (PluginConfig) pluginsConfig.get(name);
867
            PluginServices ps = (PluginServices) pluginsServices.get(name);
868

    
869
            if (pc.getExtensions().getSkinExtension() != null) {
870
                // if (MDIManagerFactory.getSkinExtension() != null) {
871
                // logger.warn(Messages.getString(
872
                // "Launcher.Dos_skin_extension"));
873
                // }
874

    
875
                SkinExtension[] se = pc.getExtensions().getSkinExtension();
876
                for (int numExten = 0; numExten < se.length; numExten++) {
877
                    skinExtensions.add(se[numExten]);
878
                }
879
                for (int j = 0; j < se.length; j++) {
880
                    String configuredSkin =
881
                        this.configureSkin(entity, defaultSkin);
882
                    if (configuredSkin != null
883
                        && configuredSkin.equals(se[j].getClassName())) {
884
                        skinExtension = se[j];
885
                        pluginClassLoader = ps.getClassLoader();
886
                    }
887
                }
888
            }
889
        }
890

    
891
        if ((skinExtension != null) && (pluginClassLoader != null)) {
892
            // configured skin was found
893
            fixSkin(skinExtension, pluginClassLoader);
894
        } else {
895
            if (skinExtensions.contains("com.iver.core.mdiManager.NewSkin")) {
896
                // try first NewSkin (from CorePlugin)
897
                skinPlugin("com.iver.core.mdiManager.NewSkin");
898
            } else
899
                if (skinExtensions.size() > 0) {
900
                    // try to load the first skin found
901
                    SkinExtension se = (SkinExtension) skinExtensions.get(0);
902
                    skinPlugin((String) se.getClassName());
903
                } else {
904
                    throw new MDIManagerLoadException("No Skin-Extension installed");
905
                }
906
        }
907

    
908
    }
909

    
910
    private static void frameIcon(Theme theme) {
911
        Iterator i = pluginsConfig.keySet().iterator();
912

    
913
        while (i.hasNext()) {
914
            String pName = (String) i.next();
915
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
916
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
917
            if (pc.getIcon() != null) {
918
                if (theme.getIcon() != null) {
919
                    frame.setIconImage(theme.getIcon().getImage());
920
                } else {
921

    
922
                    ImageIcon icon =
923
                        PluginServices.getIconTheme()
924
                            .get(pc.getIcon().getSrc());
925
                    frame.setIconImage(icon.getImage());
926

    
927
                }
928
                if (theme.getName() != null) {
929
                    frame.setTitlePrefix(theme.getName());
930
                } else {
931
                    frame.setTitlePrefix(pc.getIcon().getText());
932
                }
933
                if (theme.getBackgroundImage() != null) {
934

    
935
                    PluginServices.getMDIManager()
936
                        .setBackgroundImage(theme.getBackgroundImage(),
937
                            theme.getTypeDesktop());
938
                }
939
            }
940
        }
941
    }
942

    
943
    private void initializeExtensions() {
944

    
945
        libInitializers =
946
            new ArrayList<LibrariesInitializer>(pluginsOrdered.size());
947

    
948
        Iterator i = pluginsOrdered.iterator();
949

    
950
        logger.debug("Initializing plugins: ");
951
        while (i.hasNext()) {
952
            String pName = (String) i.next();
953
            logger.debug("Initializing plugin " + pName);
954
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
955
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
956

    
957
            // Create the libraries initializer and
958
            // initialize the plugin libraries
959
            LibrariesInitializer libsInitializer =
960
                new DefaultLibrariesInitializer(ps.getClassLoader());
961
            libsInitializer.initialize(true);
962
            libInitializers.add(libsInitializer);
963

    
964
            Extension[] exts = pc.getExtensions().getExtension();
965

    
966
            TreeMap orderedExtensions = new TreeMap(new ExtensionComparator());
967

    
968
            for (int j = 0; j < exts.length; j++) {
969
                if (!exts[j].getActive()) {
970
                    continue;
971
                }
972

    
973
                if (orderedExtensions.containsKey(exts[j])) {
974
                    logger.warn("Two extensions with the same priority ("
975
                        + exts[j].getClassName() + ")");
976
                }
977

    
978
                orderedExtensions.put(exts[j], null);
979
            }
980

    
981
            Iterator e = orderedExtensions.keySet().iterator();
982

    
983
            logger.info("Initializing extensions: ");
984
            while (e.hasNext()) {
985
                Extension extension = (Extension) e.next();
986
                org.gvsig.andami.plugins.IExtension extensionInstance;
987

    
988
                try {
989
                    Class extensionClass =
990
                        ps.getClassLoader().loadClass(extension.getClassName());
991
                    extensionInstance =
992
                        (org.gvsig.andami.plugins.IExtension) extensionClass.newInstance();
993

    
994
                    // CON DECORATOR
995
                    // ANTES: classesExtensions.put(extensionClass,
996
                    // extensionInstance);
997
                    // AHORA: CREAMOS UNA ExtensionDecorator y asignamos esta
998
                    // instancia para
999
                    // poder ampliar con nuevas propiedades (AlwaysVisible, por
1000
                    // ejemplo)
1001
                    // Para crear la nueva clase ExtensionDecorator, le pasamos
1002
                    // como par?metro
1003
                    // la extensi?n original que acabamos de crear
1004
                    // 0-> Inactivo, controla la extension
1005
                    // 1-> Siempre visible
1006
                    // 2-> Invisible
1007
                    ExtensionDecorator newExtensionDecorator =
1008
                        new ExtensionDecorator(extensionInstance,
1009
                            ExtensionDecorator.INACTIVE);
1010
                    classesExtensions.put(extensionClass, newExtensionDecorator);
1011
                    logger.info("Initializing " + extension.getClassName()
1012
                        + "...");
1013
                    // logger.debug("Initializing " + extension.getClassName());
1014

    
1015
                    // AQUI
1016

    
1017
                    extensionInstance.initialize();
1018
                    extensions.add(extensionInstance);
1019
                    // logger.debug(extension.getClassName() + " initialized.");
1020

    
1021
                } catch (NoClassDefFoundError e1) {
1022
                    this.addError("Can't found class extension ("
1023
                        + extension.getClassName() + ")",
1024
                        e1);
1025
                } catch (Throwable e1) {
1026
                    this.addError("Can't initialize extension '"
1027
                        + extension.getClassName() + "'.",
1028
                        e1);
1029
                }
1030
            }
1031
        }
1032
    }
1033

    
1034
    private void postInitializeExtensions() {
1035
        // Post initialize all plugin libraries
1036
        for (int i = 0; i < libInitializers.size(); i++) {
1037
            libInitializers.get(i).postInitialize(true);
1038
        }
1039
        // Remove them all, we don't need them anymore
1040
        libInitializers.clear();
1041
        libInitializers = null;
1042

    
1043
        logger.info("PostInitializing extensions: ");
1044

    
1045
        for (int i = 0; i < extensions.size(); i++) {
1046
            org.gvsig.andami.plugins.IExtension extensionInstance =
1047
                (org.gvsig.andami.plugins.IExtension) extensions.get(i);
1048
            logger.info("PostInitializing "
1049
                + extensionInstance.getClass().getName() + "...");
1050
            try {
1051
                extensionInstance.postInitialize();
1052
            } catch (Throwable ex) {
1053
                this.addError("postInitialize of extension '"
1054
                    + extensionInstance.getClass().getName() + "' failed", ex);
1055
            }
1056
        }
1057
    }
1058

    
1059
    private void installPluginsMenus() {
1060
        TreeMap orderedMenus = new TreeMap(new MenuComparator());
1061

    
1062
        Iterator i = pluginsConfig.keySet().iterator();
1063

    
1064
        while (i.hasNext()) {
1065
            String pName = (String) i.next();
1066
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1067
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1068

    
1069
            Extension[] exts = pc.getExtensions().getExtension();
1070

    
1071
            for (int j = 0; j < exts.length; j++) {
1072
                if (!exts[j].getActive()) {
1073
                    continue;
1074
                }
1075

    
1076
                Menu[] menus = exts[j].getMenu();
1077

    
1078
                for (int k = 0; k < menus.length; k++) {
1079
                    SortableMenu sm =
1080
                        new SortableMenu(ps.getClassLoader(), exts[j], menus[k]);
1081

    
1082
                    if (orderedMenus.containsKey(sm)) {
1083
                        this.addError(Messages.getString("Launcher.Two_menus_with_the_same_position")
1084
                            + " - "
1085
                            + menus[k].getText()
1086
                            + " - "
1087
                            + exts[j].getClassName());
1088
                    }
1089

    
1090
                    orderedMenus.put(sm, null);
1091
                }
1092
            }
1093

    
1094
            // Se instalan las extensiones de MDI
1095
            SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1096
            for (int j = 0; j < skinExts.length; j++) {
1097

    
1098
                if (skinExts[j] != null) {
1099
                    Menu[] menu = skinExts[j].getMenu();
1100

    
1101
                    for (int k = 0; k < menu.length; k++) {
1102
                        SortableMenu sm =
1103
                            new SortableMenu(ps.getClassLoader(),
1104
                                skinExts[j],
1105
                                menu[k]);
1106

    
1107
                        if (orderedMenus.containsKey(sm)) {
1108
                            this.addError(Messages.getString("Launcher.Two_menus_with_the_same_position")
1109
                                + skinExts[j].getClassName());
1110
                        }
1111

    
1112
                        orderedMenus.put(sm, null);
1113
                    }
1114
                }
1115
            }
1116
        }
1117

    
1118
        // Se itera por los menus ordenados
1119
        Iterator e = orderedMenus.keySet().iterator();
1120

    
1121
        // Se ordenan los menues
1122
        while (e.hasNext()) {
1123
            try {
1124
                SortableMenu sm = (SortableMenu) e.next();
1125

    
1126
                frame.addMenu(sm.loader, sm.extension, sm.menu);
1127
            } catch (ClassNotFoundException ex) {
1128
                this.addError(Messages.getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1129
                    ex);
1130
            }
1131
        }
1132
    }
1133

    
1134
    /**
1135
     * Installs the menus, toolbars, actiontools, selectable toolbars and
1136
     * combos.
1137
     * The order in which they are shown is determined here.
1138
     */
1139
    private void installPluginsControls() {
1140
        Iterator i = pluginsConfig.keySet().iterator();
1141

    
1142
        HashMap extensionPluginServices = new HashMap();
1143
        HashMap extensionPluginConfig = new HashMap();
1144
        TreeMap orderedExtensions = new TreeMap(new ExtensionComparator());
1145

    
1146
        // First of all, sort the extensions.
1147
        // We need to iterate on the plugins, and iterate on each plugin's
1148
        // extensions
1149
        // (each plugin may contain one or more extensions)
1150
        while (i.hasNext()) { // iterate on the plugins
1151
            String pName = (String) i.next();
1152
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1153
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1154

    
1155
            Extension[] exts = pc.getExtensions().getExtension();
1156

    
1157
            for (int j = 0; j < exts.length; j++) { // iterate on the extensions
1158
                if (exts[j].getActive()) {
1159
                    if (orderedExtensions.containsKey(exts[j])) {
1160
                        this.addError(Messages.getString("Launcher.Two_extensions_with_the_same_priority")
1161
                            + exts[j].getClassName());
1162
                    }
1163

    
1164
                    orderedExtensions.put(exts[j], null);
1165
                    extensionPluginServices.put(exts[j], ps);
1166
                    extensionPluginConfig.put(exts[j], pc);
1167
                }
1168
            }
1169
        }
1170

    
1171
        TreeMap orderedTools = new TreeMap(new ToolComparator());
1172
        Iterator e = orderedExtensions.keySet().iterator();
1173

    
1174
        // sort the toolbars and tools from 'normal' extensions (actiontools,
1175
        // selectabletools)
1176
        // and load the combo-scales and combo-buttons for the status bar
1177
        while (e.hasNext()) {
1178
            Extension ext = (Extension) e.next();
1179

    
1180
            ToolBar[] toolbars = ext.getToolBar();
1181

    
1182
            // get tools from toolbars
1183
            for (int k = 0; k < toolbars.length; k++) {
1184
                ActionTool[] tools = toolbars[k].getActionTool();
1185

    
1186
                for (int t = 0; t < tools.length; t++) {
1187
                    SortableTool sm =
1188
                        new SortableTool(((PluginServices) extensionPluginServices.get(ext)).getClassLoader(),
1189
                            ext,
1190
                            toolbars[k],
1191
                            tools[t]);
1192
                    orderedTools.put(sm, null);
1193
                }
1194

    
1195
                SelectableTool[] sTools = toolbars[k].getSelectableTool();
1196

    
1197
                for (int t = 0; t < sTools.length; t++) {
1198
                    SortableTool sm =
1199
                        new SortableTool(((PluginServices) extensionPluginServices.get(ext)).getClassLoader(),
1200
                            ext,
1201
                            toolbars[k],
1202
                            sTools[t]);
1203
                    orderedTools.put(sm, null);
1204
                }
1205
            }
1206

    
1207
            // get controls for statusBar
1208
            PluginServices ps =
1209
                (PluginServices) extensionPluginServices.get(ext);
1210
            PluginClassLoader loader = ps.getClassLoader();
1211

    
1212
            // ArrayList componentList = new ArrayList();
1213
            ComboScale[] comboScaleArray = ext.getComboScale();
1214
            for (int k = 0; k < comboScaleArray.length; k++) {
1215
                org.gvsig.gui.beans.controls.comboscale.ComboScale combo =
1216
                    new org.gvsig.gui.beans.controls.comboscale.ComboScale();
1217
                String label = comboScaleArray[k].getLabel();
1218
                if (label != null)
1219
                    combo.setLabel(label);
1220
                String name = comboScaleArray[k].getName();
1221
                if (name != null)
1222
                    combo.setName(name);
1223
                String[] elementsString =
1224
                    ((String) comboScaleArray[k].getElements()).split(";");
1225
                long[] elements = new long[elementsString.length];
1226
                for (int currentElem = 0; currentElem < elementsString.length; currentElem++) {
1227
                    try {
1228
                        elements[currentElem] =
1229
                            Long.parseLong(elementsString[currentElem]);
1230
                    } catch (NumberFormatException nfex1) {
1231
                        this.addError(ext.getClassName()
1232
                            + " -- "
1233
                            + Messages.getString("error_parsing_comboscale_elements"));
1234
                        elements[currentElem] = 0;
1235
                    }
1236
                }
1237
                combo.setItems(elements);
1238
                try {
1239
                    long value =
1240
                        Long.parseLong((String) comboScaleArray[k].getValue());
1241
                    combo.setScale(value);
1242
                } catch (NumberFormatException nfex2) {
1243
                    this.addError(ext.getClassName() + " -- "
1244
                        + Messages.getString("error_parsing_comboscale_value"));
1245
                }
1246
                try {
1247
                    frame.addStatusBarControl(loader.loadClass(ext.getClassName()),
1248
                        combo);
1249
                } catch (ClassNotFoundException e1) {
1250
                    this.addError(Messages.getString("Launcher.error_getting_class_loader_for_status_bar_control"),
1251
                        e1);
1252
                }
1253
            }
1254

    
1255
            ComboButton[] comboButtonArray = ext.getComboButton();
1256
            for (int k = 0; k < comboButtonArray.length; k++) {
1257
                ComboButtonElement[] elementList =
1258
                    comboButtonArray[k].getComboButtonElement();
1259
                org.gvsig.gui.beans.controls.combobutton.ComboButton combo =
1260
                    new org.gvsig.gui.beans.controls.combobutton.ComboButton();
1261
                String name = comboButtonArray[k].getName();
1262
                if (name != null)
1263
                    combo.setName(name);
1264
                for (int currentElement = 0; currentElement < elementList.length; currentElement++) {
1265
                    ComboButtonElement element = elementList[currentElement];
1266
                    ImageIcon icon;
1267
                    URL iconLocation = loader.getResource(element.getIcon());
1268
                    if (iconLocation == null)
1269
                        this.addError(Messages.getString("Icon_not_found_")
1270
                            + element.getIcon());
1271
                    else {
1272
                        icon = new ImageIcon(iconLocation);
1273
                        JButton button = new JButton(icon);
1274
                        combo.addButton(button);
1275
                        button.setActionCommand(element.getActionCommand());
1276
                    }
1277
                }
1278
                try {
1279
                    frame.addStatusBarControl(loader.loadClass(ext.getClassName()),
1280
                        combo);
1281
                } catch (ClassNotFoundException e1) {
1282
                    this.addError(Messages.getString("Launcher.error_getting_class_loader_for_status_bar_control"),
1283
                        e1);
1284
                }
1285
            }
1286
        }
1287

    
1288
        // Add the tools from MDI extensions to the ordered tool-list, so that
1289
        // we get a sorted list containing all the tools
1290
        i = pluginsConfig.keySet().iterator();
1291
        while (i.hasNext()) {
1292
            String pName = (String) i.next();
1293
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1294
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1295

    
1296
            SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1297
            for (int j = 0; j < skinExts.length; j++) {
1298

    
1299
                if (skinExts[j] != null) {
1300
                    ToolBar[] toolbars = skinExts[j].getToolBar();
1301

    
1302
                    for (int k = 0; k < toolbars.length; k++) {
1303
                        ActionTool[] tools = toolbars[k].getActionTool();
1304

    
1305
                        for (int t = 0; t < tools.length; t++) {
1306
                            SortableTool stb =
1307
                                new SortableTool(ps.getClassLoader(),
1308
                                    skinExts[j],
1309
                                    toolbars[k],
1310
                                    tools[t]);
1311
                            orderedTools.put(stb, null);
1312
                        }
1313

    
1314
                        SelectableTool[] sTools =
1315
                            toolbars[k].getSelectableTool();
1316

    
1317
                        for (int t = 0; t < sTools.length; t++) {
1318
                            SortableTool stb =
1319
                                new SortableTool(ps.getClassLoader(),
1320
                                    skinExts[j],
1321
                                    toolbars[k],
1322
                                    sTools[t]);
1323
                            orderedTools.put(stb, null);
1324
                        }
1325
                    }
1326
                }
1327
            }
1328
            // Install popup menus
1329
            PopupMenus pus = pc.getPopupMenus();
1330

    
1331
            if (pus != null) {
1332
                PopupMenu[] menus = pus.getPopupMenu();
1333

    
1334
                for (int j = 0; j < menus.length; j++) {
1335
                    frame.addPopupMenu(ps.getClassLoader(), menus[j]);
1336
                }
1337
            }
1338
        }
1339

    
1340
        // loop on the ordered extension list, to add them to the interface in
1341
        // an ordered way
1342
        Iterator t = orderedTools.keySet().iterator();
1343
        while (t.hasNext()) {
1344
            try {
1345
                SortableTool stb = (SortableTool) t.next();
1346
                if (stb.actiontool != null)
1347
                    frame.addTool(stb.loader,
1348
                        stb.extension,
1349
                        stb.toolbar,
1350
                        stb.actiontool);
1351
                else
1352
                    frame.addTool(stb.loader,
1353
                        stb.extension,
1354
                        stb.toolbar,
1355
                        stb.selectabletool);
1356
            } catch (ClassNotFoundException ex) {
1357
                this.addError(Messages.getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1358
                    ex);
1359
            }
1360
        }
1361
    }
1362

    
1363
    /**
1364
     * Adds new plugins to the the andami-config file.
1365
     */
1366
    private void updateAndamiConfig() {
1367
        HashSet olds = new HashSet();
1368

    
1369
        Plugin[] plugins = andamiConfig.getPlugin();
1370

    
1371
        for (int i = 0; i < plugins.length; i++) {
1372
            olds.add(plugins[i].getName());
1373
        }
1374

    
1375
        Iterator i = pluginsServices.values().iterator();
1376

    
1377
        while (i.hasNext()) {
1378
            PluginServices ps = (PluginServices) i.next();
1379

    
1380
            if (!olds.contains(ps.getPluginName())) {
1381
                Plugin p = new Plugin();
1382
                p.setName(ps.getPluginName());
1383
                p.setUpdate(false);
1384

    
1385
                andamiConfig.addPlugin(p);
1386
            }
1387
        }
1388
    }
1389

    
1390
    private void pluginsClassLoaders() {
1391
        HashSet instalados = new HashSet();
1392

    
1393
        // Se itera hasta que est?n todos instalados
1394
        while (instalados.size() != pluginsConfig.size()) {
1395
            boolean circle = true;
1396

    
1397
            // Hacemos una pasada por todos los plugins
1398
            Iterator i = pluginsConfig.keySet().iterator();
1399

    
1400
            while (i.hasNext()) {
1401
                String pluginName = (String) i.next();
1402
                PluginConfig config =
1403
                    (PluginConfig) pluginsConfig.get(pluginName);
1404

    
1405
                if (instalados.contains(pluginName)) {
1406
                    continue;
1407
                }
1408

    
1409
                // Se obtienen las dependencias y sus class loaders
1410
                boolean ready = true;
1411
                Depends[] dependencies = config.getDepends();
1412
                PluginClassLoader[] loaders =
1413
                    new PluginClassLoader[dependencies.length];
1414

    
1415
                for (int j = 0; j < dependencies.length; j++) {
1416
                    if (pluginsConfig.get(dependencies[j].getPluginName()) == null) {
1417
                        this.addError(Messages.getString("Launcher.Dependencia_no_resuelta_en_plugin")
1418
                            + " "
1419
                            + pluginName
1420
                            + ": "
1421
                            + dependencies[j].getPluginName());
1422

    
1423
                        continue;
1424
                    }
1425

    
1426
                    if (!instalados.contains(dependencies[j].getPluginName())) {
1427
                        ready = false;
1428
                    } else {
1429
                        loaders[j] =
1430
                            ((PluginServices) pluginsServices.get(dependencies[j].getPluginName())).getClassLoader();
1431
                    }
1432
                }
1433

    
1434
                // Si no est?n sus dependencias satisfechas se aborta la
1435
                // instalaci?n
1436
                if (!ready) {
1437
                    continue;
1438
                }
1439

    
1440
                // Se genera el class loader
1441
                String jardir = config.getLibraries().getLibraryDir();
1442
                File jarDir =
1443
                    new File(andamiConfig.getPluginsDirectory()
1444
                        + File.separator + pluginName + File.separator + jardir);
1445
                File[] jarFiles = jarDir.listFiles(new FileFilter() {
1446

    
1447
                    public boolean accept(File pathname) {
1448
                        return (pathname.getName().toUpperCase().endsWith(".JAR"))
1449
                            || (pathname.getName().toUpperCase().endsWith(".ZIP"));
1450
                    }
1451
                });
1452

    
1453
                URL[] urls = new URL[jarFiles.length];
1454

    
1455
                for (int j = 0; j < jarFiles.length; j++) {
1456
                    try {
1457
                        urls[j] = new URL("file:" + jarFiles[j]);
1458
                    } catch (MalformedURLException e) {
1459
                        this.addError(Messages.getString("Launcher.No_se_puede_acceder_a")
1460
                            + " " + jarFiles[j]);
1461
                    }
1462
                }
1463

    
1464
                PluginClassLoader loader;
1465

    
1466
                try {
1467
                    loader =
1468
                        new PluginClassLoader(urls,
1469
                            andamiConfig.getPluginsDirectory() + File.separator
1470
                                + pluginName,
1471
                            Launcher.class.getClassLoader(),
1472
                            loaders);
1473

    
1474
                    PluginServices ps = new PluginServices(loader);
1475

    
1476
                    pluginsServices.put(ps.getPluginName(), ps);
1477

    
1478
                    instalados.add(pluginName);
1479
                    // FJP: Los metemos ordenados para luego no cargar uno que
1480
                    // necesita de otro antes de tiempo. Esto lo usaremos al
1481
                    // inicializar los plugins
1482
                    pluginsOrdered.add(pluginName);
1483

    
1484
                    circle = false;
1485
                } catch (IOException e) {
1486
                    this.addError(Messages.getString("Launcher.Error_con_las_librerias_del_plugin"),
1487
                        e);
1488
                    pluginsConfig.remove(pluginName);
1489
                    i = pluginsConfig.keySet().iterator();
1490
                }
1491
            }
1492

    
1493
            if (circle) {
1494
                this.addError(Messages.getString("Launcher.Hay_dependencias_circulares"));
1495

    
1496
                break;
1497
            }
1498
        }
1499

    
1500
        // Se eliminan los plugins que no fueron instalados
1501
        Iterator i = pluginsConfig.keySet().iterator();
1502

    
1503
        while (i.hasNext()) {
1504
            String pluginName = (String) i.next();
1505
            PluginConfig config = (PluginConfig) pluginsConfig.get(pluginName);
1506
            PluginServices ps =
1507
                (PluginServices) pluginsServices.get(pluginName);
1508

    
1509
            if (ps == null) {
1510
                pluginsConfig.remove(pluginName);
1511
                i = pluginsConfig.keySet().iterator();
1512
            }
1513
        }
1514
    }
1515

    
1516
    private void pluginsMessages() {
1517
        Iterator iterator = pluginsOrdered.iterator();
1518
        PluginConfig config;
1519
        PluginServices ps;
1520

    
1521
        while (iterator.hasNext()) {
1522
            String pluginName = (String) iterator.next();
1523
            config = (PluginConfig) pluginsConfig.get(pluginName);
1524
            ps = (PluginServices) pluginsServices.get(pluginName);
1525

    
1526
            if (config.getResourceBundle() != null
1527
                && !config.getResourceBundle().getName().equals("")) {
1528
                // add the locale files associated with the plugin
1529
                org.gvsig.i18n.Messages.addResourceFamily(config.getResourceBundle()
1530
                    .getName(),
1531
                    ps.getClassLoader(),
1532
                    pluginName);
1533
            }
1534
        }
1535
    }
1536

    
1537
    static public PluginServices getPluginServices(String name) {
1538
        return (PluginServices) pluginsServices.get(name);
1539
    }
1540

    
1541
    static String getPluginsDir() {
1542
        return andamiConfig.getPluginsDirectory();
1543
    }
1544

    
1545
    static void setPluginsDir(String s) {
1546
        andamiConfig.setPluginsDirectory(s);
1547
    }
1548

    
1549
    static MDIFrame getMDIFrame() {
1550
        return frame;
1551
    }
1552

    
1553
    private void loadPlugins(String pluginsDirectory) {
1554
        File pDir = new File(pluginsDirectory);
1555

    
1556
        if (!pDir.exists()) {
1557
            logger.error("\n\tPlugins directory not found: "
1558
                + pDir.getAbsolutePath()
1559
                + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1560
            System.exit(-1);
1561
            return;
1562
        }
1563

    
1564
        File[] pluginDirs = pDir.listFiles();
1565
        if (pluginDirs.length == 0) {
1566
            logger.error("\n\tPlugins directory is empty: "
1567
                + pDir.getAbsolutePath()
1568
                + "Did you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1569
            System.exit(-1);
1570
            return;
1571
        }
1572

    
1573
        for (int i = 0; i < pluginDirs.length; i++) {
1574
            if (pluginDirs[i].isDirectory()) {
1575
                File configXml =
1576
                    new File(pluginDirs[i].getAbsolutePath() + File.separator
1577
                        + "config.xml");
1578

    
1579
                try {
1580
                    FileInputStream is = new FileInputStream(configXml);
1581
                    Reader xml =
1582
                        org.gvsig.utils.xml.XMLEncodingUtils.getReader(is);
1583
                    if (xml == null) {
1584
                        // the encoding was not correctly detected, use system
1585
                        // default
1586
                        xml = new FileReader(configXml);
1587
                    } else {
1588
                        // use a buffered reader to improve performance
1589
                        xml = new BufferedReader(xml);
1590
                    }
1591
                    PluginConfig pConfig =
1592
                        (PluginConfig) PluginConfig.unmarshal(xml);
1593
                    pluginsConfig.put(pluginDirs[i].getName(), pConfig);
1594
                } catch (FileNotFoundException e) {
1595
                    logger.info("Plugin folder without config.xml. Skip plugin '"
1596
                        + pluginDirs[i].getAbsolutePath() + "'.");
1597
                } catch (MarshalException e) {
1598
                    this.addError("Can't load plugin '"
1599
                        + pluginDirs[i].getAbsolutePath() + "'.",
1600
                        e);
1601
                } catch (ValidationException e) {
1602
                    this.addError("Can't load plugin '"
1603
                        + pluginDirs[i].getAbsolutePath() + "'.",
1604
                        e);
1605
                }
1606
            }
1607
        }
1608

    
1609
        if (pluginsConfig.size() == 0) {
1610
            logger.error("No valid plugin was found. The plugins directory currently is: "
1611
                + pDir.getAbsolutePath()
1612
                + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1613
            System.exit(-1);
1614
            return;
1615
        }
1616
    }
1617

    
1618
    private static Locale getLocale(String language,
1619
        String country,
1620
        String variant) {
1621
        if (variant != null) {
1622
            return new Locale(language, country, variant);
1623
        } else
1624
            if (country != null) {
1625
                return new Locale(language, country);
1626
            } else
1627
                if (language != null) {
1628
                    return new Locale(language);
1629
                } else {
1630
                    return new Locale("es");
1631
                }
1632
    }
1633

    
1634
    private static void andamiConfigToXML(String file) throws IOException,
1635
        MarshalException,
1636
        ValidationException {
1637
        // write on a temporary file in order to not destroy current file if
1638
        // there is some problem while marshaling
1639
        File tmpFile =
1640
            new File(file + "-" + DateTime.getCurrentDate().getTime());
1641
        File xml = new File(file);
1642
        File parent = xml.getParentFile();
1643
        parent.mkdirs();
1644

    
1645
        BufferedOutputStream os =
1646
            new BufferedOutputStream(new FileOutputStream(tmpFile));
1647
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
1648
        andamiConfig.marshal(writer);
1649
        writer.close();
1650

    
1651
        // if marshaling process finished correctly, move the file to the
1652
        // correct one
1653
        xml.delete();
1654
        if (!tmpFile.renameTo(xml)) {
1655
            // if rename was not succesful, try copying it
1656
            FileChannel sourceChannel =
1657
                new FileInputStream(tmpFile).getChannel();
1658
            FileChannel destinationChannel =
1659
                new FileOutputStream(xml).getChannel();
1660
            sourceChannel.transferTo(0,
1661
                sourceChannel.size(),
1662
                destinationChannel);
1663
            sourceChannel.close();
1664
            destinationChannel.close();
1665
        }
1666
    }
1667

    
1668
    private static void andamiConfigFromXML(String file) throws ConfigurationException {
1669
        File xml = new File(file);
1670

    
1671
        InputStreamReader reader = null;
1672
        try {
1673
            // Se lee la configuraci?n
1674
            reader = XMLEncodingUtils.getReader(xml);
1675
            andamiConfig = (AndamiConfig) AndamiConfig.unmarshal(reader);
1676
        } catch (FileNotFoundException e) {
1677
            // Si no existe se ponen los valores por defecto
1678
            andamiConfig = getDefaultAndamiConfig();
1679
        } catch (MarshalException e) {
1680
            // try to close the stream, maybe it remains open
1681
            if (reader != null) {
1682
                try {
1683
                    reader.close();
1684
                } catch (IOException e1) {
1685
                }
1686
            }
1687
            // if there was a problem reading the file, backup it and create a
1688
            // new one with default values
1689
            String backupFile =
1690
                file + "-" + DateTime.getCurrentDate().getTime();
1691
            NotificationManager.addError(Messages.getString("Error_reading_andami_config_New_file_created_A_backup_was_made_on_")
1692
                + backupFile,
1693
                new ConfigurationException(e));
1694
            xml.renameTo(new File(backupFile));
1695
            andamiConfig = getDefaultAndamiConfig();
1696
        } catch (ValidationException e) {
1697
            throw new ConfigurationException(e);
1698
        }
1699
    }
1700

    
1701
    private static AndamiConfig getDefaultAndamiConfig() {
1702
        AndamiConfig andamiConfig = new AndamiConfig();
1703

    
1704
        Andami andami = new Andami();
1705
        andami.setUpdate(true);
1706
        andamiConfig.setAndami(andami);
1707
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
1708
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
1709
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
1710

    
1711
        if (System.getProperty("javawebstart.version") != null) // Es java web
1712
                                                                // start)
1713
        {
1714
            andamiConfig.setPluginsDirectory(new File(appHomeDir
1715
                + "extensiones").getAbsolutePath());
1716
        } else {
1717
            andamiConfig.setPluginsDirectory(new File(appName + File.separator
1718
                + "extensiones").getAbsolutePath());
1719
        }
1720

    
1721
        andamiConfig.setPlugin(new Plugin[0]);
1722
        return andamiConfig;
1723
    }
1724

    
1725
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
1726
        File xml = getPluginsPersistenceFile(true);
1727

    
1728
        if (xml.exists()) {
1729
            InputStreamReader reader = null;
1730

    
1731
            try {
1732
                reader = XMLEncodingUtils.getReader(xml);
1733
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1734
                return new XMLEntity(tag);
1735
            } catch (FileNotFoundException e) {
1736
                throw new ConfigurationException(e);
1737
            } catch (MarshalException e) {
1738

    
1739
                // try to reopen with default encoding (for backward
1740
                // compatibility)
1741
                try {
1742
                    reader = new FileReader(xml);
1743
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1744
                    return new XMLEntity(tag);
1745

    
1746
                } catch (MarshalException ex) {
1747
                    // try to close the stream, maybe it remains open
1748
                    if (reader != null) {
1749
                        try {
1750
                            reader.close();
1751
                        } catch (IOException e1) {
1752
                        }
1753
                    }
1754
                    // backup the old file
1755
                    String backupFile =
1756
                        getPluginsPersistenceFile(true).getPath() + "-"
1757
                            + DateTime.getCurrentDate().getTime();
1758
                    NotificationManager.addError(Messages.getString("Error_reading_plugin_persinstence_New_file_created_A_backup_was_made_on_")
1759
                        + backupFile,
1760
                        new ConfigurationException(e));
1761
                    xml.renameTo(new File(backupFile));
1762
                    // create a new, empty configuration
1763
                    return new XMLEntity();
1764
                } catch (FileNotFoundException ex) {
1765
                    return new XMLEntity();
1766
                } catch (ValidationException ex) {
1767
                    throw new ConfigurationException(e);
1768
                }
1769
            } catch (ValidationException e) {
1770
                throw new ConfigurationException(e);
1771
            }
1772
        } else {
1773
            return new XMLEntity();
1774
        }
1775
    }
1776

    
1777
    private static File getPluginsPersistenceFile(boolean read) {
1778
        if (read) {
1779
            File pluginsPersistenceFile =
1780
                new File(getAppHomeDir() + "plugins-persistence-2_0.xml");
1781
            if (pluginsPersistenceFile.exists()) {
1782
                return pluginsPersistenceFile;
1783
            }
1784
            pluginsPersistenceFile =
1785
                new File(getAppHomeDir() + "plugins-persistence.xml");
1786
            if (pluginsPersistenceFile.exists()) {
1787
                return pluginsPersistenceFile;
1788
            }
1789
        }
1790
        return new File(getAppHomeDir() + "plugins-persistence-2_0.xml");
1791

    
1792
    }
1793

    
1794
    private static void persistenceToXML(XMLEntity entity) throws ConfigurationException {
1795
        // write on a temporary file in order to not destroy current file if
1796
        // there is some problem while marshaling
1797
        File tmpFile =
1798
            new File(getPluginsPersistenceFile(false).getPath() + "-"
1799
                + DateTime.getCurrentDate().getTime());
1800

    
1801
        File xml = getPluginsPersistenceFile(false);
1802
        OutputStreamWriter writer = null;
1803

    
1804
        try {
1805
            writer =
1806
                new OutputStreamWriter(new FileOutputStream(tmpFile),
1807
                    CASTORENCODING);
1808
            entity.getXmlTag().marshal(writer);
1809
            writer.close();
1810

    
1811
            // if marshaling process finished correctly, move the file to the
1812
            // correct one
1813
            xml.delete();
1814
            if (!tmpFile.renameTo(xml)) {
1815
                // if rename was not succesful, try copying it
1816
                FileChannel sourceChannel =
1817
                    new FileInputStream(tmpFile).getChannel();
1818
                FileChannel destinationChannel =
1819
                    new FileOutputStream(xml).getChannel();
1820
                sourceChannel.transferTo(0,
1821
                    sourceChannel.size(),
1822
                    destinationChannel);
1823
                sourceChannel.close();
1824
                destinationChannel.close();
1825

    
1826
            }
1827
        } catch (FileNotFoundException e) {
1828
            throw new ConfigurationException(e);
1829
        } catch (MarshalException e) {
1830
            // try to close the stream, maybe it remains open
1831
            if (writer != null) {
1832
                try {
1833
                    writer.close();
1834
                } catch (IOException e1) {
1835
                }
1836
            }
1837
        } catch (ValidationException e) {
1838
            throw new ConfigurationException(e);
1839
        } catch (IOException e) {
1840
            throw new ConfigurationException(e);
1841
        }
1842
    }
1843

    
1844
    static MDIFrame getFrame() {
1845
        return frame;
1846
    }
1847

    
1848
    /**
1849
     * Gracefully closes the application. It shows dialogs to save data,
1850
     * finish processes, etc, then it terminates the extensions, removes
1851
     * temporal files and finally exits.
1852
     */
1853
    public synchronized static void closeApplication() {
1854
        TerminationProcess terminationProcess =
1855
            (new Launcher()).new TerminationProcess();
1856
        terminationProcess.run();
1857
    }
1858

    
1859
    static HashMap getClassesExtensions() {
1860
        return classesExtensions;
1861
    }
1862

    
1863
    private static Extensions[] getExtensions() {
1864
        ArrayList array = new ArrayList();
1865
        Iterator iter = pluginsConfig.values().iterator();
1866

    
1867
        while (iter.hasNext()) {
1868
            array.add(((PluginConfig) iter.next()).getExtensions());
1869
        }
1870

    
1871
        return (Extensions[]) array.toArray(new Extensions[0]);
1872
    }
1873

    
1874
    public static Iterator getExtensionIterator() {
1875
        return extensions.iterator();
1876
    }
1877

    
1878
    public static HashMap getPluginConfig() {
1879
        return pluginsConfig;
1880
    }
1881

    
1882
    public static Extension getExtension(String s) {
1883
        Extensions[] exts = getExtensions();
1884

    
1885
        for (int i = 0; i < exts.length; i++) {
1886
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
1887
                if (exts[i].getExtension(j).getClassName().equals(s)) {
1888
                    return exts[i].getExtension(j);
1889
                }
1890
            }
1891
        }
1892

    
1893
        return null;
1894
    }
1895

    
1896
    public static AndamiConfig getAndamiConfig() {
1897
        return andamiConfig;
1898
    }
1899

    
1900
    private static class ExtensionComparator implements Comparator {
1901

    
1902
        public int compare(Object o1, Object o2) {
1903
            Extension e1 = (Extension) o1;
1904
            Extension e2 = (Extension) o2;
1905

    
1906
            if (!e1.hasPriority() && !e2.hasPriority()) {
1907
                return -1;
1908
            }
1909

    
1910
            if (e1.hasPriority() && !e2.hasPriority()) {
1911
                return Integer.MIN_VALUE;
1912
            }
1913

    
1914
            if (e2.hasPriority() && !e1.hasPriority()) {
1915
                return Integer.MAX_VALUE;
1916
            }
1917

    
1918
            if (e1.getPriority() != e2.getPriority()) {
1919
                return e2.getPriority() - e1.getPriority();
1920
            } else {
1921
                return (e2.toString().compareTo(e1.toString()));
1922
            }
1923
        }
1924
    }
1925

    
1926
    private static class MenuComparator implements Comparator {
1927

    
1928
        private static ExtensionComparator extComp = new ExtensionComparator();
1929

    
1930
        public int compare(Object o1, Object o2) {
1931
            SortableMenu e1 = (SortableMenu) o1;
1932
            SortableMenu e2 = (SortableMenu) o2;
1933

    
1934
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
1935
                if (e1.extension instanceof SkinExtensionType) {
1936
                    return 1;
1937
                } else
1938
                    if (e2.extension instanceof SkinExtensionType) {
1939
                        return -1;
1940
                    } else {
1941
                        return extComp.compare(e1.extension, e2.extension);
1942
                    }
1943
            }
1944

    
1945
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
1946
                return Integer.MIN_VALUE;
1947
            }
1948

    
1949
            if (e2.menu.hasPosition() && !e1.menu.hasPosition()) {
1950
                return Integer.MAX_VALUE;
1951
            }
1952
            if (e1.menu.getPosition() != e2.menu.getPosition()) {
1953
                // we don't return 0 unless both objects are the same, otherwise
1954
                // the objects get overwritten in the treemap
1955
                return e1.menu.getPosition() - e2.menu.getPosition();
1956
            } else {
1957
                return (e1.toString().compareTo(e2.toString()));
1958
            }
1959
        }
1960
    }
1961

    
1962
    private static class SortableMenu {
1963

    
1964
        public PluginClassLoader loader;
1965
        public Menu menu;
1966
        public SkinExtensionType extension;
1967

    
1968
        public SortableMenu(PluginClassLoader loader,
1969
            SkinExtensionType skinExt,
1970
            Menu menu2) {
1971
            extension = skinExt;
1972
            menu = menu2;
1973
            this.loader = loader;
1974
        }
1975
    }
1976

    
1977
    private static class SortableTool {
1978

    
1979
        public PluginClassLoader loader;
1980
        public ToolBar toolbar;
1981
        public ActionTool actiontool;
1982
        public SelectableTool selectabletool;
1983
        public SkinExtensionType extension;
1984

    
1985
        public SortableTool(PluginClassLoader loader,
1986
            SkinExtensionType skinExt,
1987
            ToolBar toolbar2,
1988
            ActionTool actiontool2) {
1989
            extension = skinExt;
1990
            toolbar = toolbar2;
1991
            actiontool = actiontool2;
1992
            this.loader = loader;
1993
        }
1994

    
1995
        public SortableTool(PluginClassLoader loader,
1996
            SkinExtensionType skinExt,
1997
            ToolBar toolbar2,
1998
            SelectableTool selectabletool2) {
1999
            extension = skinExt;
2000
            toolbar = toolbar2;
2001
            selectabletool = selectabletool2;
2002
            this.loader = loader;
2003
        }
2004
    }
2005

    
2006
    private static class ToolBarComparator implements Comparator {
2007

    
2008
        private static ExtensionComparator extComp = new ExtensionComparator();
2009

    
2010
        public int compare(Object o1, Object o2) {
2011
            SortableTool e1 = (SortableTool) o1;
2012
            SortableTool e2 = (SortableTool) o2;
2013

    
2014
            // if the toolbars have the same name, they are considered to be
2015
            // the same toolbar, so we don't need to do further comparing
2016
            if (e1.toolbar.getName().equals(e2.toolbar.getName()))
2017
                return 0;
2018

    
2019
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2020
                if (e1.extension instanceof SkinExtensionType) {
2021
                    return 1;
2022
                } else
2023
                    if (e2.extension instanceof SkinExtensionType) {
2024
                        return -1;
2025
                    } else {
2026
                        return extComp.compare(e1.extension, e2.extension);
2027
                    }
2028
            }
2029

    
2030
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2031
                return Integer.MIN_VALUE;
2032
            }
2033

    
2034
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2035
                return Integer.MAX_VALUE;
2036
            }
2037
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition())
2038
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2039

    
2040
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2041
                && e1.toolbar.getSelectableTool()
2042
                    .equals(e2.toolbar.getSelectableTool())) {
2043
                return 0;
2044
            }
2045
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2046
        }
2047
    }
2048

    
2049
    /**
2050
     * <p>
2051
     * This class is used to compare tools (selectabletool and actiontool),
2052
     * using the "position" attribute.
2053
     * </p>
2054
     * <p>
2055
     * The ordering criteria are:
2056
     * </p>
2057
     * <ul>
2058
     * <li>If the tools are placed in different toolbars, they use the toolbars'
2059
     * order. (using the ToolBarComparator).</li>
2060
     * <li></li>
2061
     * <li>If any of the tools has not 'position' attribute, the tool which
2062
     * <strong>has</strong> the attribute will be placed first.</li>
2063
     * <li>If both tools have the same position (or they don't have a 'position'
2064
     * attribute), the priority of the extensions where the tool is defined.</li>
2065
     * </ul>
2066
     * 
2067
     * @author cesar
2068
     * @version $Revision: 34114 $
2069
     */
2070
    private static class ToolComparator implements Comparator {
2071

    
2072
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2073

    
2074
        public int compare(Object o1, Object o2) {
2075
            // compare the toolbars which contain the tools
2076
            int result = toolBarComp.compare(o1, o2);
2077
            if (result != 0) { // if the toolbars are different, use their order
2078
                return result;
2079
            }
2080
            // otherwise, compare the tools
2081
            SortableTool e1 = (SortableTool) o1;
2082
            SortableTool e2 = (SortableTool) o2;
2083
            int e1Position = -1, e2Position = -1;
2084

    
2085
            if (e1.actiontool != null) {
2086
                if (e1.actiontool.hasPosition())
2087
                    e1Position = e1.actiontool.getPosition();
2088
            } else
2089
                if (e1.selectabletool != null) {
2090
                    if (e1.selectabletool.hasPosition())
2091
                        e1Position = e1.selectabletool.getPosition();
2092
                }
2093

    
2094
            if (e2.actiontool != null) {
2095
                if (e2.actiontool.hasPosition())
2096
                    e2Position = e2.actiontool.getPosition();
2097
            } else
2098
                if (e2.selectabletool != null) {
2099
                    if (e2.selectabletool.hasPosition())
2100
                        e2Position = e2.selectabletool.getPosition();
2101
                }
2102

    
2103
            if (e1Position == -1 && e2Position != -1) {
2104
                return 1;
2105
            }
2106
            if (e1Position != -1 && e2Position == -1) {
2107
                return -1;
2108
            }
2109
            if (e1Position != -1 && e2Position != -1) {
2110
                result = e1Position - e2Position;
2111
                // we don't return 0 unless both objects are the same, otherwise
2112
                // the objects get overwritten in the treemap
2113
                if (result != 0)
2114
                    return result;
2115
            }
2116
            return e1.toString().compareTo(e2.toString());
2117
        }
2118
    }
2119

    
2120
    /**
2121
     * validates the user before starting gvsig
2122
     * 
2123
     */
2124
    private static void validate() {
2125

    
2126
        IAuthentication session = null;
2127
        try {
2128
            session =
2129
                (IAuthentication) Class.forName("com.iver.andami.authentication.Session")
2130
                    .newInstance();
2131

    
2132
        } catch (ClassNotFoundException e) {
2133
            return;
2134
        } catch (InstantiationException e) {
2135
            return;
2136
        } catch (IllegalAccessException e) {
2137
            return;
2138
        }
2139

    
2140
        session.setPluginDirectory(andamiConfig.getPluginsDirectory());
2141
        if (session.validationRequired()) {
2142
            if (session.Login()) {
2143
                logger.info("You are logged in");
2144
            } else {
2145
                JOptionPane.showMessageDialog((Component) PluginServices.getMainFrame(),
2146
                    "You are not logged in");
2147
            }
2148
            PluginServices.setAuthentication(session);
2149
        }
2150
    }
2151

    
2152
    public static String getDefaultLookAndFeel() {
2153
        String osName = (String) System.getProperty("os.name");
2154

    
2155
        if (osName.length() > 4
2156
            && osName.substring(0, 5).toLowerCase().equals("linux"))
2157
            return nonWinDefaultLookAndFeel;
2158
        if (osName.toLowerCase().startsWith("mac os x"))
2159
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
2160

    
2161
        return UIManager.getSystemLookAndFeelClassName();
2162
    }
2163

    
2164
    /**
2165
     * Gets the ISO 839 two-characters-long language code matching the
2166
     * provided language code (which may be an ISO 839-2/T
2167
     * three-characters-long code or an ISO 839-1 two-characters-long
2168
     * code).
2169
     * 
2170
     * If the provided parameter is already two characters long, it
2171
     * returns the parameter without any modification.
2172
     * 
2173
     * @param langCode
2174
     *            A language code representing either
2175
     *            an ISO 839-2/T language code or an ISO 839-1 code.
2176
     * @return A two-characters-long code specifying
2177
     *         an ISO 839 language code.
2178
     */
2179
    private static String normalizeLanguageCode(String langCode) {
2180
        final String fileName = "iso_639.tab";
2181
        if (langCode.length() == 2)
2182
            return langCode;
2183
        else
2184
            if (langCode.length() == 3) {
2185
                if (langCode.equals("va") || langCode.equals("val")) { // special
2186
                                                                       // case
2187
                                                                       // for
2188
                                                                       // Valencian
2189
                    return "ca";
2190
                }
2191
                URL isoCodes =
2192
                    Launcher.class.getClassLoader().getResource(fileName);
2193
                if (isoCodes != null) {
2194
                    try {
2195
                        BufferedReader reader =
2196
                            new BufferedReader(new InputStreamReader(isoCodes.openStream(),
2197
                                "ISO-8859-1"));
2198
                        String line;
2199

    
2200
                        while ((line = reader.readLine()) != null) {
2201
                            String[] language = line.split("\t");
2202
                            if (language[0].equals(langCode)) // first column is
2203
                                                              // the three
2204
                                                              // characters code
2205
                                return language[2]; // third column i the two
2206
                                                    // characters code
2207
                        }
2208
                    } catch (IOException ex) {
2209
                        logger.error(Messages.getString("Error_reading_isocodes_file"),
2210
                            ex);
2211
                        return "es";
2212
                    }
2213
                } else {
2214
                    logger.error(Messages.getString("Error_reading_isocodes_file"));
2215
                    return "es";
2216
                }
2217
            }
2218
        return "es";
2219
    }
2220

    
2221
    /**
2222
     * Configures the locales (languages and local resources) to be used
2223
     * by the application.
2224
     * 
2225
     * First it tries to get the locale from the command line parameters,
2226
     * then the andami-config file is checked.
2227
     * 
2228
     * The locale name is normalized to get a two characters language code
2229
     * as defined by ISO-639-1 (although ISO-639-2/T three characters codes
2230
     * are also accepted from the command line or the configuration file).
2231
     * 
2232
     * Finally, the gvsig-i18n library and the default locales for Java and
2233
     * Swing are configured.
2234
     * 
2235
     */
2236
    private static void configureLocales(String[] args) {
2237
        // Configurar el locale
2238
        String localeStr = null;
2239
        /*
2240
         * for (int i=2; i < args.length; i++)
2241
         * {
2242
         * int index = args[i].indexOf("language=");
2243
         * if (index != -1)
2244
         * localeStr = args[i].substring(index+9);
2245
         * }
2246
         */
2247
        localeStr = PluginServices.getArgumentByName("language");
2248
        if (localeStr == null) {
2249
            localeStr = andamiConfig.getLocaleLanguage();
2250
        }
2251
        localeStr = normalizeLanguageCode(localeStr);
2252
        locale =
2253
            getLocale(localeStr,
2254
                andamiConfig.getLocaleCountry(),
2255
                andamiConfig.getLocaleVariant());
2256
        Locale.setDefault(locale);
2257
        JComponent.setDefaultLocale(locale);
2258
        org.gvsig.i18n.Messages.addLocale(locale);
2259
        // add english and spanish as fallback languages
2260
        if (localeStr.equals("es") || localeStr.equals("ca")
2261
            || localeStr.equals("gl") || localeStr.equals("eu")
2262
            || localeStr.equals("va")) {
2263
            // prefer Spanish for languages spoken in Spain
2264
            org.gvsig.i18n.Messages.addLocale(new Locale("es"));
2265
            org.gvsig.i18n.Messages.addLocale(new Locale("en"));
2266
        } else {
2267
            // prefer English for the rest
2268
            org.gvsig.i18n.Messages.addLocale(new Locale("en"));
2269
            org.gvsig.i18n.Messages.addLocale(new Locale("es"));
2270
        }
2271
        org.gvsig.i18n.Messages.addResourceFamily("com.iver.andami.text",
2272
            "com.iver.andami.text");
2273

    
2274
    }
2275

    
2276
    /**
2277
     * Gets Home Directory location of the application into users home folder.
2278
     * 
2279
     * May be set from outside the aplication by means of
2280
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name
2281
     * of the application
2282
     * 
2283
     * @return
2284
     */
2285
    public static String getAppHomeDir() {
2286
        return appHomeDir;
2287
    }
2288

    
2289
    /**
2290
     * Sets Home Directory location of the application.
2291
     * May be set from outside the aplication by means of
2292
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name
2293
     * of the application
2294
     * 
2295
     * @param appHomeDir
2296
     */
2297
    public static void setAppHomeDir(String appHomeDir) {
2298
        Launcher.appHomeDir = appHomeDir;
2299
    }
2300

    
2301
    /**
2302
     * Initialize the extesion that have to take the control
2303
     * of the state of action controls of the UI of all extensions. <br>
2304
     * <br>
2305
     * For use this option you have to add an argument
2306
     * to the command line like this: <br>
2307
     * <br>
2308
     * -exclusiveUI={pathToExtensionClass} <br>
2309
     * 
2310
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
2311
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
2312
     */
2313
    private static void initializeExclusiveUIExtension() {
2314
        String name = PluginServices.getArgumentByName("exclusiveUI");
2315
        if (name == null)
2316
            return;
2317

    
2318
        Iterator iter = classesExtensions.keySet().iterator();
2319
        int charIndex;
2320
        Class key;
2321
        while (iter.hasNext()) {
2322
            key = (Class) iter.next();
2323
            charIndex = key.getName().indexOf(name);
2324
            // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex);
2325
            if (charIndex == 0) {
2326
                IExtension ext = (IExtension) classesExtensions.get(key);
2327
                if (ext instanceof ExtensionDecorator)
2328
                    ext = ((ExtensionDecorator) ext).getExtension();
2329
                if (ext instanceof ExclusiveUIExtension)
2330
                    PluginServices.setExclusiveUIExtension((ExclusiveUIExtension) ext);
2331
                break;
2332
            }
2333
        }
2334

    
2335
        logger.error(Messages.getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
2336
            + " '" + name + "'");
2337
    }
2338

    
2339
    // public static void initIconThemes() {
2340
    // // load the iconTheme
2341
    // IconThemeManager iconManager = new IconThemeManager();
2342
    // PluginServices.setIconThemeManager(iconManager);
2343
    // IconThemeInfo selectedTheme = iconManager.readConfig();
2344
    // if (selectedTheme!=null) {
2345
    // iconManager.setDefault(selectedTheme);
2346
    // logger.info("Setting the icon theme: "+selectedTheme.toVerboseString());
2347
    // }
2348
    // else {
2349
    // // set the default dir and try to load the default theme
2350
    // try {
2351
    // iconManager.setThemesDir(new File("iconThemes"));
2352
    // IconThemeInfo[] list = iconManager.list();
2353
    //
2354
    // for (int i=0; i<list.length; i++) {
2355
    // if (list[i].getResourceName().equals("iconThemes/icons")) {
2356
    // iconManager.setDefault(list[i]);
2357
    // logger.info("Setting the default icon theme: "+list[i].toVerboseString());
2358
    // return;
2359
    // }
2360
    // }
2361
    // } catch (FileNotFoundException e) {
2362
    // logger.info("IconTheme basedir does not exist");
2363
    // }
2364
    // // create an empty theme
2365
    // IconThemeInfo info = new IconThemeInfo();
2366
    // info.setName("No theme loaded");
2367
    // info.setResource(null); // null resource means that no real theme is
2368
    // loaded
2369
    // info.setDescription("No theme loaded");
2370
    // info.setVersion("0");
2371
    // iconManager.setDefault(new IconTheme(info));
2372
    // logger.info("Setting an empty icon theme");
2373
    //
2374
    // }
2375
    // }
2376

    
2377
    public static void initIconThemes() {
2378
        IconThemeManager iconManager = IconThemeManager.getIconThemeManager();
2379
        IIconTheme icontheme = iconManager.getIconThemeFromConfig();
2380
        if (icontheme != null) {
2381
            iconManager.setCurrent(icontheme);
2382
        }
2383
    }
2384

    
2385
    /**
2386
     * Manages Andami termination process
2387
     * 
2388
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
2389
     */
2390
    public class TerminationProcess {
2391

    
2392
        private boolean proceed = false;
2393
        private UnsavedDataPanel panel = null;
2394

    
2395
        public void run() {
2396
            int exit = manageUnsavedData();
2397
            if (exit == JOptionPane.NO_OPTION
2398
                || exit == JOptionPane.CLOSED_OPTION) {
2399
                // the user doesn't want to exit
2400
                return;
2401
            }
2402

    
2403
            closeAndami();
2404
        }
2405

    
2406
        /**
2407
         * Finishes the application without asking user if want or not to save
2408
         * unsaved data.
2409
         */
2410
        public void closeAndami() {
2411
            // Configuraci?n de Andami
2412
            try {
2413
                andamiConfigToXML(andamiConfigPath);
2414
            } catch (MarshalException e) {
2415
                logger.error(Messages.getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2416
                    e);
2417
            } catch (ValidationException e) {
2418
                logger.error(Messages.getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2419
                    e);
2420
            } catch (IOException e) {
2421
                logger.error(Messages.getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2422
                    e);
2423
            }
2424

    
2425
            // Persistencia de los plugins
2426
            savePluginPersistence();
2427
            savePluginsProperties();
2428

    
2429
            // Finalize all the extensions
2430
            finalizeExtensions();
2431

    
2432
            // Clean any temp data created
2433
            Utilities.cleanUpTempFiles();
2434

    
2435
            // Para la depuraci?n de memory leaks
2436
            System.gc();
2437

    
2438
            System.exit(0);
2439
        }
2440

    
2441
        private void savePluginsProperties(){
2442
            PluginsManager manager = PluginsLocator.getManager();
2443
            List<PluginServices> plugins = manager.getPlugins();
2444
            for (PluginServices plugin : plugins) {
2445
                if (plugin!=null){
2446
                    plugin.savePluginProperties();
2447
                }
2448
            }
2449
        }
2450
        
2451
        /**
2452
         * Exectutes the terminate method for all the extensions, in the reverse
2453
         * order they were initialized
2454
         * 
2455
         */
2456
        private void finalizeExtensions() {
2457
            for (int i = extensions.size() - 1; i >= 0; i--) {
2458
                org.gvsig.andami.plugins.IExtension extensionInstance =
2459
                    (org.gvsig.andami.plugins.IExtension) extensions.get(i);
2460
                extensionInstance.terminate();
2461
            }
2462
        }
2463

    
2464
        private ArrayList getUnsavedData() {
2465
            ArrayList unsavedDataList = new ArrayList();
2466
            IExtension exclusiveExtension =
2467
                PluginServices.getExclusiveUIExtension();
2468

    
2469
            for (int i = extensions.size() - 1; i >= 0; i--) {
2470
                org.gvsig.andami.plugins.IExtension extensionInstance =
2471
                    (org.gvsig.andami.plugins.IExtension) extensions.get(i);
2472
                IExtensionStatus status = null;
2473
                if (exclusiveExtension != null) {
2474
                    status = exclusiveExtension.getStatus(extensionInstance);
2475
                } else {
2476
                    status = extensionInstance.getStatus();
2477
                }
2478
                if (status != null) {
2479
                    if (status.hasUnsavedData()) {
2480
                        IUnsavedData[] array = status.getUnsavedData();
2481
                        for (int element = 0; element < array.length; element++) {
2482
                            unsavedDataList.add(array[element]);
2483
                        }
2484
                    }
2485
                }
2486
            }
2487
            return unsavedDataList;
2488
        }
2489

    
2490
        public UnsavedDataPanel getUnsavedDataPanel() {
2491
            if (panel == null) {
2492
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
2493
            }
2494
            return panel;
2495
        }
2496

    
2497
        /**
2498
         * Checks if the extensions have some unsaved data, and shows a dialog
2499
         * to allow saving it. This dialog also allows to don't exit Andami.
2500
         * 
2501
         * @return true if the user confirmed he wishes to exit, false otherwise
2502
         */
2503
        public int manageUnsavedData() {
2504
            ArrayList unsavedDataList = getUnsavedData();
2505

    
2506
            // there was no unsaved data
2507
            if (unsavedDataList.size() == 0) {
2508
                int option =
2509
                    JOptionPane.showConfirmDialog(frame,
2510
                        Messages.getString("MDIFrame.quiere_salir"),
2511
                        Messages.getString("MDIFrame.salir"),
2512
                        JOptionPane.YES_NO_OPTION);
2513
                return option;
2514
            }
2515

    
2516
            // it does not work if we directly cast the array
2517
            IUnsavedData[] unsavedDataArray;
2518
            unsavedDataArray = new IUnsavedData[unsavedDataList.size()];
2519
            System.arraycopy(unsavedDataList.toArray(),
2520
                0,
2521
                unsavedDataArray,
2522
                0,
2523
                unsavedDataList.size());
2524

    
2525
            UnsavedDataPanel panel = getUnsavedDataPanel();
2526
            panel.setUnsavedDataArray(unsavedDataArray);
2527

    
2528
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
2529

    
2530
                public void cancel(UnsavedDataPanel panel) {
2531
                    proceed(false);
2532
                    PluginServices.getMDIManager().closeWindow(panel);
2533

    
2534
                }
2535

    
2536
                public void discard(UnsavedDataPanel panel) {
2537
                    proceed(true);
2538
                    PluginServices.getMDIManager().closeWindow(panel);
2539

    
2540
                }
2541

    
2542
                public void accept(UnsavedDataPanel panel) {
2543
                    IUnsavedData[] unsavedDataArray =
2544
                        panel.getSelectedsUnsavedData();
2545
                    boolean saved;
2546
                    for (int i = 0; i < unsavedDataArray.length; i++) {
2547
                        try {
2548
                            saved = unsavedDataArray[i].saveData();
2549
                        } catch (Exception ex) {
2550
                            PluginServices.getLogger().error("Error saving"
2551
                                + unsavedDataArray[i].getResourceName(),
2552
                                ex);
2553
                            saved = false;
2554
                        }
2555
                        if (!saved) {
2556
                            JOptionPane.showMessageDialog(panel,
2557
                                PluginServices.getText(this,
2558
                                    "The_following_resource_could_not_be_saved_")
2559
                                    + "\n"
2560
                                    + unsavedDataArray[i].getResourceName()
2561
                                    + " -- "
2562
                                    + unsavedDataArray[i].getDescription(),
2563
                                PluginServices.getText(this,
2564
                                    "Resource_was_not_saved"),
2565
                                JOptionPane.ERROR_MESSAGE);
2566

    
2567
                            ArrayList unsavedDataList = getUnsavedData();
2568
                            // it does not work if we directly cast the array
2569
                            unsavedDataArray =
2570
                                new IUnsavedData[unsavedDataList.size()];
2571
                            System.arraycopy(unsavedDataList.toArray(),
2572
                                0,
2573
                                unsavedDataArray,
2574
                                0,
2575
                                unsavedDataList.size());
2576
                            panel.setUnsavedDataArray(unsavedDataArray);
2577
                            return;
2578
                        }
2579
                    }
2580
                    proceed(true);
2581
                    PluginServices.getMDIManager().closeWindow(panel);
2582
                }
2583
            });
2584

    
2585
            PluginServices.getMDIManager().addWindow(panel);
2586
            if (proceed) {
2587
                return JOptionPane.YES_OPTION;
2588
            } else {
2589
                return JOptionPane.NO_OPTION;
2590
            }
2591
        }
2592

    
2593
        private void proceed(boolean proceed) {
2594
            this.proceed = proceed;
2595
        }
2596

    
2597
    }
2598

    
2599
    public static TerminationProcess getTerminationProcess() {
2600
        return (new Launcher()).new TerminationProcess();
2601
    }
2602
}