Statistics
| Revision:

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

History | View | Annotate | Download (111 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: 37498 $
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
        // 19. Se ejecuta el postInitialize
495
        splashWindow.process(190, PluginServices.getText(Launcher.class,
496
            "SplashWindow.post_initializing_extensions"));
497
        SwingUtilities.invokeAndWait(new Runnable() {
498

    
499
            public void run() {
500
                postInitializeExtensions();
501

    
502
            }
503
        });
504

    
505
        // Definimos un KeyEventDispatcher global para que las extensiones
506
        // puedan registrar sus "teclas r?pidas".
507
        GlobalKeyEventDispatcher keyDispatcher =
508
            GlobalKeyEventDispatcher.getInstance();
509
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
510
            .addKeyEventDispatcher(keyDispatcher);
511

    
512
        SwingUtilities.invokeAndWait(new Runnable() {
513

    
514
            public void run() {
515
                frame.enableControls();
516
            }
517
        });
518
        splashWindow.close();
519
        if (launcherrors != null) {
520
            NotificationManager.addError(launcherrors);
521
        }
522
        
523
        org.apache.log4j.Logger.getRootLogger().addAppender(new NotificationAppender());
524

    
525
        
526
    }
527

    
528
    /**
529
     * 
530
     */
531
    private void initializeLibraries() {
532
        List<ClassLoader> classLoaders =
533
            new ArrayList<ClassLoader>(pluginsOrdered.size() + 1);
534
        classLoaders.add(getClass().getClassLoader());
535
        Iterator<String> iter = pluginsOrdered.iterator();
536

    
537
        logger.debug("Initializing plugins libraries: ");
538
        while (iter.hasNext()) {
539
            String pName = (String) iter.next();
540
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
541
            classLoaders.add(ps.getClassLoader());
542
        }
543

    
544
        // Create the libraries initializer and
545
        // initialize the plugin libraries
546
        new DefaultLibrariesInitializer(
547
            classLoaders.toArray(new ClassLoader[classLoaders.size()]))
548
            .fullInitialize(true);
549

    
550
        // Remove them all, we don't need them anymore
551
        classLoaders.clear();
552
        classLoaders = null;
553
    }
554

    
555
    /**
556
     * @param args
557
     * @throws IOException
558
     * @throws ConfigurationException
559
     */
560
    private void initializeApp(String[] args) throws IOException,
561
        ConfigurationException {
562
        if (!validJVM()) {
563
            System.exit(-1);
564
        }
565

    
566
        // Clean temporal files
567
        Utilities.cleanUpTempFiles();
568

    
569
        appName = args[0];
570

    
571
        getOrCreateConfigFolder();
572

    
573
        configureLogging(appName);
574

    
575
        loadAndamiConfig(args[1]);
576

    
577
        // Hacemos visibles los argumentos como una propiedad est?tica
578
        // de plugin services para quien lo quiera usar (por ejemplo, para
579
        // cargar un proyecto por l?nea de comandos)
580
        PluginServices.setArguments(args);
581

    
582
        configureLocales(args);
583

    
584
        logger.info("Load and initialize andami and plugins libraries");
585
        // LibrariesInitializer libsInitializer =
586
        // new DefaultLibrariesInitializer();
587
        // libsInitializer.initialize(true);
588
        // libsInitializer.postInitialize(true);
589

    
590
        logger.info("Configure LookAndFeel");
591
        configureLookAndFeel();
592
    }
593

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

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

    
628
    /**
629
     * 
630
     */
631
    private void getOrCreateConfigFolder() {
632
        // Create application configuration folder
633
        appHomeDir = System.getProperty(appName + ".home");
634
        if (appHomeDir == null) {
635
            appHomeDir = System.getProperty("user.home");
636
        }
637

    
638
        appHomeDir += File.separator + appName;
639
        File parent = new File(appHomeDir);
640
        parent.mkdirs();
641
    }
642

    
643
    /**
644
     * @param args
645
     * @throws IOException
646
     */
647
    private void configureLogging(String appName) throws IOException {
648
        // Configurar el log4j
649
        Launcher.class.getClassLoader().getResource(".");
650
        PropertyConfigurator.configure("log4j.properties");
651

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

    
661
    
662
    private class NotificationAppender extends AppenderSkeleton{
663

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

    
677
        @Override
678
        public void close() {
679
            // TODO Auto-generated method stub
680
            
681
        }
682

    
683
        @Override
684
        public boolean requiresLayout() {
685
            // TODO Auto-generated method stub
686
            return false;
687
        }
688
        
689
    }
690

    
691
    /**
692
     * Return the directory applicaction is installed.
693
     */
694
    public static String getApplicationDirectory() {
695
        return new File("").getAbsolutePath();
696
    }
697

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

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

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

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

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

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

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

    
813
    /**
814
     * Establece los datos que ten?amos guardados respecto de la configuraci?n
815
     * del proxy.
816
     */
817
    private void configureProxy() {
818
        String host = prefs.get("firewall.http.host", "");
819
        String port = prefs.get("firewall.http.port", "");
820

    
821
        System.getProperties().put("http.proxyHost", host);
822
        System.getProperties().put("http.proxyPort", port);
823

    
824
        // Ponemos el usuario y clave del proxy, si existe
825
        String proxyUser = prefs.get("firewall.http.user", null);
826
        String proxyPassword = prefs.get("firewall.http.password", null);
827
        if (proxyUser != null) {
828
            System.getProperties().put("http.proxyUserName", proxyUser);
829
            System.getProperties().put("http.proxyPassword", proxyPassword);
830

    
831
            Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword));
832
        } else {
833
            Authenticator.setDefault(new ProxyAuth("", ""));
834
        }
835
    }
836

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

    
863
        // restore frame status (Maximized, minimized, etc);
864
        int state = java.awt.Frame.MAXIMIZED_BOTH;
865
        if (xml.contains("MDIFrameState")) {
866
            state = xml.getIntProperty("MDIFrameState");
867
        }
868
        frame.setExtendedState(state);
869
    }
870

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

    
888
    private boolean validJVM() {
889
        char thirdCharacter = System.getProperty("java.version").charAt(2);
890
        if (thirdCharacter < '4') {
891
            return false;
892
        } else {
893
            return true;
894
        }
895
    }
