Statistics
| Revision:

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

History | View | Annotate | Download (113 KB)

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

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

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

    
98
import org.apache.commons.cli.CommandLine;
99
import org.apache.commons.cli.CommandLineParser;
100
import org.apache.commons.cli.Options;
101
import org.apache.commons.cli.ParseException;
102
import org.apache.commons.cli.PosixParser;
103
import org.apache.log4j.AppenderSkeleton;
104
import org.apache.log4j.PatternLayout;
105
import org.apache.log4j.PropertyConfigurator;
106
import org.apache.log4j.RollingFileAppender;
107
import org.apache.log4j.spi.LoggingEvent;
108
import org.exolab.castor.xml.MarshalException;
109
import org.exolab.castor.xml.ValidationException;
110
import org.slf4j.Logger;
111
import org.slf4j.LoggerFactory;
112

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

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

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

    
209
    protected static ArrayList<String> pluginsOrdered = new ArrayList<String>();
210
    protected static ArrayList<IExtension> extensions =
211
        new ArrayList<IExtension>();
212
    protected static String appHomeDir = null;
213
    // it seems castor uses this encoding
214
    protected static final String CASTORENCODING = "UTF8";
215

    
216
    protected static ListBaseException launcherrors = null;
217

    
218
    protected static Theme theme = null;
219

    
220
    private static final class ProxyAuth extends Authenticator {
221

    
222
        private PasswordAuthentication auth;
223

    
224
        private ProxyAuth(String user, String pass) {
225
            auth = new PasswordAuthentication(user, pass.toCharArray());
226
        }
227

    
228
        protected PasswordAuthentication getPasswordAuthentication() {
229
            return auth;
230
        }
231
    }
232

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

    
253
    protected void downloadExtensions(String extDir) {
254
        // do nothing
255
    }
256

    
257
    public static class LaunchException extends ListBaseException {
258

    
259
        private static final long serialVersionUID = 4541192746962684705L;
260

    
261
        public LaunchException() {
262
            super("Errors in initialization of application.",
263
                "_errors_in_initialization_of_application", serialVersionUID);
264
        }
265

    
266
    }
267

    
268
    protected void addError(Throwable ex) {
269
        if (launcherrors == null) {
270
            launcherrors = new LaunchException();
271
        }
272
        launcherrors.add(ex);
273
    }
274

    
275
    protected void addError(String msg, Throwable cause) {
276
        logger.error(msg, cause);
277
        this.addError(new RuntimeException(msg, cause));
278
    }
279

    
280
    protected void addError(String msg) {
281
        this.addError(msg, null);
282
    }
283

    
284
    public void doMain(String[] args) throws Exception {
285

    
286
        if (args.length < 1) {
287
            System.err
288
                .println("Uso: Launcher appName plugins-directory [language=locale]");
289
        }
290

    
291
        initializeApp(args);
292

    
293
        // Solucionamos el problema de permisos que se produc?a con Java
294
        // Web Start con este c?digo.
295
        // System.setSecurityManager(null);
296
        Policy.setPolicy(new Policy() {
297

    
298
            public PermissionCollection getPermissions(CodeSource codesource) {
299
                Permissions perms = new Permissions();
300
                perms.add(new AllPermission());
301
                return (perms);
302
            }
303

    
304
            public void refresh() {
305
            }
306
        });
307

    
308
        try {
309
            initIconThemes();
310
        } catch (Exception ex) {
311
            this.addError("Can't initialize icon theme", ex);
312
        }
313
        // Registramos los iconos base
314
        try {
315
            registerIcons();
316
        } catch (Exception ex) {
317
            this.addError("Can't register icons", ex);
318
        }
319
        validate();
320

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

    
330
        // Mostrar la ventana de inicio
331
        Frame f = new Frame();
332
        splashWindow = new MultiSplashWindow(f, theme, 190);
333

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

    
349
        // 2.5. Initialize andami libraries
350
        splashWindow.process(25, PluginServices.getText(Launcher.class,
351
            "SplashWindow.initialize_andami_libraries"));
352
        new DefaultLibrariesInitializer().fullInitialize(true);
353
        logger.info("Dump system information");
354
        logger_info(getInformation());
355

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

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

    
376
        // 5. Initialize libraries
377
        splashWindow.process(50, PluginServices.getText(Launcher.class,
378
            "SplashWindow.initialize_libraries"));
379
        initializeLibraries();
380

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

    
396
        // 8. Se configura la mensajer?a del plugin
397
        splashWindow.process(80, PluginServices.getText(Launcher.class,
398
            "SplashWindow.starting_plugin_internationalization_system"));
399
        pluginsMessages();
400

    
401
        // 9. Se modifica el andami-config con los plugins nuevos
402
        splashWindow.process(90, PluginServices.getText(Launcher.class,
403
            "SplashWindow.looking_for_a_skin"));
404
        updateAndamiConfig();
405

    
406
        frame = new MDIFrame();
407
        // 10. Se configura el nombre e icono de la aplicaci?n
408
        splashWindow.process(100, PluginServices.getText(Launcher.class,
409
            "SplashWindow.setting_up_applications_name_and_icons"));
410
        frameIcon(theme);
411

    
412
        // 11. Se prepara el MainFrame para albergar las extensiones
413
        splashWindow.process(110, PluginServices.getText(Launcher.class,
414
            "SplashWindow.preparing_workbench"));
415
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
416

    
417
        SwingUtilities.invokeAndWait(new Runnable() {
418

    
419
            public void run() {
420
                frame.init();
421
            }
422
        });
423
        ToolsSwingLocator.registerWindowManager(ToolsWindowManager.class);
424

    
425
        // 12. Leer el fichero de persistencia
426
        // info de los plugins
427
        // bookmarks de los plugins
428
        splashWindow.process(120, PluginServices.getText(Launcher.class,
429
            "SplashWindow.loading_plugin_settings"));
430
        loadPluginsPersistence();
431

    
432
        // Se instalan los controles del skin
433
        // 13. Se inicializan todas las extensiones de todos los plugins
434
        splashWindow.process(130, PluginServices.getText(Launcher.class,
435
            "SplashWindow.initializing_extensions"));
436
        SwingUtilities.invokeAndWait(new Runnable() {
437

    
438
            public void run() {
439
                initializeExtensions();
440
            }
441
        });
442

    
443
        // 14. Se inicializan la extensi?n exclusiva
444
        splashWindow.process(140, PluginServices.getText(Launcher.class,
445
            "SplashWindow.setting_up_master_extension"));
446
        SwingUtilities.invokeAndWait(new Runnable() {
447

    
448
            public void run() {
449
                initializeExclusiveUIExtension();
450
            }
451
        });
452
        frame.setClassesExtensions(classesExtensions);
453

    
454
        // 15. Se instalan los controles de las extensiones de los plugins
455
        splashWindow.process(150, PluginServices.getText(Launcher.class,
456
            "SplashWindow.installing_extensions_controls"));
457
        SwingUtilities.invokeAndWait(new Runnable() {
458

    
459
            public void run() {
460
                installPluginsControls();
461

    
462
            }
463
        });
464

    
465
        // 16. Se instalan los menus de las extensiones de los plugins
466
        splashWindow.process(160, PluginServices.getText(Launcher.class,
467
            "SplashWindow.installing_extensions_menus"));
468
        SwingUtilities.invokeAndWait(new Runnable() {
469

    
470
            public void run() {
471
                installPluginsMenus();
472

    
473
            }
474
        });
475

    
476
        // 17. Se instalan las etiquetas de las extensiones de los plugins
477
        splashWindow.process(170, PluginServices.getText(Launcher.class,
478
            "SplashWindow.installing_extensions_labels"));
479
        SwingUtilities.invokeAndWait(new Runnable() {
480

    
481
            public void run() {
482
                installPluginsLabels();
483

    
484
            }
485
        });
486

    
487
        // 18. Se instalan los bookmarks de los plugins
488

    
489
        // 19. Se muestra el frame principal
490
        splashWindow.process(180, PluginServices.getText(Launcher.class,
491
            "creating_main_window"));
492
        frame.setVisible(true);
493

    
494
                // TODO: Anyado el directorio de plugins
495
                File defaultAddonsRepository = new File(System.getProperty("user.dir"),
496
                                andamiConfig.getPluginsDirectory());
497
                InstallerManager installerManager = InstallerLocator
498
                                .getInstallerManager();
499
                installerManager.addAddonRepository(defaultAddonsRepository);
500

    
501
                // TODO: hacer algo asi para tener un repositorio por defecto?
502
                installerManager.setDefaultAddonRepository(defaultAddonsRepository);
503
        
504
        
505
        // 19. Se ejecuta el postInitialize
506
        splashWindow.process(190, PluginServices.getText(Launcher.class,
507
            "SplashWindow.post_initializing_extensions"));
508
        SwingUtilities.invokeAndWait(new Runnable() {
509

    
510
            public void run() {
511
                postInitializeExtensions();
512

    
513
            }
514
        });
515

    
516
        // Definimos un KeyEventDispatcher global para que las extensiones
517
        // puedan registrar sus "teclas r?pidas".
518
        GlobalKeyEventDispatcher keyDispatcher =
519
            GlobalKeyEventDispatcher.getInstance();
520
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
521
            .addKeyEventDispatcher(keyDispatcher);
522

    
523
        SwingUtilities.invokeAndWait(new Runnable() {
524

    
525
            public void run() {
526
                frame.enableControls();
527
            }
528
        });
529
        splashWindow.close();
530
        if (launcherrors != null) {
531
            NotificationManager.addError(launcherrors);
532
        }
533
        
534
        org.apache.log4j.Logger.getRootLogger().addAppender(new NotificationAppender());
535

    
536
        
537
    }
538

    
539
    /**
540
     * 
541
     */
542
    private void initializeLibraries() {
543
        List<ClassLoader> classLoaders =
544
            new ArrayList<ClassLoader>(pluginsOrdered.size() + 1);
545
        classLoaders.add(getClass().getClassLoader());
546
        Iterator<String> iter = pluginsOrdered.iterator();
547

    
548
        logger.debug("Initializing plugins libraries: ");
549
        while (iter.hasNext()) {
550
            String pName = (String) iter.next();
551
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
552
            classLoaders.add(ps.getClassLoader());
553
        }
554

    
555
        // Create the libraries initializer and
556
        // initialize the plugin libraries
557
        new DefaultLibrariesInitializer(
558
            classLoaders.toArray(new ClassLoader[classLoaders.size()]))
559
            .fullInitialize(true);
560

    
561
        // Remove them all, we don't need them anymore
562
        classLoaders.clear();
563
        classLoaders = null;
564
    }
565

    
566
    /**
567
     * @param args
568
     * @throws IOException
569
     * @throws ConfigurationException
570
     */
571
    private void initializeApp(String[] args) throws IOException,
572
        ConfigurationException {
573
        if (!validJVM()) {
574
            System.exit(-1);
575
        }
576

    
577
        // Clean temporal files
578
        Utilities.cleanUpTempFiles();
579

    
580
        appName = args[0];
581

    
582
        getOrCreateConfigFolder();
583

    
584
        configureLogging(appName);
585

    
586
        loadAndamiConfig(args[1]);
587

    
588
        // Hacemos visibles los argumentos como una propiedad est?tica
589
        // de plugin services para quien lo quiera usar (por ejemplo, para
590
        // cargar un proyecto por l?nea de comandos)
591
        PluginServices.setArguments(args);
592

    
593
        configureLocales(args);
594

    
595
        logger.info("Load and initialize andami and plugins libraries");
596
        // LibrariesInitializer libsInitializer =
597
        // new DefaultLibrariesInitializer();
598
        // libsInitializer.initialize(true);
599
        // libsInitializer.postInitialize(true);
600

    
601
        logger.info("Configure LookAndFeel");
602
        configureLookAndFeel();
603
    }
604

    
605
    /**
606
     * 
607
     */
608
    private void configureLookAndFeel() {
609
        // Se pone el lookAndFeel
610
        try {
611
            String lookAndFeel = getAndamiConfig().getLookAndFeel();
612
            if (lookAndFeel == null) {
613
                lookAndFeel = getDefaultLookAndFeel();
614
            }
615
            UIManager.setLookAndFeel(lookAndFeel);
616
        } catch (Exception e) {
617
            logger.warn(Messages.getString("Launcher.look_and_feel"), e);
618
        }
619
        FontUtils.initFonts();
620
    }
621

    
622
    /**
623
     * @param args
624
     * @throws ConfigurationException
625
     */
626
    private void loadAndamiConfig(String pluginFolder)
627
        throws ConfigurationException {
628
        // Leer el fichero de configuraci?n de andami (andami-config.xsd)
629
        // locale
630
        // Buscar actualizaci?nes al comenzar
631
        // Andami
632
        // Plugins
633
        // Directorio de las extensiones
634
        andamiConfigPath = appHomeDir + File.separator + "andami-config.xml";
635
        andamiConfigFromXML(andamiConfigPath);
636
        andamiConfig.setPluginsDirectory(pluginFolder);
637
    }
638

    
639
    /**
640
     * 
641
     */
642
    private void getOrCreateConfigFolder() {
643
        // Create application configuration folder
644
        appHomeDir = System.getProperty(appName + ".home");
645
        if (appHomeDir == null) {
646
            appHomeDir = System.getProperty("user.home");
647
        }
648

    
649
        appHomeDir += File.separator + appName;
650
        File parent = new File(appHomeDir);
651
        parent.mkdirs();
652
    }
653

    
654
    /**
655
     * @param args
656
     * @throws IOException
657
     */
658
    private void configureLogging(String appName) throws IOException {
659
        // Configurar el log4j
660
        Launcher.class.getClassLoader().getResource(".");
661
        PropertyConfigurator.configure("log4j.properties");
662

    
663
        PatternLayout l = new PatternLayout("%p %t %C - %m%n");
664
        RollingFileAppender fa =
665
            new RollingFileAppender(l, appHomeDir + File.separator + appName
666
                + ".log", false);
667
        fa.setMaxFileSize("512KB");
668
        fa.setMaxBackupIndex(3);
669
        org.apache.log4j.Logger.getRootLogger().addAppender(fa);
670
    }
671

    
672
    
673
    private class NotificationAppender extends AppenderSkeleton{
674

    
675
        @Override
676
        protected void append(LoggingEvent event) {
677
            if (event.getLevel() == org.apache.log4j.Level.ERROR
678
                || event.getLevel() == org.apache.log4j.Level.FATAL) {
679
                NotificationManager.dispatchError(event.getRenderedMessage(), null);
680
                return;
681
            }
682
//            if (event.getLevel() == org.apache.log4j.Level.WARN) {
683
//                NotificationManager.dispatchWarning(event.getRenderedMessage(), null);
684
//                return;
685
//            }
686
        }
687

    
688
        @Override
689
        public void close() {
690
            // TODO Auto-generated method stub
691
            
692
        }
693

    
694
        @Override
695
        public boolean requiresLayout() {
696
            // TODO Auto-generated method stub
697
            return false;
698
        }
699
        
700
    }
701

    
702
    /**
703
     * Return the directory applicaction is installed.
704
     */
705
    public static String getApplicationDirectory() {
706
        return new File("").getAbsolutePath();
707
    }
708

    
709
    private void registerIcons() {
710
        PluginServices.getIconTheme().registerDefault(
711
            "login-gvsig",
712
            LoginUI.class.getClassLoader()
713
                .getResource("images/login_gvsig.png"));
714
        PluginServices.getIconTheme().registerDefault(
715
            "splash-gvsig",
716
            MultiSplashWindow.class.getClassLoader().getResource(
717
                "images/splash.png"));
718
        PluginServices.getIconTheme().registerDefault("info-icon",
719
            NewStatusBar.class.getClassLoader().getResource("images/info.gif"));
720
        PluginServices.getIconTheme()
721
            .registerDefault(
722
                "error-icon",
723
                NewStatusBar.class.getClassLoader().getResource(
724
                    "images/error.gif"));
725
        PluginServices.getIconTheme().registerDefault(
726
            "warning-icon",
727
            NewStatusBar.class.getClassLoader().getResource(
728
                "images/warning.gif"));
729
        PluginServices.getIconTheme().registerDefault(
730
            "no-icon",
731
            NewStatusBar.class.getClassLoader().getResource(
732
                "images/no_icon.png"));
733
    }
734

    
735
    /**
736
     * Obtiene la personalizaci?n de los iconos, splash, fondo y el nombre de
737
     * la aplicaci?n.
738
     * 
739
     * @return Theme
740
     */
741
    private Theme getTheme(String pluginsDirectory) {
742
        File themeFile = null;
743
        Theme theme = new Theme();
744

    
745
        // Try to get theme from args
746
        String name = PluginServices.getArgumentByName("andamiTheme");
747
        if (name != null) {
748
            themeFile = new File(name);
749
            logger.info("search andami-theme in {}", themeFile
750
                .getAbsolutePath());
751
            if (themeFile.exists()) {
752
                theme.readTheme(themeFile);
753
                logger.info("andami-theme found in {}", themeFile
754
                    .getAbsolutePath());
755
                return theme;
756
            }
757
        }
758

    
759
        // Try to get theme from a plugin
760
        File pluginsDir = new File(pluginsDirectory);
761
        if( !pluginsDir.isAbsolute() ) {
762
                pluginsDir = new File(System.getProperty("user.dir"),  pluginsDirectory);
763
        }
764
        if (pluginsDir.exists()) {
765
            logger.info("search andami-theme in plugins folder.");
766
            File[] pluginDirs = pluginsDir.listFiles();
767
            if (pluginDirs.length > 0) {
768
                for (int i = 0; i < pluginDirs.length; i++) {
769
                    File pluginThemeFile =
770
                        new File( pluginDirs[i], "theme" + File.separator
771
                            + "andami-theme.xml");
772
                    if (pluginThemeFile.exists()) {
773
                        themeFile = pluginThemeFile;
774
                        // This if is a hack to allow more themes than the
775
                        // one available in org.gvsig.app. Remove this
776
                        // when a the theme format is changed to allow for
777
                        // priorities
778
                        if (!"org.gvsig.app".equals(pluginDirs[i].getName())  ) {
779
                            break;
780
                        }
781
                    }
782
                }
783
            }
784
        }
785

    
786
        // The theme file will be the one into a plugin or by default the one
787
        // in the org.gvsig.app plugin
788
        if (themeFile != null && themeFile.exists()) {
789
            theme.readTheme(themeFile);
790
            logger.info("andami-theme found in plugin {}",
791
                themeFile.getAbsolutePath());
792
            return theme;
793
        }
794

    
795
        // Try to get theme from dir gvSIG in user home
796
        themeFile =
797
            new File(getAppHomeDir(), "theme" + File.separator
798
                + "andami-theme.xml");
799
        logger.info("search andami-theme in user's home {}", themeFile
800
            .getAbsolutePath());
801
        if (themeFile.exists()) {
802
            theme.readTheme(themeFile);
803
            logger.info("andami-theme found in user's home {}", themeFile
804
                .getAbsolutePath());
805
            return theme;
806
        }
807

    
808
        // Try to get theme from the instalation dir of gvSIG.
809
        themeFile =
810
            new File(getApplicationDirectory(), "theme" + File.separator
811
                + "andami-theme.xml");
812
        logger.info("search andami-theme in installation folder {}", themeFile
813
            .getAbsolutePath());
814
        if (themeFile.exists()) {
815
            theme.readTheme(themeFile);
816
            logger.info("andami-theme found in instalation folder {}",
817
                themeFile.getAbsolutePath());
818
            return theme;
819
        }
820
        logger.info("Apply default andami-theme.");
821
        return theme;
822
    }
823

    
824
    /**
825
     * Establece los datos que ten?amos guardados respecto de la configuraci?n
826
     * del proxy.
827
     */
828
    private void configureProxy() {
829
        String host = prefs.get("firewall.http.host", "");
830
        String port = prefs.get("firewall.http.port", "");
831

    
832
        System.getProperties().put("http.proxyHost", host);
833
        System.getProperties().put("http.proxyPort", port);
834

    
835
        // Ponemos el usuario y clave del proxy, si existe
836
        String proxyUser = prefs.get("firewall.http.user", null);
837
        String proxyPassword = prefs.get("firewall.http.password", null);
838
        if (proxyUser != null) {
839
            System.getProperties().put("http.proxyUserName", proxyUser);
840
            System.getProperties().put("http.proxyPassword", proxyPassword);
841

    
842
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
843
        } else {
844
            Authenticator.setDefault(new ProxyAuth("", ""));
845
        }
846
    }
847

    
848
    /**
849
     * Recupera la geometr?a (tama?o, posic?n y estado) de la ventana principal
850
     * de Andami.
851
     * TODO Pendiente de ver como se asigna un pluginServices para el launcher.
852
     * 
853
     * @author LWS
854
     */
855
    private void restoreMDIStatus(XMLEntity xml) {
856
        if (xml == null) {
857
            xml = new XMLEntity();
858
        }
859
        // restore frame size
860
        Dimension sz = new Dimension(700, 580);
861
        if (xml.contains("MDIFrameSize")) {
862
            int[] wh = xml.getIntArrayProperty("MDIFrameSize");
863
            sz = new Dimension(wh[0], wh[1]);
864
        }
865
        frame.setSize(sz);
866
        // restore frame location
867
        Point pos = new Point(10, 10);
868
        if (xml.contains("MDIFramePos")) {
869
            int[] xy = xml.getIntArrayProperty("MDIFramePos");
870
            pos = new Point(xy[0], xy[1]);
871
        }
872
        frame.setLocation(pos);
873

    
874
        // restore frame status (Maximized, minimized, etc);
875
        int state = java.awt.Frame.MAXIMIZED_BOTH;
876
        if (xml.contains("MDIFrameState")) {
877
            state = xml.getIntProperty("MDIFrameState");
878
        }
879
        frame.setExtendedState(state);
880
    }
881

    
882
    private XMLEntity saveMDIStatus() {
883
        XMLEntity xml = new XMLEntity();
884
        // save frame size
885
        int[] wh = new int[2];
886
        wh[0] = frame.getWidth();
887
        wh[1] = frame.getHeight();
888
        xml.putProperty("MDIFrameSize", wh);
889
        // save frame location
890
        int[] xy = new int[2];
891
        xy[0] = frame.getX();
892
        xy[1] = frame.getY();
893
        xml.putProperty("MDIFramePos", xy);
894
        // save frame status
895
        xml.putProperty("MDIFrameState", frame.getExtendedState());
896
        return xml;
897
    }
898

    
899
    private boolean validJVM() {
900
        char thirdCharacter = System.getProperty("java.version").charAt(2);
901
        if (thirdCharacter < '4') {
902
            return false;
903
        } else {
904
            return true;
905
        }
906
    }
907

    
908
    private void loadPluginsPersistence() throws ConfigurationException {
909
        XMLEntity entity = persistenceFromXML();
910

    
911
        for (int i = 0; i < entity.getChildrenCount(); i++) {
912
            XMLEntity plugin = entity.getChild(i);
913
            String pName =
914
                plugin.getStringProperty("com.iver.andami.pluginName");
915

    
916
            if (pName.compareToIgnoreCase("com.iver.cit.gvsig") == 0) {
917
                pName = "org.gvsig.app";
918
            }
919
            if (pluginsServices.get(pName) != null) {
920
                ((PluginServices) pluginsServices.get(pName))
921
                    .setPersistentXML(plugin);
922
            } else {
923
                if (pName.startsWith("Andami.Launcher")) {
924
                    restoreMDIStatus(plugin);
925
                }
926
            }
927
        }
928
    }
929

    
930
    /**
931
     * Salva la persistencia de los plugins.
932
     * 
933
     * @author LWS
934
     */
935
    private void savePluginPersistence() {
936
        Iterator<String> i = pluginsConfig.keySet().iterator();
937

    
938
        XMLEntity entity = new XMLEntity();
939

    
940
        while (i.hasNext()) {
941
            String pName = i.next();
942
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
943
            XMLEntity ent = ps.getPersistentXML();
944

    
945
            if (ent != null) {
946
                ent.putProperty("com.iver.andami.pluginName", pName);
947
                entity.addChild(ent);
948
            }
949
        }
950
        XMLEntity ent = saveMDIStatus();
951
        if (ent != null) {
952
            ent.putProperty("com.iver.andami.pluginName", "Andami.Launcher");
953
            entity.addChild(ent);
954
        }
955
        try {
956
            persistenceToXML(entity);
957
        } catch (ConfigurationException e1) {
958
            this
959
                .addError(
960
                    Messages
961
                        .getString("Launcher.Se_produjo_un_error_guardando_la_configuracion_de_los_plugins"),
962
                    e1);
963
        }
964
    }
965

    
966
    private void installPluginsLabels() {
967
        Iterator<String> i = pluginsConfig.keySet().iterator();
968

    
969
        while (i.hasNext()) {
970
            String name = i.next();
971
            PluginConfig pc = pluginsConfig.get(name);
972
            PluginServices ps = (PluginServices) pluginsServices.get(name);
973

    
974
            LabelSet[] ls = pc.getLabelSet();
975

    
976
            for (int j = 0; j < ls.length; j++) {
977
                PluginClassLoader loader = ps.getClassLoader();
978

    
979
                try {
980
                    Class clase = loader.loadClass(ls[j].getClassName());
981
                    frame.setStatusBarLabels(clase, ls[j].getLabel());
982
                } catch (ClassNotFoundException e) {
983
                    this.addError(
984
                        Messages.getString("Launcher.labelset_class"), e);
985
                }
986
            }
987
        }
988
    }
989

    
990
    private String configureSkin(XMLEntity xml, String defaultSkin) {
991
        if (defaultSkin == null) {
992
            for (int i = 0; i < xml.getChildrenCount(); i++) {
993
                if (xml.getChild(i).contains("Skin-Selected")) {
994
                    String className =
995
                        xml.getChild(i).getStringProperty("Skin-Selected");
996
                    return className;
997
                }
998
            }
999
        }
1000
        // return "com.iver.core.mdiManager.NewSkin";
1001
        return defaultSkin;
1002
    }