896

    
897
    private void loadPluginsPersistence() throws ConfigurationException {
898
        XMLEntity entity = persistenceFromXML();
899

    
900
        for (int i = 0; i < entity.getChildrenCount(); i++) {
901
            XMLEntity plugin = entity.getChild(i);
902
            String pName =
903
                plugin.getStringProperty("com.iver.andami.pluginName");
904

    
905
            if (pName.compareToIgnoreCase("com.iver.cit.gvsig") == 0) {
906
                pName = "org.gvsig.app";
907
            }
908
            if (pluginsServices.get(pName) != null) {
909
                ((PluginServices) pluginsServices.get(pName))
910
                    .setPersistentXML(plugin);
911
            } else {
912
                if (pName.startsWith("Andami.Launcher")) {
913
                    restoreMDIStatus(plugin);
914
                }
915
            }
916
        }
917
    }
918

    
919
    /**
920
     * Salva la persistencia de los plugins.
921
     * 
922
     * @author LWS
923
     */
924
    private void savePluginPersistence() {
925
        Iterator<String> i = pluginsConfig.keySet().iterator();
926

    
927
        XMLEntity entity = new XMLEntity();
928

    
929
        while (i.hasNext()) {
930
            String pName = i.next();
931
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
932
            XMLEntity ent = ps.getPersistentXML();
933

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

    
955
    private void installPluginsLabels() {
956
        Iterator<String> i = pluginsConfig.keySet().iterator();
957

    
958
        while (i.hasNext()) {
959
            String name = i.next();
960
            PluginConfig pc = pluginsConfig.get(name);
961
            PluginServices ps = (PluginServices) pluginsServices.get(name);
962

    
963
            LabelSet[] ls = pc.getLabelSet();
964

    
965
            for (int j = 0; j < ls.length; j++) {
966
                PluginClassLoader loader = ps.getClassLoader();
967

    
968
                try {
969
                    Class clase = loader.loadClass(ls[j].getClassName());
970
                    frame.setStatusBarLabels(clase, ls[j].getLabel());
971
                } catch (ClassNotFoundException e) {
972
                    this.addError(
973
                        Messages.getString("Launcher.labelset_class"), e);
974
                }
975
            }
976
        }
977
    }
978

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

    
993
    private void fixSkin(SkinExtension skinExtension,
994
        PluginClassLoader pluginClassLoader) throws MDIManagerLoadException {
995
        // now insert the skin selected.
996
        MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader);
997
        // MDIManagerFactory.setSkinExtension(se,
998
        // ps.getClassLoader());
999

    
1000
        Class<? extends IExtension> skinClass;
1001

    
1002
        try {
1003
            skinClass =
1004
                (Class<? extends IExtension>) pluginClassLoader
1005
                    .loadClass(skinExtension.getClassName());
1006

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

    
1032
    }
1033

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

    
1049
        SkinExtension skinExtension = null;
1050
        PluginClassLoader pluginClassLoader = null;
1051
        List<SkinExtension> skinExtensions = new ArrayList<SkinExtension>();
1052
        while (i.hasNext()) {
1053
            String name = i.next();
1054
            PluginConfig pc = pluginsConfig.get(name);
1055
            PluginServices ps = pluginsServices.get(name);
1056

    
1057
            if (pc.getExtensions().getSkinExtension() != null) {
1058
                // if (MDIManagerFactory.getSkinExtension() != null) {
1059
                // logger.warn(Messages.getString(
1060
                // "Launcher.Dos_skin_extension"));
1061
                // }
1062

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

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

    
1097
    }
1098

    
1099
    private static void frameIcon(Theme theme) {
1100
        Iterator<String> i = pluginsConfig.keySet().iterator();
1101

    
1102
        while (i.hasNext()) {
1103
            String pName = i.next();
1104
            PluginConfig pc = pluginsConfig.get(pName);
1105
            if (pc.getIcon() != null) {
1106
                if (theme.getIcon() != null) {
1107
                    frame.setIconImage(theme.getIcon().getImage());
1108
                } else {
1109

    
1110
                    ImageIcon icon =
1111
                        PluginServices.getIconTheme()
1112
                            .get(pc.getIcon().getSrc());
1113
                    frame.setIconImage(icon.getImage());
1114

    
1115
                }
1116
                if (theme.getName() != null) {
1117
                    frame.setTitlePrefix(theme.getName());
1118
                } else {
1119
                    frame.setTitlePrefix(pc.getIcon().getText());
1120
                }
1121
                if (theme.getBackgroundImage() != null) {
1122

    
1123
                    PluginServices.getMDIManager().setBackgroundImage(
1124
                        theme.getBackgroundImage(), theme.getTypeDesktop());
1125
                }
1126
            }
1127
        }
1128
    }
1129

    
1130
    private void initializeExtensions() {
1131

    
1132
        List<ClassLoader> classLoaders =
1133
            new ArrayList<ClassLoader>(pluginsOrdered.size());
1134
        classLoaders.add(getClass().getClassLoader());
1135
        Iterator<String> iter = pluginsOrdered.iterator();
1136

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

    
1154
        logger.info("Initializing plugins: ");
1155
        // iter = pluginsOrdered.iterator();
1156
        while (iter.hasNext()) {
1157
            String pName = (String) iter.next();
1158
            logger.info("Initializing plugin " + pName);
1159
            PluginConfig pc = (PluginConfig) pluginsConfig.get(pName);
1160
            PluginServices ps = (PluginServices) pluginsServices.get(pName);
1161

    
1162
            Extension[] exts = pc.getExtensions().getExtension();
1163

    
1164
            TreeSet<Extension> orderedExtensions =
1165
                new TreeSet<Extension>(new ExtensionComparator());
1166

    
1167
            for (int j = 0; j < exts.length; j++) {
1168
                if (!exts[j].getActive()) {
1169
                    continue;
1170
                }
1171

    
1172
                if (orderedExtensions.contains(exts[j])) {
1173
                    logger.warn("Two extensions with the same priority ("
1174
                        + exts[j].getClassName() + ")");
1175
                }
1176

    
1177
                orderedExtensions.add(exts[j]);
1178
            }
1179

    
1180
            Iterator<Extension> e = orderedExtensions.iterator();
1181

    
1182
            logger.info("Initializing extensions of plugin "+pName+": ");
1183
            while (e.hasNext()) {
1184
                Extension extension = e.next();
1185
                org.gvsig.andami.plugins.IExtension extensionInstance;
1186

    
1187
                try {
1188
                    logger.info("Initializing " + extension.getClassName()
1189
                        + "...");
1190
                    Class<? extends IExtension> extensionClass =
1191
                        (Class<? extends IExtension>) ps.getClassLoader()
1192
                            .loadClass(extension.getClassName());
1193
                    extensionInstance = extensionClass.newInstance();
1194

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

    
1214
                    extensionInstance.initialize();
1215
                    extensions.add(extensionInstance);
1216

    
1217
                } catch (NoClassDefFoundError e1) {
1218
                    this.addError("Can't find class extension ("
1219
                        + extension.getClassName() + ")", e1);
1220
                } catch (Throwable e1) {
1221
                    this.addError("Can't initialize extension '"
1222
                        + extension.getClassName() + "'.", e1);
1223
                }
1224
            }
1225
        }
1226
    }
1227

    
1228
    private void postInitializeExtensions() {
1229
        logger.info("PostInitializing extensions: ");
1230

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

    
1245
    private void installPluginsMenus() {
1246
        TreeSet<SortableMenu> orderedMenus =
1247
            new TreeSet<SortableMenu>(new MenuComparator());
1248

    
1249
        Iterator<String> i = pluginsConfig.keySet().iterator();
1250

    
1251
        while (i.hasNext()) {
1252
            String pName = i.next();
1253
                try {
1254
            PluginServices ps = pluginsServices.get(pName);
1255
            PluginConfig pc = pluginsConfig.get(pName);
1256

    
1257
            Extension[] exts = pc.getExtensions().getExtension();
1258

    
1259
            for (int j = 0; j < exts.length; j++) {
1260
                if (!exts[j].getActive()) {
1261
                    continue;
1262
                }
1263

    
1264
                Menu[] menus = exts[j].getMenu();
1265

    
1266
                for (int k = 0; k < menus.length; k++) {
1267
                    SortableMenu sm =
1268
                        new SortableMenu(ps.getClassLoader(), exts[j], menus[k]);
1269

    
1270
                    if (orderedMenus.contains(sm)) {
1271
                        this
1272
                            .addError(Messages
1273
                                .getString("Launcher.Two_menus_with_the_same_position")
1274
                                + " - "
1275
                                + menus[k].getText()
1276
                                + " - "
1277
                                + exts[j].getClassName());
1278
                    }
1279

    
1280
                    orderedMenus.add(sm);
1281
                }
1282
            }
1283

    
1284
            // Se instalan las extensiones de MDI
1285
            SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1286
            for (int j = 0; j < skinExts.length; j++) {
1287

    
1288
                if (skinExts[j] != null) {
1289
                    Menu[] menu = skinExts[j].getMenu();
1290

    
1291
                    for (int k = 0; k < menu.length; k++) {
1292
                        SortableMenu sm =
1293
                            new SortableMenu(ps.getClassLoader(), skinExts[j],
1294
                                menu[k]);
1295

    
1296
                        if (orderedMenus.contains(sm)) {
1297
                            this
1298
                                .addError(Messages
1299
                                    .getString("Launcher.Two_menus_with_the_same_position")
1300
                                    + skinExts[j].getClassName());
1301
                        }
1302

    
1303
                        orderedMenus.add(sm);
1304
                    }
1305
                }
1306
            }
1307
            
1308
            
1309
                } catch (Throwable e) {
1310
                        addError("Error initializing menus of plugin '"+pName+"'", e);
1311
                        }
1312
            
1313
            
1314
        }
1315

    
1316
        // Se itera por los menus ordenados
1317
        Iterator<SortableMenu> e = orderedMenus.iterator();
1318

    
1319
        // Se ordenan los menues
1320
        while (e.hasNext()) {
1321
            try {
1322
                SortableMenu sm = e.next();
1323

    
1324
                frame.addMenu(sm.loader, sm.extension, sm.menu);
1325

    
1326
            } catch (ClassNotFoundException ex) {
1327
                this
1328
                    .addError(
1329
                        Messages
1330
                            .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1331
                        ex);
1332
            } catch (NoClassDefFoundError ex) {
1333
                this
1334
                .addError(
1335
                    Messages
1336
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1337
                    ex);
1338
            } catch (Throwable ex) {
1339
                this
1340
                .addError(
1341
                    Messages
1342
                        .getString("Launcher.No_se_encontro_la_clase_de_la_extension"),
1343
                    ex);
1344
            }
1345
        }
1346
    }
1347

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

    
1356
        Map<Extension, PluginServices> extensionPluginServices =
1357
            new HashMap<Extension, PluginServices>();
1358
        Map<Extension, PluginConfig> extensionPluginConfig =
1359
            new HashMap<Extension, PluginConfig>();
1360
        Set<Extension> orderedExtensions =
1361
            new TreeSet<Extension>(new ExtensionComparator());
1362

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

    
1373
                        Extension[] exts = pc.getExtensions().getExtension();
1374

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

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

    
1400
        TreeSet<SortableTool> orderedTools =
1401
            new TreeSet<SortableTool>(new ToolComparator());
1402
        Iterator<Extension> e = orderedExtensions.iterator();
1403

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

    
1414
                        // get tools from toolbars
1415
                        for (int k = 0; k < toolbars.length; k++) {
1416
                                ActionTool[] tools = toolbars[k].getActionTool();
1417

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

    
1425
                                SelectableTool[] sTools = toolbars[k].getSelectableTool();
1426

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

    
1435
                        // get controls for statusBar
1436
                        PluginServices ps = extensionPluginServices.get(ext);
1437
                        PluginClassLoader loader = ps.getClassLoader();
1438

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

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

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

    
1538
                        SkinExtension[] skinExts = pc.getExtensions().getSkinExtension();
1539
                        for (int j = 0; j < skinExts.length; j++) {
1540

    
1541
                                if (skinExts[j] != null) {
1542
                                        ToolBar[] toolbars = skinExts[j].getToolBar();
1543

    
1544
                                        for (int k = 0; k < toolbars.length; k++) {
1545
                                                ActionTool[] tools = toolbars[k].getActionTool();
1546

    
1547
                                                for (int t = 0; t < tools.length; t++) {
1548
                                                        SortableTool stb =
1549
                                                                new SortableTool(ps.getClassLoader(),
1550
                                                                                skinExts[j], toolbars[k], tools[t]);
1551
                                                        orderedTools.add(stb);
1552
                                                }
1553

    
1554
                                                SelectableTool[] sTools =
1555
                                                        toolbars[k].getSelectableTool();
1556

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

    
1569
                        if (pus != null) {
1570
                                PopupMenu[] menus = pus.getPopupMenu();
1571

    
1572
                                for (int j = 0; j < menus.length; j++) {
1573
                                        frame.addPopupMenu(ps.getClassLoader(), menus[j]);
1574
                                }
1575
                        }
1576
                } catch (Throwable e3) {
1577
                        addError("Error initializing skins of the plugin '"+pName+"'", e3);
1578
                }
1579
        }
1580

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

    
1606
    /**
1607
     * Adds new plugins to the the andami-config file.
1608
     */
1609
    private void updateAndamiConfig() {
1610
        Set<String> olds = new HashSet<String>();
1611

    
1612
        Plugin[] plugins = andamiConfig.getPlugin();
1613

    
1614
        for (int i = 0; i < plugins.length; i++) {
1615
            olds.add(plugins[i].getName());
1616
        }
1617

    
1618
        Iterator<PluginServices> i = pluginsServices.values().iterator();
1619

    
1620
        while (i.hasNext()) {
1621
            PluginServices ps = i.next();
1622

    
1623
            if (!olds.contains(ps.getPluginName())) {
1624
                Plugin p = new Plugin();
1625
                p.setName(ps.getPluginName());
1626
                p.setUpdate(false);
1627

    
1628
                andamiConfig.addPlugin(p);
1629
            }
1630
        }
1631
    }
1632

    
1633
    private void pluginsClassLoaders() {
1634
        Set<String> installed = new HashSet<String>();
1635

    
1636
        // Se itera hasta que est?n todos instalados
1637
        while (installed.size() != pluginsConfig.size()) {
1638
            boolean circle = true;
1639

    
1640
            // Hacemos una pasada por todos los plugins
1641
            Iterator<String> i = pluginsConfig.keySet().iterator();
1642

    
1643
            while (i.hasNext()) {
1644
                String pluginName = i.next();
1645
                PluginConfig config =
1646
                    (PluginConfig) pluginsConfig.get(pluginName);
1647

    
1648
                if (installed.contains(pluginName)) {
1649
                    continue;
1650
                }
1651

    
1652
                // Se obtienen las dependencias y sus class loaders
1653
                boolean ready = true;
1654
                Depends[] dependencies = config.getDepends();
1655
                PluginClassLoader[] loaders =
1656
                    new PluginClassLoader[dependencies.length];
1657

    
1658
                for (int j = 0; j < dependencies.length; j++) {
1659
                    if (pluginsConfig.get(dependencies[j].getPluginName()) == null) {
1660
                        this
1661
                            .addError(Messages
1662
                                .getString("Launcher.Dependencia_no_resuelta_en_plugin")
1663
                                + " "
1664
                                + pluginName
1665
                                + ": "
1666
                                + dependencies[j].getPluginName());
1667

    
1668
                        continue;
1669
                    }
1670

    
1671
                    if (!installed.contains(dependencies[j].getPluginName())) {
1672
                        ready = false;
1673
                    } else {
1674
                        loaders[j] =
1675
                            (pluginsServices.get(dependencies[j]
1676
                                .getPluginName())).getClassLoader();
1677
                    }
1678
                }
1679

    
1680
                // Si no est?n sus dependencias satisfechas se aborta la
1681
                // instalaci?n
1682
                if (!ready) {
1683
                    continue;
1684
                }
1685

    
1686
                // Se genera el class loader
1687
                String jardir = config.getLibraries().getLibraryDir();
1688
                File jarDir =
1689
                    new File(andamiConfig.getPluginsDirectory(), pluginName
1690
                        + File.separator + jardir);
1691
                File[] jarFiles = jarDir.listFiles(new FileFilter() {
1692

    
1693
                    public boolean accept(File pathname) {
1694
                        return (pathname.getName().toUpperCase()
1695
                            .endsWith(".JAR"))
1696
                            || (pathname.getName().toUpperCase()
1697
                                .endsWith(".ZIP"));
1698
                    }
1699
                });
1700

    
1701
                URL[] urls = new URL[jarFiles.length];
1702

    
1703
                for (int j = 0; j < jarFiles.length; j++) {
1704
                    try {
1705
                        urls[j] = new URL("file:" + jarFiles[j]);
1706
                    } catch (MalformedURLException e) {
1707
                        this.addError(Messages
1708
                            .getString("Launcher.No_se_puede_acceder_a")
1709
                            + " " + jarFiles[j]);
1710
                    }
1711
                }
1712

    
1713
                PluginClassLoader loader;
1714

    
1715
                try {
1716
                    loader =
1717
                        new PluginClassLoader(urls, andamiConfig
1718
                            .getPluginsDirectory()
1719
                            + File.separator + pluginName, Launcher.class
1720
                            .getClassLoader(), loaders);
1721

    
1722
                    PluginServices ps = new PluginServices(loader);
1723

    
1724
                    pluginsServices.put(ps.getPluginName(), ps);
1725

    
1726
                    installed.add(pluginName);
1727
                    // FJP: Los metemos ordenados para luego no cargar uno que
1728
                    // necesita de otro antes de tiempo. Esto lo usaremos al
1729
                    // inicializar los plugins
1730
                    pluginsOrdered.add(pluginName);
1731

    
1732
                    circle = false;
1733
                } catch (IOException e) {
1734
                    this
1735
                        .addError(
1736
                            Messages
1737
                                .getString("Launcher.Error_con_las_librerias_del_plugin"),
1738
                            e);
1739
                    pluginsConfig.remove(pluginName);
1740
                    i = pluginsConfig.keySet().iterator();
1741
                }
1742
            }
1743

    
1744
            if (circle) {
1745
                this.addError(Messages
1746
                    .getString("Launcher.Hay_dependencias_circulares"));
1747

    
1748
                break;
1749
            }
1750
        }
1751

    
1752
        // Se eliminan los plugins que no fueron instalados
1753
        Iterator<String> i = pluginsConfig.keySet().iterator();
1754

    
1755
        while (i.hasNext()) {
1756
            String pluginName = i.next();
1757
            PluginServices ps =
1758
                (PluginServices) pluginsServices.get(pluginName);
1759

    
1760
            if (ps == null) {
1761
                pluginsConfig.remove(pluginName);
1762
                i = pluginsConfig.keySet().iterator();
1763
            }
1764
        }
1765
    }
1766

    
1767
    private void pluginsMessages() {
1768
        Iterator<String> iterator = pluginsOrdered.iterator();
1769
        PluginConfig config;
1770
        PluginServices ps;
1771

    
1772
        while (iterator.hasNext()) {
1773
            String pluginName = iterator.next();
1774
            config = pluginsConfig.get(pluginName);
1775
            ps = pluginsServices.get(pluginName);
1776

    
1777
            if ((config.getResourceBundle() != null)
1778
                && !config.getResourceBundle().getName().equals("")) {
1779
                // add the locale files associated with the plugin
1780
                org.gvsig.i18n.Messages.addResourceFamily(config
1781
                    .getResourceBundle().getName(), ps.getClassLoader(),
1782
                    pluginName);
1783
            }
1784
        }
1785
    }
1786

    
1787
    static public PluginServices getPluginServices(String name) {
1788
        return (PluginServices) pluginsServices.get(name);
1789
    }
1790

    
1791
    static String getPluginsDir() {
1792
        return andamiConfig.getPluginsDirectory();
1793
    }
1794

    
1795
    static void setPluginsDir(String s) {
1796
        andamiConfig.setPluginsDirectory(s);
1797
    }
1798

    
1799
    static MDIFrame getMDIFrame() {
1800
        return frame;
1801
    }
1802

    
1803
    private void loadPlugins(String pluginsDirectory) {
1804
        File pDir = new File(pluginsDirectory);
1805

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

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

    
1825
        for (int i = 0; i < pluginDirs.length; i++) {
1826
            if (pluginDirs[i].isDirectory()) {
1827
                File configXml =
1828
                    new File(pluginDirs[i].getAbsolutePath(), "config.xml");
1829

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

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

    
1869
    private static Locale getLocale(String language, String country,
1870
        String variant) {
1871
        if (variant != null) {
1872
            return new Locale(language, country, variant);
1873
        } else
1874
            if (country != null) {
1875
                return new Locale(language, country);
1876
            } else
1877
                if (language != null) {
1878
                    return new Locale(language);
1879
                } else {
1880
                    return new Locale("es");
1881
                }
1882
    }
1883

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

    
1894
        BufferedOutputStream os =
1895
            new BufferedOutputStream(new FileOutputStream(tmpFile));
1896
        OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING);
1897
        andamiConfig.marshal(writer);
1898
        writer.close();
1899

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

    
1916
    private static void andamiConfigFromXML(String file)
1917
        throws ConfigurationException {
1918
        File xml = new File(file);
1919

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

    
1952
    private static AndamiConfig getDefaultAndamiConfig() {
1953
        AndamiConfig andamiConfig = new AndamiConfig();
1954

    
1955
        Andami andami = new Andami();
1956
        andami.setUpdate(true);
1957
        andamiConfig.setAndami(andami);
1958
        andamiConfig.setLocaleCountry(Locale.getDefault().getCountry());
1959
        andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage());
1960
        andamiConfig.setLocaleVariant(Locale.getDefault().getVariant());
1961

    
1962
        if (System.getProperty("javawebstart.version") != null) // Es java web
1963
        // start)
1964
        {
1965
            andamiConfig
1966
                .setPluginsDirectory(new File(appHomeDir, "extensiones")
1967
                    .getAbsolutePath());
1968
        } else {
1969
            andamiConfig.setPluginsDirectory(new File(appName, "extensiones")
1970
                .getAbsolutePath());
1971
        }
1972

    
1973
        andamiConfig.setPlugin(new Plugin[0]);
1974
        return andamiConfig;
1975
    }
1976

    
1977
    private static XMLEntity persistenceFromXML() throws ConfigurationException {
1978
        File xml = getPluginsPersistenceFile(true);
1979

    
1980
        if (xml.exists()) {
1981
            InputStreamReader reader = null;
1982

    
1983
            try {
1984
                reader = XMLEncodingUtils.getReader(xml);
1985
                XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1986
                return new XMLEntity(tag);
1987
            } catch (FileNotFoundException e) {
1988
                throw new ConfigurationException(e);
1989
            } catch (MarshalException e) {
1990

    
1991
                // try to reopen with default encoding (for backward
1992
                // compatibility)
1993
                try {
1994
                    reader = new FileReader(xml);
1995
                    XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1996
                    return new XMLEntity(tag);
1997

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

    
2031
    private static File getPluginsPersistenceFile(boolean read) {
2032
        if (read) {
2033
            File pluginsPersistenceFile =
2034
                new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2035
            if (pluginsPersistenceFile.exists()) {
2036
                return pluginsPersistenceFile;
2037
            }
2038
            pluginsPersistenceFile =
2039
                new File(getAppHomeDir(), "plugins-persistence.xml");
2040
            if (pluginsPersistenceFile.exists()) {
2041
                return pluginsPersistenceFile;
2042
            }
2043
        }
2044
        return new File(getAppHomeDir(), "plugins-persistence-2_0.xml");
2045

    
2046
    }
2047

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

    
2056
        File xml = getPluginsPersistenceFile(false);
2057
        OutputStreamWriter writer = null;
2058

    
2059
        try {
2060
            writer =
2061
                new OutputStreamWriter(new FileOutputStream(tmpFile),
2062
                    CASTORENCODING);
2063
            entity.getXmlTag().marshal(writer);
2064
            writer.close();
2065

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

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

    
2098
    static MDIFrame getFrame() {
2099
        return frame;
2100
    }
2101

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

    
2113
    static HashMap getClassesExtensions() {
2114
        return classesExtensions;
2115
    }
2116

    
2117
    private static Extensions[] getExtensions() {
2118
        List<Extensions> array = new ArrayList<Extensions>();
2119
        Iterator<PluginConfig> iter = pluginsConfig.values().iterator();
2120

    
2121
        while (iter.hasNext()) {
2122
            array.add(iter.next().getExtensions());
2123
        }
2124

    
2125
        return array.toArray(new Extensions[array.size()]);
2126
    }
2127

    
2128
    public static Iterator getExtensionIterator() {
2129
        return extensions.iterator();
2130
    }
2131

    
2132
    public static HashMap getPluginConfig() {
2133
        return pluginsConfig;
2134
    }
2135

    
2136
    public static Extension getExtension(String s) {
2137
        Extensions[] exts = getExtensions();
2138

    
2139
        for (int i = 0; i < exts.length; i++) {
2140
            for (int j = 0; j < exts[i].getExtensionCount(); j++) {
2141
                if (exts[i].getExtension(j).getClassName().equals(s)) {
2142
                    return exts[i].getExtension(j);
2143
                }
2144
            }
2145
        }
2146

    
2147
        return null;
2148
    }
2149

    
2150
    public static AndamiConfig getAndamiConfig() {
2151
        return andamiConfig;
2152
    }
2153

    
2154
    private static class ExtensionComparator implements Comparator {
2155

    
2156
        public int compare(Object o1, Object o2) {
2157
            Extension e1 = (Extension) o1;
2158
            Extension e2 = (Extension) o2;
2159

    
2160
            if (!e1.hasPriority() && !e2.hasPriority()) {
2161
                return -1;
2162
            }
2163

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

    
2168
            if (e2.hasPriority() && !e1.hasPriority()) {
2169
                return Integer.MAX_VALUE;
2170
            }
2171

    
2172
            if (e1.getPriority() != e2.getPriority()) {
2173
                return e2.getPriority() - e1.getPriority();
2174
            } else {
2175
                return (e2.toString().compareTo(e1.toString()));
2176
            }
2177
        }
2178
    }
2179

    
2180
    private static class MenuComparator implements Comparator<SortableMenu> {
2181

    
2182
        private static ExtensionComparator extComp = new ExtensionComparator();
2183

    
2184
        public int compare(SortableMenu e1, SortableMenu e2) {
2185

    
2186
            if (!e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2187
                if (e1.extension instanceof SkinExtensionType) {
2188
                    return 1;
2189
                } else
2190
                    if (e2.extension instanceof SkinExtensionType) {
2191
                        return -1;
2192
                    } else {
2193
                        return extComp.compare(e1.extension, e2.extension);
2194
                    }
2195
            }
2196

    
2197
            if (e1.menu.hasPosition() && !e2.menu.hasPosition()) {
2198
                return Integer.MIN_VALUE;
2199
            }
2200

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

    
2214
    private static class SortableMenu {
2215

    
2216
        public PluginClassLoader loader;
2217
        public Menu menu;
2218
        public SkinExtensionType extension;
2219

    
2220
        public SortableMenu(PluginClassLoader loader,
2221
            SkinExtensionType skinExt, Menu menu2) {
2222
            extension = skinExt;
2223
            menu = menu2;
2224
            this.loader = loader;
2225
        }
2226
    }
2227

    
2228
    private static class SortableTool {
2229

    
2230
        public PluginClassLoader loader;
2231
        public ToolBar toolbar;
2232
        public ActionTool actiontool;
2233
        public SelectableTool selectabletool;
2234
        public SkinExtensionType extension;
2235

    
2236
        public SortableTool(PluginClassLoader loader,
2237
            SkinExtensionType skinExt, ToolBar toolbar2, ActionTool actiontool2) {
2238
            extension = skinExt;
2239
            toolbar = toolbar2;
2240
            actiontool = actiontool2;
2241
            this.loader = loader;
2242
        }
2243

    
2244
        public SortableTool(PluginClassLoader loader,
2245
            SkinExtensionType skinExt, ToolBar toolbar2,
2246
            SelectableTool selectabletool2) {
2247
            extension = skinExt;
2248
            toolbar = toolbar2;
2249
            selectabletool = selectabletool2;
2250
            this.loader = loader;
2251
        }
2252
    }
2253

    
2254
    private static class ToolBarComparator implements Comparator<SortableTool> {
2255

    
2256
        private static ExtensionComparator extComp = new ExtensionComparator();
2257

    
2258
        public int compare(SortableTool e1, SortableTool e2) {
2259

    
2260
            // if the toolbars have the same name, they are considered to be
2261
            // the same toolbar, so we don't need to do further comparing
2262
            if (e1.toolbar.getName().equals(e2.toolbar.getName())) {
2263
                return 0;
2264
            }
2265

    
2266
            if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2267
                if (e1.extension instanceof SkinExtensionType) {
2268
                    return 1;
2269
                } else
2270
                    if (e2.extension instanceof SkinExtensionType) {
2271
                        return -1;
2272
                    } else {
2273
                        return extComp.compare(e1.extension, e2.extension);
2274
                    }
2275
            }
2276

    
2277
            if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) {
2278
                return Integer.MIN_VALUE;
2279
            }
2280

    
2281
            if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) {
2282
                return Integer.MAX_VALUE;
2283
            }
2284
            if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) {
2285
                return e1.toolbar.getPosition() - e2.toolbar.getPosition();
2286
            }
2287

    
2288
            if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool())
2289
                && e1.toolbar.getSelectableTool().equals(
2290
                    e2.toolbar.getSelectableTool())) {
2291
                return 0;
2292
            }
2293
            return (e1.toolbar.toString().compareTo(e2.toolbar.toString()));
2294
        }
2295
    }
2296

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

    
2320
        private static ToolBarComparator toolBarComp = new ToolBarComparator();
2321

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

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

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

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

    
2371
    /**
2372
     * validates the user before starting gvsig
2373
     * 
2374
     */
2375
    private static void validate() {
2376

    
2377
        IAuthentication session = null;
2378
        try {
2379
            session =
2380
                (IAuthentication) Class.forName(
2381
                    "com.iver.andami.authentication.Session").newInstance();
2382

    
2383
        } catch (ClassNotFoundException e) {
2384
            return;
2385
        } catch (InstantiationException e) {
2386
            return;
2387
        } catch (IllegalAccessException e) {
2388
            return;
2389
        }
2390

    
2391
        session.setPluginDirectory(andamiConfig.getPluginsDirectory());
2392
        if (session.validationRequired()) {
2393
            if (session.Login()) {
2394
                logger.info("You are logged in");
2395
            } else {
2396
                JOptionPane.showMessageDialog((Component) PluginServices
2397
                    .getMainFrame(), "You are not logged in");
2398
            }
2399
            PluginServices.setAuthentication(session);
2400
        }
2401
    }
2402

    
2403
    public static String getDefaultLookAndFeel() {
2404
        String osName = (String) System.getProperty("os.name");
2405

    
2406
        if ((osName.length() > 4)
2407
            && osName.substring(0, 5).toLowerCase().equals("linux")) {
2408
            return nonWinDefaultLookAndFeel;
2409
        }
2410
        if (osName.toLowerCase().startsWith("mac os x")) {
2411
            return "ch.randelshofer.quaqua.QuaquaLookAndFeel";
2412
        }
2413

    
2414
        return UIManager.getSystemLookAndFeelClassName();
2415
    }
2416

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

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

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

    
2528
    }
2529

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

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

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

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

    
2594
        logger
2595
            .error(Messages
2596
                .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI")
2597
                + " '" + name + "'");
2598
    }
2599

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

    
2638
    public static void initIconThemes() {
2639
        IconThemeManager iconManager = IconThemeManager.getIconThemeManager();
2640
        IIconTheme icontheme = iconManager.getIconThemeFromConfig();
2641
        if (icontheme != null) {
2642
            iconManager.setCurrent(icontheme);
2643
        }
2644
    }
2645

    
2646
    /**
2647
     * Manages Andami termination process
2648
     * 
2649
     * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
2650
     */
2651
    public class TerminationProcess {
2652

    
2653
        private boolean proceed = false;
2654
        private UnsavedDataPanel panel = null;
2655

    
2656
        public void run() {
2657
            int exit = manageUnsavedData();
2658
            if ((exit == JOptionPane.NO_OPTION)
2659
                || (exit == JOptionPane.CLOSED_OPTION)) {
2660
                // the user doesn't want to exit
2661
                return;
2662
            }
2663

    
2664
            closeAndami();
2665
        }
2666

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

    
2678
            
2679
            try {
2680
                // Persistencia de los plugins
2681
                savePluginPersistence();
2682
                savePluginsProperties();
2683
            } catch(Exception ex) {
2684
                logger.error("There was an error exiting application, can't save plugins properties", ex);
2685
            }
2686

    
2687
            // Finalize all the extensions
2688
            finalizeExtensions();
2689

    
2690
            try {
2691
                // Clean any temp data created
2692
                Utilities.cleanUpTempFiles();
2693
            } catch(Exception ex) {
2694
                logger.error("There was an error exiting application, can't remove temporary files", ex);
2695
            }
2696

    
2697
            logger.info("Quiting application.");
2698
            
2699
            // Para la depuraci?n de memory leaks
2700
            System.gc();
2701

    
2702
            System.exit(0);
2703
        }
2704

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

    
2733
        private void savePluginsProperties() {
2734
            PluginsManager manager = PluginsLocator.getManager();
2735
            List<PluginServices> plugins = manager.getPlugins();
2736
            for (PluginServices plugin : plugins) {
2737
                if (plugin != null) {
2738
                    plugin.savePluginProperties();
2739
                }
2740
            }
2741
        }
2742

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

    
2764
        private IUnsavedData[] getUnsavedData() {
2765
            List<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>();
2766
            IExtension exclusiveExtension =
2767
                PluginServices.getExclusiveUIExtension();
2768

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

    
2791
        public UnsavedDataPanel getUnsavedDataPanel() {
2792
            if (panel == null) {
2793
                panel = new UnsavedDataPanel(new IUnsavedData[0]);
2794
            }
2795
            return panel;
2796
        }
2797

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

    
2807
            // there was no unsaved data
2808
            if (unsavedData.length == 0) {
2809
                int option =
2810
                    JOptionPane
2811
                        .showConfirmDialog(frame, Messages
2812
                            .getString("MDIFrame.quiere_salir"), Messages
2813
                            .getString("MDIFrame.salir"),
2814
                            JOptionPane.YES_NO_OPTION);
2815
                return option;
2816
            }
2817

    
2818
            UnsavedDataPanel panel = getUnsavedDataPanel();
2819
            panel.setUnsavedDataArray(unsavedData);
2820

    
2821
            panel.addActionListener(panel.new UnsavedDataPanelListener() {
2822

    
2823
                public void cancel(UnsavedDataPanel panel) {
2824
                    proceed(false);
2825
                    PluginServices.getMDIManager().closeWindow(panel);
2826

    
2827
                }
2828

    
2829
                public void discard(UnsavedDataPanel panel) {
2830
                    proceed(true);
2831
                    PluginServices.getMDIManager().closeWindow(panel);
2832

    
2833
                }
2834

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

    
2866
                            unsavedDataArray = getUnsavedData();
2867
                            panel.setUnsavedDataArray(unsavedDataArray);
2868
                            return;
2869
                        }
2870
                    }
2871
                    proceed(true);
2872
                    PluginServices.getMDIManager().closeWindow(panel);
2873
                }
2874
            });
2875

    
2876
            PluginServices.getMDIManager().addWindow(panel);
2877
            if (proceed) {
2878
                return JOptionPane.YES_OPTION;
2879
            } else {
2880
                return JOptionPane.NO_OPTION;
2881
            }
2882
        }
2883

    
2884
        private void proceed(boolean proceed) {
2885
            this.proceed = proceed;
2886
        }
2887

    
2888
    }
2889

    
2890
    public static TerminationProcess getTerminationProcess() {
2891
        return (new Launcher()).new TerminationProcess();
2892
    }
2893

    
2894
    /**
2895
     * Launch the gvSIG package installer.
2896
     * 
2897
     * @throws Exception
2898
     *             if there is any error
2899
     */
2900
    private void doInstall(String[] args) throws Exception {
2901
        String installURL = null;
2902
        String installURLFile = null;
2903
        String gvSIGVersion = null;
2904
        String[] myArgs = new String[2];
2905
        
2906
                Options options = new Options();
2907
                options.addOption("i", "install", false,
2908
                                "install");
2909
                options.addOption("u", "installURL", true,
2910
                                "installURL");
2911
                options.addOption("f", "installURLFile", true,
2912
                                "installURLFile");
2913
                options.addOption("v", "installVersion", true, "installVersion");
2914
                options.addOption("A", "applicationName", true, "applicationName");
2915
                options.addOption("P", "pluginsFolder", true, "pluginsFolder");
2916

    
2917
                CommandLineParser parser = new PosixParser();
2918
                CommandLine line = null;
2919
                try {
2920
                        line = parser.parse(options, args);
2921
                        boolean hasAllMandatoryOptions = true;
2922
                        if (!line.hasOption("install")) {
2923
                                hasAllMandatoryOptions = false;
2924
                        }
2925
                        if (line.hasOption("installURL")) {
2926
                                installURL = line.getOptionValue("installURL");
2927
                        }
2928
                        if (line.hasOption("installURLFile")) {
2929
                                installURLFile = line.getOptionValue("installURLFile");
2930
                        }
2931
                        if (line.hasOption("installVersion")) {
2932
                                gvSIGVersion = line.getOptionValue("installVersion");
2933
                        }
2934
                        if (line.hasOption("applicationName")) {
2935
                                myArgs[0] = line.getOptionValue("applicationName");
2936
                        } else {
2937
                                hasAllMandatoryOptions = false;
2938
                        }
2939
                        if (line.hasOption("pluginsFolder")) {
2940
                                myArgs[1] = line.getOptionValue("pluginsFolder");
2941
                        } else {
2942
                                hasAllMandatoryOptions = false;
2943
                        }
2944
                        if (!hasAllMandatoryOptions) {
2945
                    System.err.println(Messages.get("usage")
2946
                                + ": Launcher --applicationName=appName --pluginsFolder=plugins-directory "
2947
                                + "[--installURLFile=File] "
2948
                                + "--install [--installURL=URL] [language=locale]");
2949
                    return;
2950
                        }
2951
                } catch (ParseException exp) {
2952
                        System.out.println("Unexpected exception:" + exp.getMessage());
2953
                }
2954

    
2955
        initializeApp(myArgs);
2956
        initializeLibraries();
2957
        AndamiConfig config = getAndamiConfig();
2958
        config.setLocaleLanguage(locale.getLanguage());
2959
        config.setLocaleCountry(locale.getCountry());
2960
        config.setLocaleVariant(locale.getVariant());
2961

    
2962
        // Configure default index download URL
2963
        if (installURL != null) {
2964
                SwingInstallerLocator.getSwingInstallerManager()
2965
                    .setDefaultDownloadURL(installURL);
2966
        }
2967

    
2968
        if (installURLFile != null) {
2969
                //TODO: Convertir a File y pasarlo
2970
            SwingInstallerLocator.getSwingInstallerManager()
2971
                .setDefaultDownloadURL(new File(installURLFile));
2972
        }
2973

    
2974
        // Launch installer
2975

    
2976
        PluginsManager manager = PluginsLocator.getManager();
2977
        AbstractInstallPackageWizard installPackageWizard =
2978
            SwingInstallerLocator.getSwingInstallerManager()
2979
                .createInstallPackageWizard(manager.getApplicationFolder(),
2980
                    manager.getPluginsFolder().getAbsoluteFile(),
2981
                    manager.getInstallFolder());
2982
        installPackageWizard
2983
            .setWizardActionListener(new InstallerWizardActionListener() {
2984

    
2985
                public void finish(InstallerWizardPanel installerWizard) {
2986
                    System.exit(0);
2987
                }
2988

    
2989
                public void cancel(InstallerWizardPanel installerWizard) {
2990
                    System.exit(0);
2991
                }
2992
            });
2993
        
2994
        // the wizard will show the Typical or Advanced mode option.
2995
        installPackageWizard.setAskTypicalOrCustom(true);
2996
        // default packages will be selected.
2997
        installPackageWizard.setSelectDefaultPackages(true);
2998
        
2999
        // set the gvSIG version to the install manager, to compose the download
3000
        // URL:
3001
        InstallerLocator.getInstallerManager().setVersion(gvSIGVersion);
3002
        
3003
        // 1. Create the frame.
3004
        JFrame frame = new JFrame(Messages.get("gvsig_package_installer"));
3005

    
3006
        // 2. What happens when the frame closes?
3007
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
3008
        Runtime.getRuntime().addShutdownHook(new Thread() {
3009

    
3010
            @Override
3011
            public void run() {
3012
                getTerminationProcess().saveAndamiConfig();
3013
            }
3014
        });
3015

    
3016
        // 3. Add the installer panel to the frame
3017
        frame.getContentPane().add(installPackageWizard, BorderLayout.CENTER);
3018

    
3019
        // 4. Size the frame and center on the screen
3020
        frame.pack();
3021
        frame.setLocationRelativeTo(null);
3022

    
3023
        // 5. Show it.
3024
        frame.setVisible(true);
3025
    }
3026
    
3027
        public static String getInformation() {
3028
                PluginsManager pluginmgr = PluginsLocator.getManager();
3029
                InstallerManager installmgr = InstallerLocator.getInstallerManager();
3030

    
3031
                StringWriter writer = new StringWriter();
3032

    
3033
                Properties props = System.getProperties();
3034

    
3035
                // OS information
3036
                String osName = props.getProperty("os.name");
3037
                writer.write("OS\n");
3038
                writer.write("    name   : " + osName + "\n");
3039
                writer.write("    arch   : " + props.get("os.arch") + "\n");
3040
                writer.write("    version: " + props.get("os.version") + "\n");
3041
                if (osName.startsWith("Linux")) {
3042
                        try {
3043
                                String[] command = {"lsb_release", "-a"};
3044
                                Process p = Runtime.getRuntime().exec(command);
3045
                                InputStream is = p.getInputStream();
3046
                                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
3047
                                String line;
3048
                                while ( (line = reader.readLine()) != null) {
3049
                                        writer.write("    "+line+"\n");
3050
                                }
3051
                        } catch (Exception ex) {
3052
                                writer.write("Can't get detailled os information (lsb_release -a).");
3053
                        }
3054
                }
3055

    
3056
                // JRE information
3057
                writer.write("JRE\n");
3058
                writer.write("    vendor : " + props.get("java.vendor") + "\n");
3059
                writer.write("    version: " +props.get("java.version")+ "\n");
3060
                writer.write("    home   : " + props.get("java.home") + "\n");
3061

    
3062
                writer.write("HTTP Proxy\n");
3063
                writer.write("    http.proxyHost     : " + props.get("http.proxyHost") + "\n");
3064
                writer.write("    http.proxyPort     : " + props.get("http.proxyPort") + "\n");
3065
                writer.write("    http.proxyUserName : " + props.get("http.proxyUserName") + "\n");
3066
                writer.write("    http.proxyPassword : " + props.get("http.proxyPassword") + "\n");
3067
                
3068
                String skinName = "(unknow)";
3069
                try {
3070
                        skinName = MDIManagerFactory.getSkinExtension().getClassName();
3071
                } catch (Throwable e) {
3072
                        // Ignore
3073
                }
3074
                writer.write("Application\n");
3075
                writer.write("    locale language         : " + Launcher.getAndamiConfig().getLocaleLanguage()+ "\n");
3076
                writer.write("    application forlder     : " + pluginmgr.getApplicationFolder()+ "\n");
3077
                writer.write("    install forlder         : " + pluginmgr.getInstallFolder()+ "\n");
3078
                writer.write("    application home forlder: " + pluginmgr.getApplicationHomeFolder()+ "\n");
3079
                writer.write("    plugins forlder         : " + pluginmgr.getPluginsFolder()+ "\n");
3080
        writer.write("    theme                   : "
3081
            + Launcher.theme.getSource() + "\n");
3082
//                writer.write("    Skin                    : " + skinName + "\n");
3083
                
3084
                
3085
                try {
3086
                        PackageInfo[] pkgs = installmgr.getInstalledPackages(pluginmgr.getPluginsFolder());
3087
                        writer.write("Installed packages\n");
3088
                        for( int i=0; i<pkgs.length; i++) {
3089
                                writer.write("    ");
3090
                                writer.write(pkgs[i].toStringCompact());
3091
                                writer.write("\n");
3092
                        }
3093
                } catch(Throwable e) {
3094
                        writer.write("Can't get installed package information.");
3095
                }
3096
                return writer.toString();
3097
        }
3098

    
3099
        private void logger_info(String msg) {
3100
                String info[] = msg.split("\n");
3101
                for (int i=0;i< info.length;i++) {
3102
                        logger.info(info[i]);
3103
                }
3104
        }
3105

    
3106

    
3107
}