1003

    
1004
    private void fixSkin(SkinExtension skinExtension,
1005
        PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
1006
        // now insert the skin selected.
1007
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
1008
        // MDIManagerFactory.setSkinExtension(se,
1009
        // ps.getClassLoader());
1010

    
1011
        Class<? extends IExtension> skinClass;
1012

    
1013
        try {
1014
            skinClass =
1015
                (Class<? extends IExtension>) pluginClassLoader
1016
                    .loadClass(skinExtension.getClassName());
1017

    
1018
            IExtension skinInstance = skinClass.newInstance();
1019
            ExtensionDecorator newExtensionDecorator =
1020
                new ExtensionDecorator(skinInstance,
1021
                    ExtensionDecorator.INACTIVE);
1022
            classesExtensions.put(skinClass, newExtensionDecorator);
1023
        } catch (ClassNotFoundException e) {
1024
            logger.error(Messages
1025
                .getString("Launcher.No_se_encontro_la_clase_mdi_manager"), e);
1026
            throw new MDIManagerLoadException(e);
1027
        } catch (InstantiationException e) {
1028
            logger
1029
                .error(
1030
                    Messages
1031
                        .getString("Launcher.No_se_pudo_instanciar_la_clase_mdi_manager"),
1032
                    e);
1033
            throw new MDIManagerLoadException(e);
1034
        } catch (IllegalAccessException e) {
1035
            logger
1036
                .error(
1037
                    Messages
1038
                        .getString("Launcher.No_se_pudo_acceder_a_la_clase_mdi_manager"),
1039
                    e);
1040
            throw new MDIManagerLoadException(e);
1041
        }
1042

    
1043
    }
1044

    
1045
    /**
1046
     * DOCUMENT ME!
1047
     * 
1048
     * @throws MDIManagerLoadException
1049
     */
1050
    private void skinPlugin(String defaultSkin) throws MDIManagerLoadException {
1051
        XMLEntity entity = null;
1052
        try {
1053
            entity = persistenceFromXML();
1054
        } catch (ConfigurationException e1) {
1055
            // TODO Auto-generated catch block
1056
            e1.printStackTrace();
1057
        }
1058
        Iterator<String> i = pluginsConfig.keySet().iterator();
1059

    
1060
        SkinExtension skinExtension = null;
1061
        PluginClassLoader pluginClassLoader = null;
1062
        List<SkinExtension> skinExtensions = new ArrayList<SkinExtension>();
1063
        while (i.hasNext()) {
1064
            String name = i.next();
1065
            PluginConfig pc = pluginsConfig.get(name);
1066
            PluginServices ps = pluginsServices.get(name);
1067

    
1068
            if (pc.getExtensions().getSkinExtension() != null) {
1069
                // if (MDIManagerFactory.getSkinExtension() != null) {
1070
                // logger.warn(Messages.getString(
1071
                // "Launcher.Dos_skin_extension"));
1072
                // }
1073

    
1074
                SkinExtension[] se = pc.getExtensions().getSkinExtension();
1075
                for (int numExten = 0; numExten < se.length; numExten++) {
1076
                    skinExtensions.add(se[numExten]);
1077
                }
1078
                for (int j = 0; j < se.length; j++) {
1079
                    String configuredSkin =
1080
                        this.configureSkin(entity, defaultSkin);
1081
                    if ((configuredSkin != null)
1082
                        && configuredSkin.equals(se[j].getClassName())) {
1083
                        skinExtension = se[j];
1084
                        pluginClassLoader = ps.getClassLoader();
1085
                    }
1086
                }
1087
            }
1088
        }
1089

    
1090
        if ((skinExtension != null) && (pluginClassLoader != null)) {
1091
            // configured skin was found
1092
            fixSkin(skinExtension, pluginClassLoader);
1093
        } else {
1094
            if (skinExtensions.contains("com.iver.core.mdiManager.NewSkin")) {
1095
                // try first NewSkin (from CorePlugin)
1096
                skinPlugin("com.iver.core.mdiManager.NewSkin");
1097
            } else
1098
                if (skinExtensions.size() > 0) {
1099
                    // try to load the first skin found
1100
                    SkinExtension se = (SkinExtension) skinExtensions.get(0);
1101
                    skinPlugin((String) se.getClassName());
1102
                } else {
1103
                    throw new MDIManagerLoadException(
1104
                        "No Skin-Extension installed");
1105
                }
1106
        }
1107

    
1108
    }
1109

    
1110
    private static void frameIcon(Theme theme) {
1111
        Iterator<String> i = pluginsConfig.keySet().iterator();
1112

    
1113
        while (i.hasNext()) {
1114
            String pName = i.next();
1115
            PluginConfig pc = pluginsConfig.get(pName);
1116
            if (pc.getIcon() != null) {
1117
                if (theme.getIcon() != null) {
1118
                    frame.setIconImage(theme.getIcon().getImage());
1119
                } else {
1120

    
1121
                    ImageIcon icon =
1122
                        PluginServices.getIconTheme()
1123
                            .get(pc.getIcon().getSrc());
1124
                    frame.setIconImage(icon.getImage());
1125

    
1126
                }
1127
                if (theme.getName() != null) {
1128
                    frame.setTitlePrefix(theme.getName());
1129
                } else {
1130
                    frame.setTitlePrefix(pc.getIcon().getText());
1131
                }
1132
                if (theme.getBackgroundImage() != null) {
1133

    
1134
                    PluginServices.getMDIManager().setBackgroundImage(
1135
                        theme.getBackgroundImage(), theme.getTypeDesktop());
1136
                }
1137
            }
1138
        }
1139
    }
1140

    
1141
    private void initializeExtensions() {
1142

    
1143
        List<ClassLoader> classLoaders =
1144
            new ArrayList<ClassLoader>(pluginsOrdered.size());
1145
        classLoaders.add(getClass().getClassLoader());
1146
        Iterator<String> iter = pluginsOrdered.iterator();
1147

    
1148
        // logger.debug("Initializing plugins libraries: ");
1149
        // while (iter.hasNext()) {
1150
        // String pName = (String) iter.next();
1151
        // PluginServices ps = (PluginServices) pluginsServices.get(pName);
1152
        // classLoaders.add(ps.getClassLoader());
1153
        // }
1154
        //
1155
        // // Create the libraries initializer and
1156
        // // initialize the plugin libraries
1157
        // new DefaultLibrariesInitializer(
1158
        // classLoaders.toArray(new ClassLoader[classLoaders.size()]))
1159
        // .fullInitialize();
1160
        //
1161
        // // Remove them all, we don't need them anymore
1162
        // classLoaders.clear();
1163
        // classLoaders = null;
1164

    
1165
        logger.info("Initializing plugins: ");
1166
        // iter = pluginsOrdered.iterator();
1167
        while (iter.hasNext()) {
1168
            String pName = (String) iter.next();
1169
            logger.info("Initializing plugin " + pName);
1170
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1171
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1172

    
1173
            Extension[] exts = pc.getExtensions().getExtension();
1174

    
1175
            TreeSet<Extension> orderedExtensions =
1176
                new TreeSet<Extension>(new ExtensionComparator());
1177

    
1178
            for (int j = 0; j < exts.length; j++) {
1179
                if (!exts[j].getActive()) {
1180
                    continue;
1181
                }
1182

    
1183
                if (orderedExtensions.contains(exts[j])) {
1184
                    logger.warn("Two extensions with the same priority ("
1185
                        + exts[j].getClassName() + ")");
1186
                }
1187

    
1188
                orderedExtensions.add(exts[j]);
1189
            }
1190

    
1191
            Iterator<Extension> e = orderedExtensions.iterator();
1192

    
1193
            logger.info("Initializing extensions of plugin "+pName+": ");
1194
            while (e.hasNext()) {
1195
                Extension extension = e.next();
1196
                org.gvsig.andami.plugins.IExtension extensionInstance;
1197

    
1198
                try {
1199
                    logger.info("Initializing " + extension.getClassName()
1200
                        + "...");
1201
                    Class<? extends IExtension> extensionClass =
1202
                        (Class<? extends IExtension>) ps.getClassLoader()
1203
                            .loadClass(extension.getClassName());
1204
                    extensionInstance = extensionClass.newInstance();
1205

    
1206
                    // CON DECORATOR
1207
                    // ANTES: classesExtensions.put(extensionClass,
1208
                    // extensionInstance);
1209
                    // AHORA: CREAMOS UNA ExtensionDecorator y asignamos esta
1210
                    // instancia para
1211
                    // poder ampliar con nuevas propiedades (AlwaysVisible, por
1212
                    // ejemplo)
1213
                    // Para crear la nueva clase ExtensionDecorator, le pasamos
1214
                    // como par?metro
1215
                    // la extensi?n original que acabamos de crear
1216
                    // 0-> Inactivo, controla la extension
1217
                    // 1-> Siempre visible
1218
                    // 2-> Invisible
1219
                    ExtensionDecorator newExtensionDecorator =
1220
                        new ExtensionDecorator(extensionInstance,
1221
                            ExtensionDecorator.INACTIVE);
1222
                    classesExtensions
1223
                        .put(extensionClass, newExtensionDecorator);
1224

    
1225
                    extensionInstance.initialize();
1226
                    extensions.add(extensionInstance);
1227

    
1228
                } catch (NoClassDefFoundError e1) {
1229
                    this.addError("Can't find class extension ("
1230
                        + extension.getClassName() + ")", e1);
1231
                } catch (Throwable e1) {
1232
                    this.addError("Can't initialize extension '"
1233
                        + extension.getClassName() + "'.", e1);
1234
                }
1235
            }
1236
        }
1237
    }
1238

    
1239
    private void postInitializeExtensions() {
1240
        logger.info("PostInitializing extensions: ");
1241

    
1242
        for (int i = 0; i < extensions.size(); i++) {
1243
            org.gvsig.andami.plugins.IExtension extensionInstance =
1244
                (org.gvsig.andami.plugins.IExtension) extensions.get(i);
1245
            logger.info("PostInitializing "
1246
                + extensionInstance.getClass().getName() + "...");
1247
            try {
1248
                extensionInstance.postInitialize();
1249
            } catch (Throwable ex) {
1250
                this.addError("postInitialize of extension '"
1251
                    + extensionInstance.getClass().getName() + "' failed", ex);
1252
            }
1253
        }
1254
    }
1255

    
1256
    private void installPluginsMenus() {
1257
        TreeSet<SortableMenu> orderedMenus =
1258
            new TreeSet<SortableMenu>(new MenuComparator());
1259

    
1260
        Iterator<String> i = pluginsConfig.keySet().iterator();
1261

    
1262
        while (i.hasNext()) {
1263
            String pName = i.next();
1264
                try {
1265
            PluginServices ps = pluginsServices.get(pName);
1266
            PluginConfig pc = pluginsConfig.get(pName);
1267

    
1268
            Extension[] exts = pc.getExtensions().getExtension();
1269

    
1270
            for (int j = 0; j < exts.length; j++) {
1271
                if (!exts[j].getActive()) {
1272
                    continue;
1273
                }
1274

    
1275
                Menu[] menus = exts[j].getMenu();
1276

    
1277
                for (int k = 0; k < menus.length; k++) {
1278
                    SortableMenu sm =
1279
                        new SortableMenu(ps.getClassLoader(), exts[j], menus[k]);
1280

    
1281
                    if (orderedMenus.contains(sm)) {
1282
                        this
1283
                            .addError(Messages
1284
                                .getString("Launcher.Two_menus_with_the_same_position")
1285
                                + " - "
1286
                                + menus[k].getText()
1287
                                + " - "
1288
                                + exts[j].getClassName());
1289
                    }
1290

    
1291
                    orderedMenus.add(sm);
1292
                }
1293
            }
1294

    
1295
            // Se instalan las extensiones de MDI
1296
            SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1297
            for (int j = 0; j < skinExts.length; j++) {
1298

    
1299
                if (skinExts[j] != null) {
1300
                    Menu[] menu = skinExts[j].getMenu();
1301

    
1302
                    for (int k = 0; k < menu.length; k++) {
1303
                        SortableMenu sm =
1304
                            new SortableMenu(ps.getClassLoader(), skinExts[j],
1305
                                menu[k]);
1306

    
1307
                        if (orderedMenus.contains(sm)) {
1308
                            this
1309
                                .addError(Messages
1310
                                    .getString("Launcher.Two_menus_with_the_same_position")
1311
                                    + skinExts[j].getClassName());
1312
                        }
1313

    
1314
                        orderedMenus.add(sm);
1315
                    }
1316
                }
1317
            }
1318
            
1319
            
1320
                } catch (Throwable e) {
1321
                        addError("Error initializing menus of plugin '"+pName+"'", e);
1322
                        }
1323
            
1324
            
1325
        }
1326

    
1327
        // Se itera por los menus ordenados
1328
        Iterator<SortableMenu> e = orderedMenus.iterator();
1329

    
1330
        // Se ordenan los menues
1331
        while (e.hasNext()) {
1332
            try {
1333
                SortableMenu sm = e.next();
1334

    
1335
                frame.addMenu(sm.loader, sm.extension, sm.menu);
1336

    
1337
            } catch (ClassNotFoundException ex) {
1338
                this
1339
                    .addError(
1340
                        Messages
1341
                            .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1342
                        ex);
1343
            } catch (NoClassDefFoundError ex) {
1344
                this
1345
                .addError(
1346
                    Messages
1347
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1348
                    ex);
1349
            } catch (Throwable ex) {
1350
                this
1351
                .addError(
1352
                    Messages
1353
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1354
                    ex);
1355
            }
1356
        }
1357
    }
1358

    
1359
    /**
1360
     * Installs the menus, toolbars, actiontools, selectable toolbars and
1361
     * combos.
1362
     * The order in which they are shown is determined here.
1363
     */
1364
    private void installPluginsControls() {
1365
        Iterator<String> i = pluginsConfig.keySet().iterator();
1366

    
1367
        Map<Extension, PluginServices> extensionPluginServices =
1368
            new HashMap<Extension, PluginServices>();
1369
        Map<Extension, PluginConfig> extensionPluginConfig =
1370
            new HashMap<Extension, PluginConfig>();
1371
        Set<Extension> orderedExtensions =
1372
            new TreeSet<Extension>(new ExtensionComparator());
1373

    
1374
        // First of all, sort the extensions.
1375
        // We need to iterate on the plugins, and iterate on each plugin's
1376
        // extensions
1377
        // (each plugin may contain one or more extensions)
1378
        while (i.hasNext()) { // iterate on the plugins
1379
                    String pName = i.next();
1380
                try {
1381
                        PluginConfig pc = pluginsConfig.get(pName);
1382
                        PluginServices ps = pluginsServices.get(pName);
1383

    
1384
                        Extension[] exts = pc.getExtensions().getExtension();
1385

    
1386
                        for (int j = 0; j < exts.length; j++) { // iterate on the extensions
1387
                                String cname = "unknow";
1388
                                try {
1389
                                    cname = exts[j].getClassName();
1390
                                        if (exts[j].getActive()  && !cname.equals(LibraryExtension.class.getName()) ) {
1391
                                                if (orderedExtensions.contains(exts[j])) {
1392
                                                        this
1393
                                                        .addError(Messages
1394
                                                                        .getString("Launcher.Two_extensions_with_the_same_priority")
1395
                                                                        + cname);
1396
                                                }
1397

    
1398
                                                orderedExtensions.add(exts[j]);
1399
                                                extensionPluginServices.put(exts[j], ps);
1400
                                                extensionPluginConfig.put(exts[j], pc);
1401
                                        }
1402
                                } catch (Exception e) {
1403
                                addError("Error initializing controls of plugin '"+pName+"' extension '"+cname+"'", e);
1404
                                        }
1405
                        }
1406
                } catch (Throwable e) {
1407
                        addError("Error initializing controls of plugin '"+pName+"'", e);
1408
                }
1409
        }
1410

    
1411
        TreeSet<SortableTool> orderedTools =
1412
            new TreeSet<SortableTool>(new ToolComparator());
1413
        Iterator<Extension> e = orderedExtensions.iterator();
1414

    
1415
        // sort the toolbars and tools from 'normal' extensions (actiontools,
1416
        // selectabletools)
1417
        // and load the combo-scales and combo-buttons for the status bar
1418
        while (e.hasNext()) {
1419
                    Extension ext = e.next();
1420
                    String extName = "unknow";
1421
                try {
1422
                        extName = ext.getClassName();
1423
                        ToolBar[] toolbars = ext.getToolBar();
1424

    
1425
                        // get tools from toolbars
1426
                        for (int k = 0; k < toolbars.length; k++) {
1427
                                ActionTool[] tools = toolbars[k].getActionTool();
1428

    
1429
                                for (int t = 0; t < tools.length; t++) {
1430
                                        SortableTool sm =
1431
                                                new SortableTool((extensionPluginServices.get(ext))
1432
                                                                .getClassLoader(), ext, toolbars[k], tools[t]);
1433
                                        orderedTools.add(sm);
1434
                                }
1435

    
1436
                                SelectableTool[] sTools = toolbars[k].getSelectableTool();
1437

    
1438
                                for (int t = 0; t < sTools.length; t++) {
1439
                                        SortableTool sm =
1440
                                                new SortableTool((extensionPluginServices.get(ext))
1441
                                                                .getClassLoader(), ext, toolbars[k], sTools[t]);
1442
                                        orderedTools.add(sm);
1443
                                }
1444
                        }
1445

    
1446
                        // get controls for statusBar
1447
                        PluginServices ps = extensionPluginServices.get(ext);
1448
                        PluginClassLoader loader = ps.getClassLoader();
1449

    
1450
                        // ArrayList componentList = new ArrayList();
1451
                        ComboScale[] comboScaleArray = ext.getComboScale();
1452
                        for (int k = 0; k < comboScaleArray.length; k++) {
1453
                                org.gvsig.gui.beans.controls.comboscale.ComboScale combo =
1454
                                        new org.gvsig.gui.beans.controls.comboscale.ComboScale();
1455
                                String label = comboScaleArray[k].getLabel();
1456
                                if (label != null) {
1457
                                        combo.setLabel(label);
1458
                                }
1459
                                String name = comboScaleArray[k].getName();
1460
                                if (name != null) {
1461
                                        combo.setName(name);
1462
                                }
1463
                                String[] elementsString =
1464
                                        ((String) comboScaleArray[k].getElements()).split(";");
1465
                                long[] elements = new long[elementsString.length];
1466
                                for (int currentElem = 0; currentElem < elementsString.length; currentElem++) {
1467
                                        try {
1468
                                                elements[currentElem] =
1469
                                                        Long.parseLong(elementsString[currentElem]);
1470
                                        } catch (NumberFormatException nfex1) {
1471
                                                this
1472
                                                .addError(ext.getClassName()
1473
                                                                + " -- "
1474
                                                                + Messages
1475
                                                                .getString("error_parsing_comboscale_elements"));
1476
                                                elements[currentElem] = 0;
1477
                                        }
1478
                                }
1479
                                combo.setItems(elements);
1480
                                try {
1481
                                        long value =
1482
                                                Long.parseLong((String) comboScaleArray[k].getValue());
1483
                                        combo.setScale(value);
1484
                                } catch (NumberFormatException nfex2) {
1485
                                        this.addError(ext.getClassName() + " -- "
1486
                                                        + Messages.getString("error_parsing_comboscale_value"));
1487
                                }
1488
                                try {
1489
                                        frame.addStatusBarControl(loader.loadClass(ext
1490
                                                        .getClassName()), combo);
1491
                                } catch (ClassNotFoundException e1) {
1492
                                        this
1493
                                        .addError(
1494
                                                        Messages
1495
                                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
1496
                                                        e1);
1497
                                }
1498
                        }
1499

    
1500
                        ComboButton[] comboButtonArray = ext.getComboButton();
1501
                        for (int k = 0; k < comboButtonArray.length; k++) {
1502
                                ComboButtonElement[] elementList =
1503
                                        comboButtonArray[k].getComboButtonElement();
1504
                                org.gvsig.gui.beans.controls.combobutton.ComboButton combo =
1505
                                        new org.gvsig.gui.beans.controls.combobutton.ComboButton();
1506
                                String name = comboButtonArray[k].getName();
1507
                                if (name != null) {
1508
                                        combo.setName(name);
1509
                                }
1510
                                for (int currentElement = 0; currentElement < elementList.length; currentElement++) {
1511
                                        ComboButtonElement element = elementList[currentElement];
1512
                                        ImageIcon icon;
1513
                                        URL iconLocation = loader.getResource(element.getIcon());
1514
                                        if (iconLocation == null) {
1515
                                                this.addError(Messages.getString("Icon_not_found_")
1516
                                                                + element.getIcon());
1517
                                        } else {
1518
                                                icon = new ImageIcon(iconLocation);
1519
                                                JButton button = new JButton(icon);
1520
                                                combo.addButton(button);
1521
                                                button.setActionCommand(element.getActionCommand());
1522
                                        }
1523
                                }
1524
                                try {
1525
                                        frame.addStatusBarControl(loader.loadClass(ext
1526
                                                        .getClassName()), combo);
1527
                                } catch (ClassNotFoundException e1) {
1528
                                        this
1529
                                        .addError(
1530
                                                        Messages
1531
                                                        .getString("Launcher.error_getting_class_loader_for_status_bar_control"),
1532
                                                        e1);
1533
                                }
1534
                        }
1535
                } catch (Throwable e2) {
1536
                        addError("Error initializing tools and status bars of extension '"+extName+"'", e2);
1537
                }
1538
        }
1539

    
1540
        // Add the tools from MDI extensions to the ordered tool-list, so that
1541
        // we get a sorted list containing all the tools
1542
        i = pluginsConfig.keySet().iterator();
1543
        while (i.hasNext()) {
1544
                String pName = (String) i.next();
1545
                try {
1546
                        PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1547
                        PluginServices ps = (PluginServices) pluginsServices.get(pName);
1548

    
1549
                        SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1550
                        for (int j = 0; j < skinExts.length; j++) {
1551

    
1552
                                if (skinExts[j] != null) {
1553
                                        ToolBar[] toolbars = skinExts[j].getToolBar();
1554

    
1555
                                        for (int k = 0; k < toolbars.length; k++) {
1556
                                                ActionTool[] tools = toolbars[k].getActionTool();
1557

    
1558
                                                for (int t = 0; t < tools.length; t++) {
1559
                                                        SortableTool stb =
1560
                                                                new SortableTool(ps.getClassLoader(),
1561
                                                                                skinExts[j], toolbars[k], tools[t]);
1562
                                                        orderedTools.add(stb);
1563
                                                }
1564

    
1565
                                                SelectableTool[] sTools =
1566
                                                        toolbars[k].getSelectableTool();
1567

    
1568
                                                for (int t = 0; t < sTools.length; t++) {
1569
                                                        SortableTool stb =
1570
                                                                new SortableTool(ps.getClassLoader(),
1571
                                                                                skinExts[j], toolbars[k], sTools[t]);
1572
                                                        orderedTools.add(stb);
1573
                                                }
1574
                                        }
1575
                                }
1576
                        }
1577
                        // Install popup menus
1578
                        PopupMenus pus = pc.getPopupMenus();
1579

    
1580
                        if (pus != null) {
1581
                                PopupMenu[] menus = pus.getPopupMenu();
1582

    
1583
                                for (int j = 0; j < menus.length; j++) {
1584
                                        frame.addPopupMenu(ps.getClassLoader(), menus[j]);
1585
                                }
1586
                        }
1587
                } catch (Throwable e3) {
1588
                        addError("Error initializing skins of the plugin '"+pName+"'", e3);
1589
                }
1590
        }
1591

    
1592
        // loop on the ordered extension list, to add them to the interface in
1593
        // an ordered way
1594
        Iterator<SortableTool> t = orderedTools.iterator();
1595
        while (t.hasNext()) {
1596
            SortableTool stb = t.next();
1597
            try {
1598
                if (stb.actiontool != null) {
1599
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
1600
                        stb.actiontool);
1601
                } else {
1602
                    frame.addTool(stb.loader, stb.extension, stb.toolbar,
1603
                        stb.selectabletool);
1604
                }
1605
            } catch (ClassNotFoundException ex) {
1606
                this
1607
                    .addError(
1608
                        Messages
1609
                            .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1610
                        ex);
1611
            } catch (Throwable e2) {
1612
                    addError("Error adding tools to the interface of extension '"+ stb.extension.getClassName() + "'", e2);
1613
                        }
1614
        }
1615
    }
1616

    
1617
    /**
1618
     * Adds new plugins to the the andami-config file.
1619
     */
1620
    private void updateAndamiConfig() {
1621
        Set<String> olds = new HashSet<String>();
1622

    
1623
        Plugin[] plugins = andamiConfig.getPlugin();
1624

    
1625
        for (int i = 0; i < plugins.length; i++) {
1626
            olds.add(plugins[i].getName());
1627
        }
1628

    
1629
        Iterator<PluginServices> i = pluginsServices.values().iterator();
1630

    
1631
        while (i.hasNext()) {
1632
            PluginServices ps = i.next();
1633

    
1634
            if (!olds.contains(ps.getPluginName())) {
1635
                Plugin p = new Plugin();
1636
                p.setName(ps.getPluginName());
1637
                p.setUpdate(false);
1638

    
1639
                andamiConfig.addPlugin(p);
1640
            }
1641
        }
1642
    }
1643

    
1644
    private void pluginsClassLoaders() {
1645
        Set<String> installed = new HashSet<String>();
1646

    
1647
        // Se itera hasta que est?n todos instalados
1648
        while (installed.size() != pluginsConfig.size()) {
1649
            boolean circle = true;
1650

    
1651
            // Hacemos una pasada por todos los plugins
1652
            Iterator<String> i = pluginsConfig.keySet().iterator();
1653

    
1654
            while (i.hasNext()) {
1655
                String pluginName = i.next();
1656
                PluginConfig config =
1657
                    (PluginConfig) pluginsConfig.get(pluginName);
1658

    
1659
                if (installed.contains(pluginName)) {
1660
                    continue;
1661
                }
1662

    
1663
                // Se obtienen las dependencias y sus class loaders
1664
                boolean ready = true;
1665
                Depends[] dependencies = config.getDepends();
1666
                PluginClassLoader[] loaders =
1667
                    new PluginClassLoader[dependencies.length];
1668

    
1669
                for (int j = 0; j < dependencies.length; j++) {
1670
                    if (pluginsConfig.get(dependencies[j].getPluginName()) == null) {
1671
                        this
1672
                            .addError(Messages
1673
                                .getString("Launcher.Dependencia_no_resuelta_en_plugin")
1674
                                + " "
1675
                                + pluginName
1676
                                + ": "
1677
                                + dependencies[j].getPluginName());
1678

    
1679
                        continue;
1680
                    }
1681

    
1682
                    if (!installed.contains(dependencies[j].getPluginName())) {
1683
                        ready = false;
1684
                    } else {
1685
                        loaders[j] =
1686
                            (pluginsServices.get(dependencies[j]
1687
                                .getPluginName())).getClassLoader();
1688
                    }
1689
                }
1690

    
1691
                // Si no est?n sus dependencias satisfechas se aborta la
1692
                // instalaci?n
1693
                if (!ready) {
1694
                    continue;
1695
                }
1696

    
1697
                // Se genera el class loader
1698
                String jardir = config.getLibraries().getLibraryDir();
1699
                File jarDir =
1700
                    new File(andamiConfig.getPluginsDirectory(), pluginName
1701
                        + File.separator + jardir);
1702
                File[] jarFiles = jarDir.listFiles(new FileFilter() {
1703

    
1704
                    public boolean accept(File pathname) {
1705
                        return (pathname.getName().toUpperCase()
1706
                            .endsWith(".JAR"))
1707
                            || (pathname.getName().toUpperCase()
1708
                                .endsWith(".ZIP"));
1709
                    }
1710
                });
1711

    
1712
                URL[] urls = new URL[jarFiles.length];
1713

    
1714
                for (int j = 0; j < jarFiles.length; j++) {
1715
                    try {
1716
                        urls[j] = new URL("file:" + jarFiles[j]);
1717
                    } catch (MalformedURLException e) {
1718
                        this.addError(Messages
1719
                            .getString("Launcher.No_se_puede_acceder_a")
1720
                            + " " + jarFiles[j]);
1721
                    }
1722
                }
1723

    
1724
                PluginClassLoader loader;
1725

    
1726
                try {
1727
                    loader =
1728
                        new PluginClassLoader(urls, andamiConfig
1729
                            .getPluginsDirectory()
1730
                            + File.separator + pluginName, Launcher.class
1731
                            .getClassLoader(), loaders);
1732

    
1733
                    PluginServices ps = new PluginServices(loader);
1734

    
1735
                    pluginsServices.put(ps.getPluginName(), ps);
1736

    
1737
                    installed.add(pluginName);
1738
                    // FJP: Los metemos ordenados para luego no cargar uno que
1739
                    // necesita de otro antes de tiempo. Esto lo usaremos al
1740
                    // inicializar los plugins
1741
                    pluginsOrdered.add(pluginName);
1742

    
1743
                    circle = false;
1744
                } catch (IOException e) {
1745
                    this
1746
                        .addError(
1747
                            Messages
1748
                                .getString("Launcher.Error_con_las_librerias_del_plugin"),
1749
                            e);
1750
                    pluginsConfig.remove(pluginName);
1751
                    i = pluginsConfig.keySet().iterator();
1752
                }
1753
            }
1754

    
1755
            if (circle) {
1756
                this.addError(Messages
1757
                    .getString("Launcher.Hay_dependencias_circulares"));
1758

    
1759
                break;
1760
            }
1761
        }
1762

    
1763
        // Se eliminan los plugins que no fueron instalados
1764
        Iterator<String> i = pluginsConfig.keySet().iterator();
1765

    
1766
        while (i.hasNext()) {
1767
            String pluginName = i.next();
1768
            PluginServices ps =
1769
                (PluginServices) pluginsServices.get(pluginName);
1770

    
1771
            if (ps == null) {
1772
                pluginsConfig.remove(pluginName);
1773
                i = pluginsConfig.keySet().iterator();
1774
            }
1775
        }
1776
    }
1777

    
1778
    private void pluginsMessages() {
1779
        Iterator<String> iterator = pluginsOrdered.iterator();
1780
        PluginConfig config;
1781
        PluginServices ps;
1782

    
1783
        while (iterator.hasNext()) {
1784
            String pluginName = iterator.next();
1785
            config = pluginsConfig.get(pluginName);
1786
            ps = pluginsServices.get(pluginName);
1787

    
1788
            if ((config.getResourceBundle() != null)
1789
                && !config.getResourceBundle().getName().equals("")) {
1790
                // add the locale files associated with the plugin
1791
                org.gvsig.i18n.Messages.addResourceFamily(config
1792
                    .getResourceBundle().getName(), ps.getClassLoader(),
1793
                    pluginName);
1794
            }
1795
        }
1796
    }
1797

    
1798
    static public PluginServices getPluginServices(String name) {
1799
        return (PluginServices) pluginsServices.get(name);
1800
    }
1801

    
1802
    static String getPluginsDir() {
1803
        return andamiConfig.getPluginsDirectory();
1804
    }
1805

    
1806
    static void setPluginsDir(String s) {
1807
        andamiConfig.setPluginsDirectory(s);
1808
    }
1809

    
1810
    static MDIFrame getMDIFrame() {
1811
        return frame;
1812
    }
1813

    
1814
    private void loadPlugins(String pluginsDirectory) {
1815
        File pDir = new File(pluginsDirectory);
1816

    
1817
        if (!pDir.exists()) {
1818
            logger
1819
                .error("\n\tPlugins directory not found: "
1820
                    + pDir.getAbsolutePath()
1821
                    + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1822
            System.exit(-1);
1823
            return;
1824
        }
1825

    
1826
        File[] pluginDirs = pDir.listFiles();
1827
        if (pluginDirs.length == 0) {
1828
            logger
1829
                .error("\n\tPlugins directory is empty: "
1830
                    + pDir.getAbsolutePath()
1831
                    + "Did you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1832
            System.exit(-1);
1833
            return;
1834
        }
1835

    
1836
        for (int i = 0; i < pluginDirs.length; i++) {
1837
            if (pluginDirs[i].isDirectory()) {
1838
                File configXml =
1839
                    new File(pluginDirs[i].getAbsolutePath(), "config.xml");
1840

    
1841
                try {
1842
                    FileInputStream is = new FileInputStream(configXml);
1843
                    Reader xml =
1844
                        org.gvsig.utils.xml.XMLEncodingUtils.getReader(is);
1845
                    if (xml == null) {
1846
                        // the encoding was not correctly detected, use system
1847
                        // default
1848
                        xml = new FileReader(configXml);
1849
                    } else {
1850
                        // use a buffered reader to improve performance
1851
                        xml = new BufferedReader(xml);
1852
                    }
1853
                    PluginConfig pConfig =
1854
                        (PluginConfig) PluginConfig.unmarshal(xml);
1855
                    pluginsConfig.put(pluginDirs[i].getName(), pConfig);
1856
                } catch (FileNotFoundException e) {
1857
                    logger
1858
                        .info("Plugin folder without config.xml. Skip plugin '"
1859
                            + pluginDirs[i].getAbsolutePath() + "'.");
1860
                } catch (MarshalException e) {
1861
                    this.addError("Can't load plugin '"
1862
                        + pluginDirs[i].getAbsolutePath() + "'.", e);
1863
                } catch (ValidationException e) {
1864
                    this.addError("Can't load plugin '"
1865
                        + pluginDirs[i].getAbsolutePath() + "'.", e);
1866
                }
1867
            }
1868
        }
1869

    
1870
        if (pluginsConfig.size() == 0) {
1871
            logger
1872
                .error("No valid plugin was found. The plugins directory currently is: "
1873
                    + pDir.getAbsolutePath()
1874
                    + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now...");
1875
            System.exit(-1);
1876
            return;
1877
        }
1878
    }
1879

    
1880
    private static Locale getLocale(String language, String country,
1881
        String variant) {
1882
        if (variant != null) {
1883
            return new Locale(language, country, variant);
1884
        } else
1885
            if (country != null) {
1886
                return new Locale(language, country);
1887
            } else
1888
                if (language != null) {
1889
                    return new Locale(language);
1890
                } else {
1891
                    return new Locale("es");
1892
                }
1893
    }
1894

    
1895
    private static void andamiConfigToXML(String file) throws IOException,
1896
        MarshalException, ValidationException {
1897
        // write on a temporary file in order to not destroy current file if
1898
        // there is some problem while marshaling
1899
        File tmpFile =
1900
            new File(file + "-" + DateTime.getCurrentDate().getTime());
1901
        File xml = new File(file);
1902
        File parent = xml.getParentFile();
1903
        parent.mkdirs();
1904

    
1905
        BufferedOutputStream os =
1906
            new BufferedOutputStream(new FileOutputStream(tmpFile));
1907
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
1908
        andamiConfig.marshal(writer);
1909
        writer.close();
1910

    
1911
        // if marshaling process finished correctly, move the file to the
1912
        // correct one
1913
        xml.delete();
1914
        if (!tmpFile.renameTo(xml)) {
1915
            // if rename was not succesful, try copying it
1916
            FileChannel sourceChannel =
1917
                new FileInputStream(tmpFile).getChannel();
1918
            FileChannel destinationChannel =
1919
                new FileOutputStream(xml).getChannel();
1920
            sourceChannel.transferTo(0, sourceChannel.size(),
1921
                destinationChannel);
1922
            sourceChannel.close();
1923
            destinationChannel.close();
1924
        }
1925
    }
1926

    
1927
    private static void andamiConfigFromXML(String file)
1928
        throws ConfigurationException {
1929
        File xml = new File(file);
1930

    
1931
        InputStreamReader reader = null;
1932
        try {
1933
            // Se lee la configuraci?n
1934
            reader = XMLEncodingUtils.getReader(xml);
1935
            andamiConfig = (AndamiConfig) AndamiConfig.unmarshal(reader);
1936
        } catch (FileNotFoundException e) {
1937
            // Si no existe se ponen los valores por defecto
1938
            andamiConfig = getDefaultAndamiConfig();
1939
        } catch (MarshalException e) {
1940
            // try to close the stream, maybe it remains open
1941
            if (reader != null) {
1942
                try {
1943
                    reader.close();
1944
                } catch (IOException e1) {
1945
                }
1946
            }
1947
            // if there was a problem reading the file, backup it and create a
1948
            // new one with default values
1949
            String backupFile =
1950
                file + "-" + DateTime.getCurrentDate().getTime();
1951
            NotificationManager
1952
                .addError(
1953
                    Messages
1954
                        .getString("Error_reading_andami_config_New_file_created_A_backup_was_made_on_")
1955
                        + backupFile, new ConfigurationException(e));
1956
            xml.renameTo(new File(backupFile));
1957
            andamiConfig = getDefaultAndamiConfig();
1958
        } catch (ValidationException e) {
1959
            throw new ConfigurationException(e);
1960
        }
1961
    }
1962

    
1963
    private static AndamiConfig getDefaultAndamiConfig() {
1964
        AndamiConfig andamiConfig = new AndamiConfig();
1965

    
1966
        Andami andami = new Andami();
1967
        andami.setUpdate(true);
1968
        andamiConfig.setAndami(andami);
1969
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
1970
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
1971
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
1972

    
1973
        if (System.getProperty("javawebstart.version") != null) // Es java web
1974
        // start)
1975
        {
1976
            andamiConfig
1977
                .setPluginsDirectory(new File(appHomeDir, "extensiones")
1978
                    .getAbsolutePath());
1979
        } else {
1980
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
1981
                .getAbsolutePath());
1982
        }
1983

    
1984
        andamiConfig.setPlugin(new Plugin[0]);
1985
        return andamiConfig;
1986
    }
1987

    
1988
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
1989
        File xml = getPluginsPersistenceFile(true);
1990

    
1991
        if (xml.exists()) {
1992
            InputStreamReader reader = null;
1993

    
1994
            try {
1995
                reader = XMLEncodingUtils.getReader(xml);
1996
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1997
                return new XMLEntity(tag);
1998
            } catch (FileNotFoundException e) {
1999
                throw new ConfigurationException(e);
2000
            } catch (MarshalException e) {
2001

    
2002
                // try to reopen with default encoding (for backward
2003
                // compatibility)
2004
                try {
2005
                    reader = new FileReader(xml);
2006
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
2007
                    return new XMLEntity(tag);
2008

    
2009
                } catch (MarshalException ex) {
2010
                    // try to close the stream, maybe it remains open
2011
                    if (reader != null) {
2012
                        try {
2013
                            reader.close();
2014
                        } catch (IOException e1) {
2015
                        }
2016
                    }
2017
                    // backup the old file
2018
                    String backupFile =
2019
                        getPluginsPersistenceFile(true).getPath() + "-"
2020
                            + DateTime.getCurrentDate().getTime();
2021
                    NotificationManager
2022
                        .addError(
2023
                            Messages
2024
                                .getString("Error_reading_plugin_persinstence_New_file_created_A_backup_was_made_on_")
2025
                                + backupFile, new ConfigurationException(e));
2026
                    xml.renameTo(new File(backupFile));
2027
                    // create a new, empty configuration
2028
                    return new XMLEntity();
2029
                } catch (FileNotFoundException ex) {
2030
                    return new XMLEntity();
2031
                } catch (ValidationException ex) {
2032
                    throw new ConfigurationException(e);
2033
                }
2034
            } catch (ValidationException e) {
2035
                throw new ConfigurationException(e);
2036
            }
2037
        } else {
2038
            return new XMLEntity();
2039
        }
2040
    }
2041

    
2042
    private static File getPluginsPersistenceFile(boolean read) {
2043
        if (read) {
2044
            File pluginsPersistenceFile =
2045
                new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2046
            if (pluginsPersistenceFile.exists()) {
2047
                return pluginsPersistenceFile;
2048
            }
2049
            pluginsPersistenceFile =
2050
                new File(getAppHomeDir(), "plugins-persistence.xml");
2051
            if (pluginsPersistenceFile.exists()) {
2052
                return pluginsPersistenceFile;
2053
            }
2054
        }
2055
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2056

    
2057
    }
2058

    
2059
    private static void persistenceToXML(XMLEntity entity)
2060
        throws ConfigurationException {
2061
        // write on a temporary file in order to not destroy current file if
2062
        // there is some problem while marshaling
2063
        File tmpFile =
2064
            new File(getPluginsPersistenceFile(false).getPath() + "-"
2065
                + DateTime.getCurrentDate().getTime());
2066

    
2067
        File xml = getPluginsPersistenceFile(false);
2068
        OutputStreamWriter writer = null;
2069

    
2070
        try {
2071
            writer =
2072
                new OutputStreamWriter(new FileOutputStream(tmpFile),
2073
                    CASTORENCODING);
2074
            entity.getXmlTag().marshal(writer);
2075
            writer.close();
2076

    
2077
            // if marshaling process finished correctly, move the file to the
2078
            // correct one
2079
            xml.delete();
2080
            if (!tmpFile.renameTo(xml)) {
2081
                // if rename was not succesful, try copying it
2082
                FileChannel sourceChannel =
2083
                    new FileInputStream(tmpFile).getChannel();
2084
                FileChannel destinationChannel =
2085
                    new FileOutputStream(xml).getChannel();
2086
                sourceChannel.transferTo(0, sourceChannel.size(),
2087
                    destinationChannel);
2088
                sourceChannel.close();
2089
                destinationChannel.close();
2090

    
2091
            }
2092
        } catch (FileNotFoundException e) {
2093
            throw new ConfigurationException(e);
2094
        } catch (MarshalException e) {
2095
            // try to close the stream, maybe it remains open
2096
            if (writer != null) {
2097
                try {
2098
                    writer.close();
2099
                } catch (IOException e1) {
2100
                }
2101
            }
2102
        } catch (ValidationException e) {
2103
            throw new ConfigurationException(e);
2104
        } catch (IOException e) {
2105
            throw new ConfigurationException(e);
2106
        }
2107
    }
2108

    
2109
    static MDIFrame getFrame() {
2110
        return frame;
2111
    }
2112

    
2113
    /**
2114
     * Gracefully closes the application. It shows dialogs to save data,
2115
     * finish processes, etc, then it terminates the extensions, removes
2116
     * temporal files and finally exits.
2117
     */
2118
    public synchronized static void closeApplication() {
2119
        TerminationProcess terminationProcess =
2120
            (new Launcher()).new TerminationProcess();
2121
        terminationProcess.run();
2122
    }
2123

    
2124
    static HashMap getClassesExtensions() {
2125
        return classesExtensions;
2126
    }
2127

    
2128
    private static Extensions[] getExtensions() {
2129
        List<Extensions> array = new ArrayList<Extensions>();
2130
        Iterator<PluginConfig> iter = pluginsConfig.values().iterator();
2131

    
2132
        while (iter.hasNext()) {
2133
            array.add(iter.next().getExtensions());
2134
        }
2135

    
2136
        return array.toArray(new Extensions[array.size()]);
2137
    }
2138

    
2139
    public static Iterator getExtensionIterator() {
2140
        return extensions.iterator();
2141
    }
2142

    
2143
    public static HashMap getPluginConfig() {
2144
        return pluginsConfig;
2145
    }
2146

    
2147
    public static Extension getExtension(String s) {
2148
        Extensions[] exts = getExtensions();
2149

    
2150
        for (int i = 0; i < exts.length; i++) {
2151
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2152
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2153
                    return exts[i].getExtension(j);
2154
                }
2155
            }
2156
        }
2157

    
2158
        return null;
2159
    }
2160

    
2161
    public static AndamiConfig getAndamiConfig() {
2162
        return andamiConfig;
2163
    }
2164

    
2165
    private static class ExtensionComparator implements Comparator {
2166

    
2167
        public int compare(Object o1, Object o2) {
2168
            Extension e1 = (Extension) o1;
2169
            Extension e2 = (Extension) o2;
2170

    
2171
            if (!e1.hasPriority() && !e2.hasPriority()) {
2172
                return -1;
2173
            }
2174

    
2175
            if (e1.hasPriority() && !e2.hasPriority()) {
2176
                return Integer.MIN_VALUE;
2177
            }
2178

    
2179
            if (e2.hasPriority() && !e1.hasPriority()) {
2180
                return Integer.MAX_VALUE;
2181
            }
2182

    
2183
            if (e1.getPriority() != e2.getPriority()) {
2184
                return e2.getPriority() - e1.getPriority();
2185
            } else {
2186
                return (e2.toString().compareTo(e1.toString()));
2187
            }
2188
        }
2189
    }
2190

    
2191
    private static class MenuComparator implements Comparator<SortableMenu> {
2192

    
2193
        private static ExtensionComparator extComp = new ExtensionComparator();
2194

    
2195
        public int compare(SortableMenu e1, SortableMenu e2) {
2196

    
2197
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2198
                if (e1.extension instanceof SkinExtensionType) {
2199
                    return 1;
2200
                } else
2201
                    if (e2.extension instanceof SkinExtensionType) {
2202
                        return -1;
2203
                    } else {
2204
                        return extComp.compare(e1.extension, e2.extension);
2205
                    }
2206
            }
2207

    
2208
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2209
                return Integer.MIN_VALUE;
2210
            }
2211

    
2212
            if (e2.menu.hasPosition() && !e1.menu.hasPosition()) {
2213
                return Integer.MAX_VALUE;
2214
            }
2215
            if (e1.menu.getPosition() != e2.menu.getPosition()) {
2216
                // we don't return 0 unless both objects are the same, otherwise
2217
                // the objects get overwritten in the treemap
2218
                return e1.menu.getPosition() - e2.menu.getPosition();
2219
            } else {
2220
                return (e1.toString().compareTo(e2.toString()));
2221
            }
2222
        }
2223
    }
2224

    
2225
    private static class SortableMenu {
2226

    
2227
        public PluginClassLoader loader;
2228
        public Menu menu;
2229
        public SkinExtensionType extension;
2230

    
2231
        public SortableMenu(PluginClassLoader loader,
2232
            SkinExtensionType skinExt, Menu menu2) {
2233
            extension = skinExt;
2234
            menu = menu2;
2235
            this.loader = loader;
2236
        }
2237
    }
2238

    
2239
    private static class SortableTool {
2240

    
2241
        public PluginClassLoader loader;
2242
        public ToolBar toolbar;
2243
        public ActionTool actiontool;
2244
        public SelectableTool selectabletool;
2245
        public SkinExtensionType extension;
2246

    
2247
        public SortableTool(PluginClassLoader loader,
2248
            SkinExtensionType skinExt, ToolBar toolbar2, ActionTool actiontool2) {
2249
            extension = skinExt;
2250
            toolbar = toolbar2;
2251
            actiontool = actiontool2;
2252
            this.loader = loader;
2253
        }
2254

    
2255
        public SortableTool(PluginClassLoader loader,
2256
            SkinExtensionType skinExt, ToolBar toolbar2,
2257
            SelectableTool selectabletool2) {
2258
            extension = skinExt;
2259
            toolbar = toolbar2;
2260
            selectabletool = selectabletool2;
2261
            this.loader = loader;
2262
        }
2263
    }
2264

    
2265
    private static class ToolBarComparator implements Comparator<SortableTool> {
2266

    
2267
        private static ExtensionComparator extComp = new ExtensionComparator();
2268

    
2269
        public int compare(SortableTool e1, SortableTool e2) {
2270

    
2271
            // if the toolbars have the same name, they are considered to be
2272
            // the same toolbar, so we don't need to do further comparing
2273
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2274
                return 0;
2275
            }
2276

    
2277
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2278
                if (e1.extension instanceof SkinExtensionType) {
2279
                    return 1;
2280
                } else
2281
                    if (e2.extension instanceof SkinExtensionType) {
2282
                        return -1;
2283
                    } else {
2284
                        return extComp.compare(e1.extension, e2.extension);
2285
                    }
2286
            }
2287

    
2288
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2289
                return Integer.MIN_VALUE;
2290
            }
2291

    
2292
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2293
                return Integer.MAX_VALUE;
2294
            }
2295
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2296
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2297
            }
2298

    
2299
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2300
                && e1.toolbar.getSelectableTool().equals(
2301
                    e2.toolbar.getSelectableTool())) {
2302
                return 0;
2303
            }
2304
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2305
        }
2306
    }
2307

    
2308
    /**
2309
     * <p>
2310
     * This class is used to compare tools (selectabletool and actiontool),
2311
     * using the "position" attribute.
2312
     * </p>
2313
     * <p>
2314
     * The ordering criteria are:
2315
     * </p>
2316
     * <ul>
2317
     * <li>If the tools are placed in different toolbars, they use the toolbars'
2318
     * order. (using the ToolBarComparator).</li>
2319
     * <li></li>
2320
     * <li>If any of the tools has not 'position' attribute, the tool which
2321
     * <strong>has</strong> the attribute will be placed first.</li>
2322
     * <li>If both tools have the same position (or they don't have a 'position'
2323
     * attribute), the priority of the extensions where the tool is defined.</li>
2324
     * </ul>
2325
     * 
2326
     * @author cesar
2327
     * @version $Revision: 37822 $
2328
     */
2329
    private static class ToolComparator implements Comparator<SortableTool> {
2330

    
2331
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2332

    
2333
        public int compare(SortableTool e1, SortableTool e2) {
2334
            // compare the toolbars which contain the tools
2335
            int result = toolBarComp.compare(e1, e2);
2336
            if (result != 0) { // if the toolbars are different, use their order
2337
                return result;
2338
            }
2339
            // otherwise, compare the tools
2340
            int e1Position = -1, e2Position = -1;
2341

    
2342
            if (e1.actiontool != null) {
2343
                if (e1.actiontool.hasPosition()) {
2344
                    e1Position = e1.actiontool.getPosition();
2345
                }
2346
            } else
2347
                if (e1.selectabletool != null) {
2348
                    if (e1.selectabletool.hasPosition()) {
2349
                        e1Position = e1.selectabletool.getPosition();
2350
                    }
2351
                }
2352

    
2353
            if (e2.actiontool != null) {
2354
                if (e2.actiontool.hasPosition()) {
2355
                    e2Position = e2.actiontool.getPosition();
2356
                }
2357
            } else
2358
                if (e2.selectabletool != null) {
2359
                    if (e2.selectabletool.hasPosition()) {
2360
                        e2Position = e2.selectabletool.getPosition();
2361
                    }
2362
                }
2363

    
2364
            if ((e1Position == -1) && (e2Position != -1)) {
2365
                return 1;
2366
            }
2367
            if ((e1Position != -1) && (e2Position == -1)) {
2368
                return -1;
2369
            }
2370
            if ((e1Position != -1) && (e2Position != -1)) {
2371
                result = e1Position - e2Position;
2372
                // we don't return 0 unless both objects are the same, otherwise
2373
                // the objects get overwritten in the treemap
2374
                if (result != 0) {
2375
                    return result;
2376
                }
2377
            }
2378
            return e1.toString().compareTo(e2.toString());
2379
        }
2380
    }
2381

    
2382
    /**
2383
     * validates the user before starting gvsig
2384
     * 
2385
     */
2386
    private static void validate() {
2387

    
2388
        IAuthentication session = null;
2389
        try {
2390
            session =
2391
                (IAuthentication) Class.forName(
2392
                    "com.iver.andami.authentication.Session").newInstance();
2393

    
2394
        } catch (ClassNotFoundException e) {
2395
            return;
2396
        } catch (InstantiationException e) {
2397
            return;
2398
        } catch (IllegalAccessException e) {
2399
            return;
2400
        }
2401

    
2402
        session.setPluginDirectory(andamiConfig.getPluginsDirectory());
2403
        if (session.validationRequired()) {
2404
            if (session.Login()) {
2405
                logger.info("You are logged in");
2406
            } else {
2407
                JOptionPane.showMessageDialog((Component) PluginServices
2408
                    .getMainFrame(), "You are not logged in");
2409
            }
2410
            PluginServices.setAuthentication(session);
2411
        }
2412
    }
2413

    
2414
    public static String getDefaultLookAndFeel() {
2415
        String osName = (String) System.getProperty("os.name");
2416

    
2417
        if ((osName.length() > 4)
2418
            && osName.substring(0, 5).toLowerCase().equals("linux")) {
2419
            return nonWinDefaultLookAndFeel;
2420
        }
2421
        if (osName.toLowerCase().startsWith("mac os x")) {
2422
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
2423
        }
2424

    
2425
        return UIManager.getSystemLookAndFeelClassName();
2426
    }
2427

    
2428
    /**
2429
     * Gets the ISO 839 two-characters-long language code matching the
2430
     * provided language code (which may be an ISO 839-2/T
2431
     * three-characters-long code or an ISO 839-1 two-characters-long
2432
     * code).
2433
     * 
2434
     * If the provided parameter is already two characters long, it
2435
     * returns the parameter without any modification.
2436
     * 
2437
     * @param langCode
2438
     *            A language code representing either
2439
     *            an ISO 839-2/T language code or an ISO 839-1 code.
2440
     * @return A two-characters-long code specifying
2441
     *         an ISO 839 language code.
2442
     */
2443
    private static String normalizeLanguageCode(String langCode) {
2444
        final String fileName = "iso_639.tab";
2445
        if (langCode.length() == 2) {
2446
            return langCode;
2447
        } else
2448
            if (langCode.length() == 3) {
2449
                if (langCode.equals("va") || langCode.equals("val")) { // special
2450
                    // case
2451
                    // for
2452
                    // Valencian
2453
                    return "ca";
2454
                }
2455
                URL isoCodes =
2456
                    Launcher.class.getClassLoader().getResource(fileName);
2457
                if (isoCodes != null) {
2458
                    try {
2459
                        BufferedReader reader =
2460
                            new BufferedReader(new InputStreamReader(isoCodes
2461
                                .openStream(), "ISO-8859-1"));
2462
                        String line;
2463

    
2464
                        while ((line = reader.readLine()) != null) {
2465
                            String[] language = line.split("\t");
2466
                            if (language[0].equals(langCode)) {
2467
                                // the three
2468
                                // characters code
2469
                                return language[2]; // third column i the two
2470
                                // characters code
2471
                            }
2472
                        }
2473
                    } catch (IOException ex) {
2474
                        logger.error(Messages
2475
                            .getString("Error_reading_isocodes_file"), ex);
2476
                        return "es";
2477
                    }
2478
                } else {
2479
                    logger.error(Messages
2480
                        .getString("Error_reading_isocodes_file"));
2481
                    return "es";
2482
                }
2483
            }
2484
        return "es";
2485
    }
2486

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

    
2539
    }
2540

    
2541
    /**
2542
     * Gets Home Directory location of the application into users home folder.
2543
     * 
2544
     * May be set from outside the aplication by means of
2545
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name
2546
     * of the application
2547
     * 
2548
     * @return
2549
     */
2550
    public static String getAppHomeDir() {
2551
        return appHomeDir;
2552
    }
2553

    
2554
    /**
2555
     * Sets Home Directory location of the application.
2556
     * May be set from outside the aplication by means of
2557
     * -DgvSIG.home=C:/data/gvSIG, where gvSIG its the name
2558
     * of the application
2559
     * 
2560
     * @param appHomeDir
2561
     */
2562
    public static void setAppHomeDir(String appHomeDir) {
2563
        Launcher.appHomeDir = appHomeDir;
2564
    }
2565

    
2566
    /**
2567
     * Initialize the extesion that have to take the control
2568
     * of the state of action controls of the UI of all extensions. <br>
2569
     * <br>
2570
     * For use this option you have to add an argument
2571
     * to the command line like this: <br>
2572
     * <br>
2573
     * -exclusiveUI={pathToExtensionClass} <br>
2574
     * 
2575
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
2576
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
2577
     */
2578
    private static void initializeExclusiveUIExtension() {
2579
        String name = PluginServices.getArgumentByName("exclusiveUI");
2580
        if (name == null) {
2581
            return;
2582
        }
2583

    
2584
        Iterator<Class<? extends IExtension>> iter =
2585
            classesExtensions.keySet().iterator();
2586
        int charIndex;
2587
        Class<? extends IExtension> key;
2588
        while (iter.hasNext()) {
2589
            key = iter.next();
2590
            charIndex = key.getName().indexOf(name);
2591
            // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex);
2592
            if (charIndex == 0) {
2593
                IExtension ext = classesExtensions.get(key);
2594
                if (ext instanceof ExtensionDecorator) {
2595
                    ext = ((ExtensionDecorator) ext).getExtension();
2596
                }
2597
                if (ext instanceof ExclusiveUIExtension) {
2598
                    PluginServices
2599
                        .setExclusiveUIExtension((ExclusiveUIExtension) ext);
2600
                }
2601
                break;
2602
            }
2603
        }
2604

    
2605
        logger
2606
            .error(Messages
2607
                .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
2608
                + " '" + name + "'");
2609
    }
2610

    
2611
    // public static void initIconThemes() {
2612
    // // load the iconTheme
2613
    // IconThemeManager iconManager = new IconThemeManager();
2614
    // PluginServices.setIconThemeManager(iconManager);
2615
    // IconThemeInfo selectedTheme = iconManager.readConfig();
2616
    // if (selectedTheme!=null) {
2617
    // iconManager.setDefault(selectedTheme);
2618
    // logger.info("Setting the icon theme: "+selectedTheme.toVerboseString());
2619
    // }
2620
    // else {
2621
    // // set the default dir and try to load the default theme
2622
    // try {
2623
    // iconManager.setThemesDir(new File("iconThemes"));
2624
    // IconThemeInfo[] list = iconManager.list();
2625
    //
2626
    // for (int i=0; i<list.length; i++) {
2627
    // if (list[i].getResourceName().equals("iconThemes/icons")) {
2628
    // iconManager.setDefault(list[i]);
2629
    // logger.info("Setting the default icon theme: "+list[i].toVerboseString());
2630
    // return;
2631
    // }
2632
    // }
2633
    // } catch (FileNotFoundException e) {
2634
    // logger.info("IconTheme basedir does not exist");
2635
    // }
2636
    // // create an empty theme
2637
    // IconThemeInfo info = new IconThemeInfo();
2638
    // info.setName("No theme loaded");
2639
    // info.setResource(null); // null resource means that no real theme is
2640
    // loaded
2641
    // info.setDescription("No theme loaded");
2642
    // info.setVersion("0");
2643
    // iconManager.setDefault(new IconTheme(info));
2644
    // logger.info("Setting an empty icon theme");
2645
    //
2646
    // }
2647
    // }
2648

    
2649
    public static void initIconThemes() {
2650
        IconThemeManager iconManager = IconThemeManager.getIconThemeManager();
2651
        IIconTheme icontheme = iconManager.getIconThemeFromConfig();
2652
        if (icontheme != null) {
2653
            iconManager.setCurrent(icontheme);
2654
        }
2655
    }
2656

    
2657
    /**
2658
     * Manages Andami termination process
2659
     * 
2660
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
2661
     */
2662
    public class TerminationProcess {
2663

    
2664
        private boolean proceed = false;
2665
        private UnsavedDataPanel panel = null;
2666

    
2667
        public void run() {
2668
            try{
2669
                int exit = manageUnsavedData();
2670
                if ((exit == JOptionPane.NO_OPTION)
2671
                    || (exit == JOptionPane.CLOSED_OPTION)) {
2672
                    // the user doesn't want to exit
2673
                    return;
2674
                }
2675
                closeAndami();
2676
            }catch(Exception e){
2677
                //It is not possible to close the application.
2678
                //this exception has been registered before
2679
            }            
2680
        }
2681

    
2682
        /**
2683
         * Finishes the application without asking user if want or not to save
2684
         * unsaved data.
2685
         */
2686
        public void closeAndami() {
2687
            try {
2688
                saveAndamiConfig();
2689
            } catch(Exception ex) {
2690
                logger.error("There was an error exiting application, can't save andami-config.xml", ex);
2691
            }
2692

    
2693
            
2694
            try {
2695
                // Persistencia de los plugins
2696
                savePluginPersistence();
2697
                savePluginsProperties();
2698
            } catch(Exception ex) {
2699
                logger.error("There was an error exiting application, can't save plugins properties", ex);
2700
            }
2701

    
2702
            // Finalize all the extensions
2703
            finalizeExtensions();
2704

    
2705
            try {
2706
                // Clean any temp data created
2707
                Utilities.cleanUpTempFiles();
2708
            } catch(Exception ex) {
2709
                logger.error("There was an error exiting application, can't remove temporary files", ex);
2710
            }
2711

    
2712
            logger.info("Quiting application.");
2713
            
2714
            // Para la depuraci?n de memory leaks
2715
            System.gc();
2716

    
2717
            System.exit(0);
2718
        }
2719

    
2720
        /**
2721
         * 
2722
         */
2723
        public void saveAndamiConfig() {
2724
            // Configuraci?n de Andami
2725
            try {
2726
                andamiConfigToXML(andamiConfigPath);
2727
            } catch (MarshalException e) {
2728
                logger
2729
                    .error(
2730
                        Messages
2731
                            .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2732
                        e);
2733
            } catch (ValidationException e) {
2734
                logger
2735
                    .error(
2736
                        Messages
2737
                            .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2738
                        e);
2739
            } catch (IOException e) {
2740
                logger
2741
                    .error(
2742
                        Messages
2743
                            .getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"),
2744
                        e);
2745
            }
2746
        }
2747

    
2748
        private void savePluginsProperties() {
2749
            PluginsManager manager = PluginsLocator.getManager();
2750
            List<PluginServices> plugins = manager.getPlugins();
2751
            for (PluginServices plugin : plugins) {
2752
                if (plugin != null) {
2753
                    plugin.savePluginProperties();
2754
                }
2755
            }
2756
        }
2757

    
2758
        /**
2759
         * Exectutes the terminate method for all the extensions, in the reverse
2760
         * order they were initialized
2761
         * 
2762
         */
2763
        private void finalizeExtensions() {
2764
            for (int i = extensions.size() - 1; i >= 0; i--) {
2765
                org.gvsig.andami.plugins.IExtension extensionInstance =
2766
                    (org.gvsig.andami.plugins.IExtension) extensions.get(i);
2767
                String extensionName = "(unknow)";
2768
                try {
2769
                    extensionName = extensionInstance.getClass().getName();
2770
                    extensionInstance.terminate();
2771
                } catch(Exception ex) {
2772
                    logger.error(
2773
                        MessageFormat.format("There was an error extension ending {0}", extensionName),
2774
                        ex);
2775
                }
2776
            }
2777
        }
2778

    
2779
        private IUnsavedData[] getUnsavedData() throws Exception {
2780
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
2781
            IExtension exclusiveExtension =
2782
                PluginServices.getExclusiveUIExtension();
2783

    
2784
            for (int i = extensions.size() - 1; i >= 0; i--) {
2785
                org.gvsig.andami.plugins.IExtension extensionInstance =
2786
                    (org.gvsig.andami.plugins.IExtension) extensions.get(i);
2787
                IExtensionStatus status = null;
2788
                if (exclusiveExtension != null) {
2789
                    status = exclusiveExtension.getStatus(extensionInstance);
2790
                } else {
2791
                    status = extensionInstance.getStatus();
2792
                }
2793
                if (status != null) {
2794
                    try{
2795
                        if (status.hasUnsavedData()) {
2796
                            IUnsavedData[] array = status.getUnsavedData();
2797
                            for (int element = 0; element < array.length; element++) {
2798
                                unsavedDataList.add(array[element]);
2799
                            }
2800
                        }
2801
                    } catch (Exception e){
2802
                        logger.info("Error calling the hasUnsavedData method", new Exception());
2803
                        int option =
2804
                            JOptionPane.showConfirmDialog(frame, 
2805
                                Messages.getString("error_getting_unsaved_data"),                               
2806
                                Messages.getString("MDIFrame.salir"),
2807
                                JOptionPane.YES_NO_OPTION);
2808
                        if (option == JOptionPane.NO_OPTION){
2809
                            throw e;
2810
                        }                       
2811
                    }
2812
                }
2813
            }
2814
            return unsavedDataList.toArray(new IUnsavedData[unsavedDataList
2815
                .size()]);
2816
        }
2817

    
2818
        public UnsavedDataPanel getUnsavedDataPanel() {
2819
            if (panel == null) {
2820
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
2821
            }
2822
            return panel;
2823
        }
2824

    
2825
        /**
2826
         * Checks if the extensions have some unsaved data, and shows a dialog
2827
         * to allow saving it. This dialog also allows to don't exit Andami.
2828
         * 
2829
         * @return true if the user confirmed he wishes to exit, false otherwise
2830
         * @throws Exception 
2831
         */
2832
        public int manageUnsavedData() throws Exception {
2833
            IUnsavedData[] unsavedData = getUnsavedData();
2834

    
2835
            // there was no unsaved data
2836
            if (unsavedData.length == 0) {
2837
                int option =
2838
                    JOptionPane
2839
                        .showConfirmDialog(frame, Messages
2840
                            .getString("MDIFrame.quiere_salir"), Messages
2841
                            .getString("MDIFrame.salir"),
2842
                            JOptionPane.YES_NO_OPTION);
2843
                return option;
2844
            }
2845

    
2846
            UnsavedDataPanel panel = getUnsavedDataPanel();
2847
            panel.setUnsavedDataArray(unsavedData);
2848

    
2849
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
2850

    
2851
                public void cancel(UnsavedDataPanel panel) {
2852
                    proceed(false);
2853
                    PluginServices.getMDIManager().closeWindow(panel);
2854

    
2855
                }
2856

    
2857
                public void discard(UnsavedDataPanel panel) {
2858
                    proceed(true);
2859
                    PluginServices.getMDIManager().closeWindow(panel);
2860

    
2861
                }
2862

    
2863
                public void accept(UnsavedDataPanel panel) {
2864
                    IUnsavedData[] unsavedDataArray =
2865
                        panel.getSelectedsUnsavedData();
2866
                    boolean saved;
2867
                    for (int i = 0; i < unsavedDataArray.length; i++) {
2868
                        try {
2869
                            saved = unsavedDataArray[i].saveData();
2870
                        } catch (Exception ex) {
2871
                            PluginServices
2872
                                .getLogger()
2873
                                .error(
2874
                                    "Error saving"
2875
                                        + unsavedDataArray[i].getResourceName(),
2876
                                    ex);
2877
                            saved = false;
2878
                        }
2879
                        if (!saved) {
2880
                            JOptionPane
2881
                                .showMessageDialog(
2882
                                    panel,
2883
                                    PluginServices
2884
                                        .getText(this,
2885
                                            "The_following_resource_could_not_be_saved_")
2886
                                        + "\n"
2887
                                        + unsavedDataArray[i].getResourceName()
2888
                                        + " -- "
2889
                                        + unsavedDataArray[i].getDescription(),
2890
                                    PluginServices.getText(this,
2891
                                        "Resource_was_not_saved"),
2892
                                    JOptionPane.ERROR_MESSAGE);
2893

    
2894
                            try {
2895
                                unsavedDataArray = getUnsavedData();
2896
                            } catch (Exception e) {
2897
                                //This exception has been registered before
2898
                            }
2899
                            panel.setUnsavedDataArray(unsavedDataArray);
2900
                            return;
2901
                        }
2902
                    }
2903
                    proceed(true);
2904
                    PluginServices.getMDIManager().closeWindow(panel);
2905
                }
2906
            });
2907

    
2908
            PluginServices.getMDIManager().addWindow(panel);
2909
            if (proceed) {
2910
                return JOptionPane.YES_OPTION;
2911
            } else {
2912
                return JOptionPane.NO_OPTION;
2913
            }
2914
        }
2915

    
2916
        private void proceed(boolean proceed) {
2917
            this.proceed = proceed;
2918
        }
2919

    
2920
    }
2921

    
2922
    public static TerminationProcess getTerminationProcess() {
2923
        return (new Launcher()).new TerminationProcess();
2924
    }
2925

    
2926
    /**
2927
     * Launch the gvSIG package installer.
2928
     * 
2929
     * @throws Exception
2930
     *             if there is any error
2931
     */
2932
    private void doInstall(String[] args) throws Exception {
2933
        String installURL = null;
2934
        String installURLFile = null;
2935
        String gvSIGVersion = null;
2936
        String[] myArgs = new String[2];
2937
        
2938
                Options options = new Options();
2939
                options.addOption("i", "install", false,
2940
                                "install");
2941
                options.addOption("u", "installURL", true,
2942
                                "installURL");
2943
                options.addOption("f", "installURLFile", true,
2944
                                "installURLFile");
2945
                options.addOption("v", "installVersion", true, "installVersion");
2946
                options.addOption("A", "applicationName", true, "applicationName");
2947
                options.addOption("P", "pluginsFolder", true, "pluginsFolder");
2948

    
2949
                CommandLineParser parser = new PosixParser();
2950
                CommandLine line = null;
2951
                try {
2952
                        line = parser.parse(options, args);
2953
                        boolean hasAllMandatoryOptions = true;
2954
                        if (!line.hasOption("install")) {
2955
                                hasAllMandatoryOptions = false;
2956
                        }
2957
                        if (line.hasOption("installURL")) {
2958
                                installURL = line.getOptionValue("installURL");
2959
                        }
2960
                        if (line.hasOption("installURLFile")) {
2961
                                installURLFile = line.getOptionValue("installURLFile");
2962
                        }
2963
                        if (line.hasOption("installVersion")) {
2964
                                gvSIGVersion = line.getOptionValue("installVersion");
2965
                        }
2966
                        if (line.hasOption("applicationName")) {
2967
                                myArgs[0] = line.getOptionValue("applicationName");
2968
                        } else {
2969
                                hasAllMandatoryOptions = false;
2970
                        }
2971
                        if (line.hasOption("pluginsFolder")) {
2972
                                myArgs[1] = line.getOptionValue("pluginsFolder");
2973
                        } else {
2974
                                hasAllMandatoryOptions = false;
2975
                        }
2976
                        if (!hasAllMandatoryOptions) {
2977
                    System.err.println(Messages.get("usage")
2978
                                + ": Launcher --applicationName=appName --pluginsFolder=plugins-directory "
2979
                                + "[--installURLFile=File] "
2980
                                + "--install [--installURL=URL] [language=locale]");
2981
                    return;
2982
                        }
2983
                } catch (ParseException exp) {
2984
                        System.out.println("Unexpected exception:" + exp.getMessage());
2985
                }
2986

    
2987
        initializeApp(myArgs);
2988
        initializeLibraries();
2989
        AndamiConfig config = getAndamiConfig();
2990
        config.setLocaleLanguage(locale.getLanguage());
2991
        config.setLocaleCountry(locale.getCountry());
2992
        config.setLocaleVariant(locale.getVariant());
2993

    
2994
        // Configure default index download URL
2995
        if (installURL != null) {
2996
                SwingInstallerLocator.getSwingInstallerManager()
2997
                    .setDefaultDownloadURL(installURL);
2998
        }
2999

    
3000
        if (installURLFile != null) {
3001
                //TODO: Convertir a File y pasarlo
3002
            SwingInstallerLocator.getSwingInstallerManager()
3003
                .setDefaultDownloadURL(new File(installURLFile));
3004
        }
3005

    
3006
                // Launch installer
3007
                PluginsManager manager = PluginsLocator.getManager();
3008

    
3009
                // TODO: Anyado el directorio de plugins
3010
                File defaultAddonsRepository = new File(System.getProperty("user.dir"),
3011
                                andamiConfig.getPluginsDirectory());
3012
                InstallerManager installerManager = InstallerLocator
3013
                                .getInstallerManager();
3014
                installerManager.addAddonRepository(defaultAddonsRepository);
3015

    
3016
                // TODO: hacer algo asi para tener un repositorio por defecto?
3017
                installerManager.setDefaultAddonRepository(defaultAddonsRepository);
3018
                
3019
                AbstractInstallPackageWizard installPackageWizard = SwingInstallerLocator
3020
                                .getSwingInstallerManager().createInstallPackageWizard(
3021
                                                manager.getApplicationFolder(),
3022
                                                manager.getInstallFolder());
3023
                installPackageWizard
3024
                                .setWizardActionListener(new InstallerWizardActionListener() {
3025

    
3026
                public void finish(InstallerWizardPanel installerWizard) {
3027
                    System.exit(0);
3028
                }
3029

    
3030
                public void cancel(InstallerWizardPanel installerWizard) {
3031
                    System.exit(0);
3032
                }
3033
            });
3034
        
3035
        // the wizard will show the Typical or Advanced mode option.
3036
        installPackageWizard.setAskTypicalOrCustom(true);
3037
        // default packages will be selected.
3038
        installPackageWizard.setSelectDefaultPackages(true);
3039
        
3040
        // set the gvSIG version to the install manager, to compose the download
3041
        // URL:
3042
        InstallerLocator.getInstallerManager().setVersion(gvSIGVersion);
3043
        
3044
        // 1. Create the frame.
3045
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
3046

    
3047
        // 2. What happens when the frame closes?
3048
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
3049
        Runtime.getRuntime().addShutdownHook(new Thread() {
3050

    
3051
            @Override
3052
            public void run() {
3053
                getTerminationProcess().saveAndamiConfig();
3054
            }
3055
        });
3056

    
3057
        // 3. Add the installer panel to the frame
3058
        frame.getContentPane().add(installPackageWizard, BorderLayout.CENTER);
3059

    
3060
        // 4. Size the frame and center on the screen
3061
        frame.pack();
3062
        frame.setLocationRelativeTo(null);
3063

    
3064
        // 5. Show it.
3065
        frame.setVisible(true);
3066
    }
3067
    
3068
        public static String getInformation() {
3069
                PluginsManager pluginmgr = PluginsLocator.getManager();
3070
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
3071

    
3072
                StringWriter writer = new StringWriter();
3073

    
3074
                Properties props = System.getProperties();
3075

    
3076
                // OS information
3077
                String osName = props.getProperty("os.name");
3078
                writer.write("OS\n");
3079
                writer.write("    name   : " + osName + "\n");
3080
                writer.write("    arch   : " + props.get("os.arch") + "\n");
3081
                writer.write("    version: " + props.get("os.version") + "\n");
3082
                if (osName.startsWith("Linux")) {
3083
                        try {
3084
                                String[] command = {"lsb_release", "-a"};
3085
                                Process p = Runtime.getRuntime().exec(command);
3086
                                InputStream is = p.getInputStream();
3087
                                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
3088
                                String line;
3089
                                while ( (line = reader.readLine()) != null) {
3090
                                        writer.write("    "+line+"\n");
3091
                                }
3092
                        } catch (Exception ex) {
3093
                                writer.write("Can't get detailled os information (lsb_release -a).");
3094
                        }
3095
                }
3096

    
3097
                // JRE information
3098
                writer.write("JRE\n");
3099
                writer.write("    vendor : " + props.get("java.vendor") + "\n");
3100
                writer.write("    version: " +props.get("java.version")+ "\n");
3101
                writer.write("    home   : " + props.get("java.home") + "\n");
3102

    
3103
                writer.write("HTTP Proxy\n");
3104
                writer.write("    http.proxyHost     : " + props.get("http.proxyHost") + "\n");
3105
                writer.write("    http.proxyPort     : " + props.get("http.proxyPort") + "\n");
3106
                writer.write("    http.proxyUserName : " + props.get("http.proxyUserName") + "\n");
3107
                writer.write("    http.proxyPassword : " + props.get("http.proxyPassword") + "\n");
3108
                
3109
                String skinName = "(unknow)";
3110
                try {
3111
                        skinName = MDIManagerFactory.getSkinExtension().getClassName();
3112
                } catch (Throwable e) {
3113
                        // Ignore
3114
                }
3115
                writer.write("Application\n");
3116
                writer.write("    locale language         : " + Launcher.getAndamiConfig().getLocaleLanguage()+ "\n");
3117
                writer.write("    application forlder     : " + pluginmgr.getApplicationFolder()+ "\n");
3118
                writer.write("    install forlder         : " + pluginmgr.getInstallFolder()+ "\n");
3119
                writer.write("    application home forlder: " + pluginmgr.getApplicationHomeFolder()+ "\n");
3120
                writer.write("    plugins forlder         : " + pluginmgr.getPluginsFolder()+ "\n");
3121
        writer.write("    theme                   : "
3122
            + Launcher.theme.getSource() + "\n");
3123
//                writer.write("    Skin                    : " + skinName + "\n");
3124
                
3125
                
3126
                try {
3127
                        PackageInfo[] pkgs = installmgr.getInstalledPackages(pluginmgr.getPluginsFolder());
3128
                        writer.write("Installed packages\n");
3129
                        for( int i=0; i<pkgs.length; i++) {
3130
                                writer.write("    ");
3131
                                writer.write(pkgs[i].toStringCompact());
3132
                                writer.write("\n");
3133
                        }
3134
                } catch(Throwable e) {
3135
                        writer.write("Can't get installed package information.");
3136
                }
3137
                return writer.toString();
3138
        }
3139

    
3140
        private void logger_info(String msg) {
3141
                String info[] = msg.split("\n");
3142
                for (int i=0;i< info.length;i++) {
3143
                        logger.info(info[i]);
3144
                }
3145
        }
3146

    
3147

    
3148
}