Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / frameworks / _fwAndami / src / org / gvsig / andami / PluginServices.java @ 40411

History | View | Annotate | Download (30 KB)

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

    
43
import java.awt.Component;
44
import java.awt.Frame;
45
import java.awt.KeyEventDispatcher;
46
import java.awt.Toolkit;
47
import java.awt.datatransfer.DataFlavor;
48
import java.awt.datatransfer.StringSelection;
49
import java.awt.datatransfer.UnsupportedFlavorException;
50
import java.awt.event.ActionListener;
51
import java.io.File;
52
import java.io.FileInputStream;
53
import java.io.FileNotFoundException;
54
import java.io.FileOutputStream;
55
import java.io.IOException;
56
import java.lang.reflect.InvocationTargetException;
57
import java.util.ArrayList;
58
import java.util.Arrays;
59
import java.util.HashMap;
60
import java.util.Iterator;
61
import java.util.Properties;
62

    
63
import javax.swing.KeyStroke;
64
import javax.swing.SwingUtilities;
65
import javax.swing.Timer;
66

    
67
import org.gvsig.andami.authentication.IAuthentication;
68
import org.gvsig.andami.messages.Messages;
69
import org.gvsig.andami.messages.NotificationManager;
70
import org.gvsig.andami.plugins.ExclusiveUIExtension;
71
import org.gvsig.andami.plugins.ExtensionDecorator;
72
import org.gvsig.andami.plugins.IExtension;
73
import org.gvsig.andami.plugins.PluginClassLoader;
74
import org.gvsig.andami.preferences.DlgPreferences;
75
import org.gvsig.andami.ui.mdiFrame.MDIFrame;
76
import org.gvsig.andami.ui.mdiFrame.MainFrame;
77
import org.gvsig.andami.ui.mdiManager.MDIManager;
78
import org.gvsig.tools.ToolsLocator;
79
import org.gvsig.tools.dynobject.DynObject;
80
import org.gvsig.tools.dynobject.DynStruct;
81
import org.gvsig.tools.exception.BaseRuntimeException;
82
import org.gvsig.tools.persistence.PersistenceManager;
83
import org.gvsig.tools.persistence.PersistentState;
84
import org.gvsig.tools.persistence.exception.AddDefinitionException;
85
import org.gvsig.tools.swing.api.ToolsSwingLocator;
86
import org.gvsig.tools.swing.icontheme.IconTheme;
87
import org.gvsig.tools.swing.icontheme.IconThemeManager;
88
import org.gvsig.utils.XMLEntity;
89
import org.gvsig.utils.swing.threads.IMonitorableTask;
90
import org.gvsig.utils.swing.threads.IProgressMonitorIF;
91
import org.gvsig.utils.swing.threads.TaskMonitorTimerListener;
92
import org.gvsig.utils.swing.threads.UndefinedProgressMonitor;
93
import org.slf4j.Logger;
94
import org.slf4j.LoggerFactory;
95

    
96
/**
97
 * Provides services to Plugins. Each plugin has an associated PluginServices
98
 * object, which provides specific services. Main of them: translations,
99
 * logging, access to plugin's resources, background tasks, clipboard access
100
 * and data persistence.
101
 * 
102
 * @author Fernando Gonz�lez Cort�s
103
 */
104
public class PluginServices {
105

    
106
    private static Logger logger =
107
        LoggerFactory.getLogger(PluginServices.class);
108

    
109
    private static String[] arguments;
110

    
111
    private static IAuthentication authentication;
112

    
113
    private static ExclusiveUIExtension exclusiveUIExtension = null;
114

    
115
    private PluginClassLoader loader;
116

    
117
    private XMLEntity persistentXML;
118

    
119
    private DynObject pluginPersistence = null;
120

    
121
    private String[] alternativeNames = null;
122
    /**
123
     * Creates a new PluginServices objetct.
124
     * 
125
     * @param loader
126
     *            The Plugin's ClassLoader.
127
     */
128
    public PluginServices(PluginClassLoader loader) {
129
        this.loader = loader;
130
    }
131

    
132
    public PluginServices(PluginClassLoader loader, String[] alternativeNames) {
133
            this(loader);
134
        this.alternativeNames = alternativeNames;
135
    }
136

    
137
    public String[] getAlternativeNames() {
138
            return this.alternativeNames;
139
    }
140
    
141
    /**
142
     * Returns the message in the current's locale language
143
     * corresponding to the provided translation key.
144
     * The key-message pairs are obtained from the plugin's
145
     * translation files (text_xx.properties files).
146
     * 
147
     * @param key
148
     *            Translation key whose associated message is to be obtained
149
     * 
150
     * @return The message associated with the provided key, in one of the
151
     *         current locale languages, or the key if the translation is not
152
     *         found.
153
     */
154
    public String getText(String key) {
155
        if (key == null)
156
            return null;
157
        String translation = org.gvsig.i18n.Messages.getText(key, false);
158
        if (translation != null)
159
            return translation;
160
        else {
161
            logger.debug("Can't find translation for ''{}'' in plugin ''{}''.",
162
                key,
163
                getPluginName());
164
            return key;
165
        }
166
    }
167

    
168
    /**
169
     * Gets the plugin's classloader.
170
     * 
171
     * @return Returns the loader.
172
     */
173
    public PluginClassLoader getClassLoader() {
174
        return loader;
175
    }
176

    
177
    /**
178
     * Gets the plugin's name
179
     * 
180
     * @return The plugin's name
181
     */
182
    public String getPluginName() {
183
        return loader.getPluginName();
184
    }
185

    
186
    /**
187
     * Gets a reference to the PluginServices object associated with the
188
     * plugin containing the provided class.
189
     * 
190
     * Obtienen una referencia al PluginServices del plugin cuyo nombre se pasa
191
     * como par�metro
192
     * 
193
     * @param pluginClassInstance
194
     *            An instance of a class. This class is contained in a plugin,
195
     *            whose
196
     *            services are to be obtained
197
     * 
198
     * @return The PluginServices object associated to the containing plugin
199
     * 
200
     * @throws RuntimeException
201
     *             If the parameter was not loaded from a plugin
202
     */
203
    public static PluginServices getPluginServices(Object pluginClassInstance) {
204
        try {
205
                PluginClassLoader loader;
206
                    if( pluginClassInstance instanceof Class ) {
207
                            loader = (PluginClassLoader) ((Class) pluginClassInstance).getClassLoader();
208
                    } else {
209
                            loader = (PluginClassLoader) pluginClassInstance.getClass().getClassLoader();
210
                    }
211
            return Launcher.getPluginServices(loader.getPluginName());
212
        } catch (ClassCastException e) {
213
            /*
214
             * throw new RuntimeException( "Parameter is not a plugin class
215
             * instance");
216
             */
217
            return null;
218
        }
219
    }
220

    
221
    /**
222
     * Gets a reference to the PluginServices object associated with the
223
     * provided plugin.
224
     * 
225
     * @param pluginName
226
     *            Plugin's name whose services are going to be used
227
     * 
228
     * @return The PluginServices object associated with the provided plugin.
229
     */
230
    public static PluginServices getPluginServices(String pluginName) {
231
        return Launcher.getPluginServices(pluginName);
232
    }
233

    
234
    /**
235
     * Gets the window manager (MDIManager).
236
     * 
237
     * @return A reference to the window manager (MDIManager).
238
     */
239
    public static MDIManager getMDIManager() {
240
        return Launcher.getFrame().getMDIManager();
241
    }
242

    
243
    /**
244
     * Gets the application's main frame.
245
     * 
246
     * @return A reference to the application's main window
247
     */
248
    public static MainFrame getMainFrame() {
249
        return Launcher.getFrame();
250
    }
251

    
252
    public static void registerKeyStroke(KeyStroke key, KeyEventDispatcher a) {
253
        GlobalKeyEventDispatcher.getInstance().registerKeyStroke(key, a);
254
    }
255

    
256
    public static void unRegisterKeyStroke(KeyStroke key) {
257
        GlobalKeyEventDispatcher.getInstance().removeKeyStrokeBinding(key);
258
    }
259

    
260
    /**
261
     * Gets the instance of the extension whose class is provided.
262
     * 
263
     * @param extensionClass
264
     *            Class of the extension whose instance is to be returned
265
     * 
266
     * @return The instance of the extension, or null if the instance does
267
     *         not exist.Instancia de la extensi�n o null en caso de que no haya
268
     *         una
269
     */
270
    public static IExtension getExtension(Class extensionClass) {
271
        ExtensionDecorator extAux =
272
            (ExtensionDecorator) Launcher.getClassesExtensions()
273
            .get(extensionClass);
274
        try {
275
            return extAux.getExtension();
276
        } catch (NullPointerException ex) {
277
            return null;
278
        }
279
    }
280

    
281
    /**
282
     * Gets a reference to the Extension Decorator which adds some extra options
283
     * to the basic extension interface.
284
     * 
285
     * @param extensionClass
286
     *            The class of the extension whose decorator is to be returned
287
     * @return The ExtensionDecorator associated with the provided extension,
288
     *         or null if the extension does not exist.
289
     */
290
    public static ExtensionDecorator getDecoratedExtension(Class extensionClass) {
291
        return (ExtensionDecorator) Launcher.getClassesExtensions()
292
        .get(extensionClass);
293
    }
294

    
295
    /**
296
     * Returns an array containing references to all the loaded extensions.
297
     * 
298
     * @return ExtensionDecorator[] An array of ExtensionDecorators (each
299
     *         Decorator contains one extension).
300
     */
301
    public static ExtensionDecorator[] getDecoratedExtensions() {
302
        HashMap map = Launcher.getClassesExtensions();
303
        ExtensionDecorator[] extensions =
304
            (ExtensionDecorator[]) map.values()
305
            .toArray(new ExtensionDecorator[0]);
306
        return extensions;
307
    }
308

    
309
    /**
310
     * Gets an iterator with all the loaded Extensions.
311
     * 
312
     * @return Iterator over the decorated extensions (each member of
313
     *         the iterator is an ExtensionDecorator, which in turn contains
314
     *         one IExtension object).
315
     */
316
    public static Iterator getExtensions() {
317
        return Launcher.getClassesExtensions().values().iterator();
318
    }
319

    
320
    /**
321
     * Returns the message in the current's locale language
322
     * corresponding to the provided translation key.
323
     * The key-message pairs are obtained from the plugin's
324
     * translation files (text_xx.properties files).
325
     * 
326
     * @param pluginObject
327
     *            Any object which was loaded from a plugin
328
     * 
329
     * @param key
330
     *            Translation key whose associated message is to be obtained
331
     * 
332
     * @return The message associated with the provided key, in one of the
333
     *         current locale languages, or the key if the translation is not
334
     *         found.
335
     */
336
    public static String getText(Object pluginObject, String key) {
337
        if (key == null)
338
            return null;
339
        String translation = org.gvsig.i18n.Messages.getText(key, false);
340
        if (translation != null)
341
            return translation;
342
        else {
343
            logger.debug("Can't find translation for ''{}''.", key);
344
            return key;
345
        }
346
    }
347

    
348
    /**
349
     * Sets the XML data which should be saved on disk for this plugin. This
350
     * data can be retrieved on following sessions.
351
     * 
352
     * @param The
353
     *            XMLEntity object containing the data to be persisted.
354
     * 
355
     * @see PluginServices.getPersistentXML()
356
     * @see XMLEntity
357
     */
358
    public void setPersistentXML(XMLEntity entity) {
359
        persistentXML = entity;
360
    }
361

    
362
    /**
363
     * Gets the XML data which was saved on previous sessions for this
364
     * plugins.
365
     * 
366
     * @return An XMLEntity object containing the persisted data
367
     */
368
    public XMLEntity getPersistentXML() {
369
        if (persistentXML == null) {
370
            persistentXML = new XMLEntity();
371
        }
372
        return persistentXML;
373
    }
374

    
375
    /**
376
     * A�ade un listener a un popup menu registrado en el config.xml de alg�n
377
     * plugin
378
     * 
379
     * @param name
380
     *            Nombre del men� contextual
381
     * @param c
382
     *            Componente que desplegar� el men� cuando se haga click con el
383
     *            bot�n derecho
384
     * @param listener
385
     *            Listener que se ejecutar� cuando se seleccione cualquier
386
     *            entrada del men�
387
     * 
388
     * @throws RuntimeException
389
     *             Si la interfaz no est� preparada todav�a. S�lo puede darse
390
     *             durante el arranque
391
     */
392
    public void addPopupMenuListener(String name,
393
        Component c,
394
        ActionListener listener) {
395
        MDIFrame frame = Launcher.getFrame();
396

    
397
        if (frame == null) {
398
            throw new RuntimeException("MDIFrame not loaded yet");
399
        }
400

    
401
        frame.addPopupMenuListener(name, c, listener, loader);
402
    }
403

    
404
    /**
405
     * Gets the plugin's root directory.
406
     * 
407
     * @return A File pointing to the plugin's root directory.
408
     */
409
    public File getPluginDirectory() {
410
        return new File(Launcher.getPluginsDir() + File.separator
411
            + getPluginName());
412
    }
413

    
414
    /**
415
     * Runs a background task. The events produced on the main frame will
416
     * be inhibited.
417
     * 
418
     * @param r
419
     *            The task to run.
420
     * 
421
     * @return The Thread on which the task is executed.
422
     */
423
    public static Thread backgroundExecution(Runnable r) {
424
        Thread t = new Thread(new RunnableDecorator(r));
425
        t.start();
426

    
427
        return t;
428
    }
429

    
430
    /**
431
     * Runs a backbround task. This task may be monitored and canceled, and
432
     * does not inhibit any event.
433
     * 
434
     * @param task
435
     *            The task to run.
436
     */
437
    public static void cancelableBackgroundExecution(final IMonitorableTask task) {
438
        final org.gvsig.utils.swing.threads.SwingWorker worker =
439
            new org.gvsig.utils.swing.threads.SwingWorker() {
440

    
441
            public Object construct() {
442
                try {
443
                    task.run();
444
                    return task;
445
                } catch (Exception e) {
446
                    NotificationManager.addError(null, e);
447
                }
448
                return null;
449
            }
450

    
451
            /**
452
             * Called on the event dispatching thread (not on the worker
453
             * thread)
454
             * after the <code>construct</code> method has returned.
455
             */
456
            public void finished() {
457
                task.finished();
458
            }
459
        };
460

    
461
        Component mainFrame = (Component) PluginServices.getMainFrame();
462

    
463
        IProgressMonitorIF progressMonitor = null;
464
        String title = getText(null, "PluginServices.Procesando");
465
        progressMonitor =
466
            new UndefinedProgressMonitor((Frame) mainFrame, title);
467
        progressMonitor.setIndeterminated(!task.isDefined());
468
        progressMonitor.setInitialStep(task.getInitialStep());
469
        progressMonitor.setLastStep(task.getFinishStep());
470
        progressMonitor.setCurrentStep(task.getCurrentStep());
471
        progressMonitor.setMainTitleLabel(task.getStatusMessage());
472
        progressMonitor.setNote(task.getNote());
473
        progressMonitor.open();
474
        int delay = 500;
475
        TaskMonitorTimerListener timerListener =
476
            new TaskMonitorTimerListener(progressMonitor, task);
477
        Timer timer = new Timer(delay, timerListener);
478
        timerListener.setTimer(timer);
479
        timer.start();
480

    
481
        worker.start();
482

    
483
    }
484

    
485
    /**
486
     * Closes the application. Cleanly exits from the application:
487
     * terminates all the extensions, then exits.
488
     * 
489
     */
490
    public static void closeApplication() {
491
        Launcher.closeApplication();
492
    }
493

    
494
    /**
495
     * DOCUMENT ME!
496
     * 
497
     * @author Fernando Gonz�lez Cort�s
498
     */
499
    private static class RunnableDecorator implements Runnable {
500

    
501
        private Runnable r;
502

    
503
        /**
504
         * Crea un nuevo RunnableDecorator.
505
         * 
506
         * @param r
507
         *            DOCUMENT ME!
508
         */
509
        public RunnableDecorator(Runnable r) {
510
            this.r = r;
511
        }
512

    
513
        /**
514
         * @see java.lang.Runnable#run()
515
         */
516
        public void run() {
517
            try {
518
                SwingUtilities.invokeAndWait(new Runnable() {
519

    
520
                    public void run() {
521
                        try {
522
                            r.run();
523
                        } catch (RuntimeException e) {
524
                            NotificationManager.addError(Messages.getString("PluginServices.Bug_en_el_codigo"),
525
                                e);
526
                        } catch (Error e) {
527
                            NotificationManager.addError(Messages.getString("PluginServices.Error_grave_de_la_aplicaci�n"),
528
                                e);
529
                        }
530
                    }
531
                });
532
            } catch (InterruptedException e) {
533
                NotificationManager.addWarning(Messages.getString("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
534
                    e);
535
            } catch (InvocationTargetException e) {
536
                NotificationManager.addWarning(Messages.getString("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
537
                    e);
538
            }
539
        }
540
    }
541

    
542
    /**
543
     * Gets an array containing the application's startup arguments. <br>
544
     * <br>
545
     * Usually: <code>appName plugins-directory [locale] [other args]</code>
546
     * 
547
     * @return the original arguments that Andami received. (app-name
548
     *         plugins-directory, locale, etc)
549
     */
550
    public static String[] getArguments() {
551
        return arguments;
552
    }
553

    
554
    /**
555
     * Replaces the original Andami arguments with the provided arguments.
556
     * 
557
     * @param arguments
558
     *            An array of String, each element of the array
559
     *            represents one
560
     *            argument.
561
     */
562
    public static void setArguments(String[] arguments) {
563
        PluginServices.arguments = arguments;
564
    }
565

    
566
    /**
567
     * Returns the value of a command line named argument. <br>
568
     * <br>
569
     * The argument format is: <br>
570
     * -{argumentName}={argumentValue} <br>
571
     * <br>
572
     * example: <br>
573
     * ' -language=en '
574
     * 
575
     * @return String The value of the argument
576
     */
577
    public static String getArgumentByName(String name) {
578
        for (int i = 2; i < PluginServices.arguments.length; i++) {
579
                String arg = PluginServices.arguments[i];
580
                if( arg != null ) {
581
                    int index = arg.indexOf(name + "=");
582
                    if (index != -1)
583
                        return arg.substring(index
584
                            + name.length() + 1);
585
                }
586
        }
587
        return null;
588
    }
589

    
590
    /**
591
     * Gets the logger. The logger is used to register important
592
     * events (errors, etc), which are stored on a file which
593
     * can be checked later.
594
     * 
595
     * @return A Logger object.
596
     * @see Logger object from the Log4j library.
597
     * 
598
     */
599
    public static Logger getLogger() {
600
        return logger;
601
    }
602

    
603
    public static IAuthentication getAuthentication() {
604
        return authentication;
605
    }
606

    
607
    public static void setAuthentication(IAuthentication authen) {
608
        authentication = authen;
609
    }
610

    
611
    public static DlgPreferences getDlgPreferences() {
612
        return DlgPreferences.getInstance();
613
    }
614

    
615
    /**
616
     * Stores the provided text data on the clipboard.
617
     * 
618
     * @param data
619
     *            An String containing the data to be stored
620
     *            on the clipboard.
621
     */
622
    public static void putInClipboard(String data) {
623
        StringSelection ss = new StringSelection(data);
624

    
625
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, ss);
626
    }
627

    
628
    /**
629
     * Gets text data from the Clipboard, if available.
630
     * 
631
     * @return An String containing the clipboard's data, or <code>null</code>
632
     *         if the data was not available.
633
     */
634
    public static String getFromClipboard() {
635

    
636
        try {
637
            return (String) Toolkit.getDefaultToolkit()
638
            .getSystemClipboard()
639
            .getContents(null)
640
            .getTransferData(DataFlavor.stringFlavor);
641
        } catch (UnsupportedFlavorException e) {
642
            return null;
643
        } catch (IOException e) {
644
            // TODO Auto-generated catch block
645
            return null;
646
        }
647
    }
648

    
649
    /**
650
     * Gets the ExclusiveUIExtension, an special extension which
651
     * will take
652
     * control over the UI and will decide which extensions may be
653
     * enable/disabled or visible/hidden.
654
     * 
655
     * @return If an ExclusiveUIExtension was set, return this extension.
656
     *         Otherwise, return <code>null</code>.
657
     * 
658
     * @see org.gvsig.andami.Launcher#initializeExclusiveUIExtension()
659
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
660
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
661
     */
662
    public static ExclusiveUIExtension getExclusiveUIExtension() {
663
        return PluginServices.exclusiveUIExtension;
664
    }
665

    
666
    /**
667
     * Sets the ExclusiveUIExtension, an special extension which
668
     * will take
669
     * control over the UI and will decide which extensions may be
670
     * enable/disabled or visible/hidden. <br>
671
     * <br>
672
     * The ExclusiveUIExtension is normally set by the following
673
     * Andami startup argument: <br>
674
     * <br>
675
     * <code>ExclusiveUIExtension=ExtensionName</code>
676
     * 
677
     * @see org.gvsig.andami.Launcher#initializeExclusiveUIExtension()
678
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
679
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
680
     */
681
    public static void setExclusiveUIExtension(ExclusiveUIExtension extension) {
682
        PluginServices.exclusiveUIExtension = extension;
683
    }
684

    
685
    public static void addLoaders(ArrayList classLoaders) {
686
        PluginClassLoader.addLoaders(classLoaders);
687
    }
688

    
689
    /**
690
     * @deprecated use ToolsSwingLocator.getIconThemeManager()
691
     */
692
    public static IconThemeManager getIconThemeManager() {
693
            return ToolsSwingLocator.getIconThemeManager();
694
    }
695

    
696
    /**
697
     * @deprecated use  ToolsSwingLocator.getIconThemeManager().getCurrent()
698
     */
699
    public static IconTheme getIconTheme() {
700
            return getIconThemeManager().getCurrent(); 
701
    }
702

    
703
    /**
704
     * Try to detect if the application is running in a development
705
     * environment. <br>
706
     * This look for <b>.project</b> and <b>.classpath</b> files in the starts
707
     * path of the application.
708
     * 
709
     * @return true if <b>.project</b> and <b>.classpath</b> are in the
710
     *         development path
711
     */
712
    public static boolean runningInDevelopment() {
713
        String andamiPath;
714
        Properties props = System.getProperties();
715

    
716
        try {
717
            try {
718
                andamiPath =
719
                    (new File(Launcher.class.getResource(".").getFile()
720
                        + File.separator + ".." + File.separator + ".."
721
                        + File.separator + ".." + File.separator + "..")).getCanonicalPath();
722
            } catch (IOException e) {
723
                andamiPath =
724
                    (new File(Launcher.class.getResource(".").getFile()
725
                        + File.separator + ".." + File.separator + ".."
726
                        + File.separator + ".." + File.separator + "..")).getAbsolutePath();
727
            }
728
        } catch (Exception e1) {
729
            andamiPath = (String) props.get("user.dir");
730
        }
731

    
732
        File andamiJar = new File(andamiPath + File.separator + "andami.jar");
733
        if (!andamiJar.exists())
734
            return false;
735
        File projectFile = new File(andamiPath + File.separator + ".project");
736
        File classpathFile =
737
            new File(andamiPath + File.separator + ".classpath");
738
        return projectFile.exists() && classpathFile.exists();
739

    
740
    }
741

    
742
    public PluginsManager getManager() {
743
        return PluginsLocator.getManager();
744
    }
745

    
746
    private String[] getAllPluginNames() {
747
            String[] names = new String[this.alternativeNames.length+1];
748
            names[0] = this.getPluginName();
749
            for( int n=0; n<this.alternativeNames.length; n++ ) {
750
                names[n+1] = this.alternativeNames[n];
751
            }
752
            return names;
753
    }
754
    
755
    public DynObject getPluginProperties() {
756
        if (this.pluginPersistence == null) {
757
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
758
            DynStruct dynStruct = manager.getDynObjectDefinition(getPluginName());
759
            if ( dynStruct == null) {
760
                File persistenceDefinitionFile =
761
                    new File(getManager().getPluginsDirectory().getAbsolutePath()
762
                        + File.separator + this.getPluginName()
763
                        + File.separator + "plugin-persistence.def");
764
                String[] names = getAllPluginNames(); 
765
                for( int i=0; i<names.length ; i++ ) {
766
                        try {
767
                            dynStruct = manager.addDefinition(DynObject.class,
768
                                names[i],
769
                                new FileInputStream(persistenceDefinitionFile),
770
                                this.getClassLoader(),
771
                                null,
772
                                null);
773
                            break;
774
                        } catch (FileNotFoundException e) {
775
                            throw new PluginPersistenceNeedDefinitionException(this.getPluginName(), e);
776
                        } catch (AddDefinitionException e) {
777
                                if( i+1 >= names.length ) { // Si ya no hay mas nombres peta
778
                                        throw new PluginPersistenceAddDefinitionException(this.getPluginName(), e);
779
                                }
780
                        }
781
                }
782
            }
783

    
784

    
785
                        File persistenceFile = getPluginPersistenceFile();
786
            if (persistenceFile.exists()) {
787
                PersistentState state;
788

    
789
                try {
790
                    state = manager.loadState(new FileInputStream(persistenceFile));
791
                    pluginPersistence = (DynObject) manager.create(state);
792
                } catch (Exception e) {
793
                    logger.error("Can't retrieve persistent values from plugin "+this.getPluginName(), e);
794
                }
795
            }
796
            if (this.pluginPersistence == null) {
797
                this.pluginPersistence =
798
                    ToolsLocator.getDynObjectManager()
799
                    .createDynObject(dynStruct); 
800
            }
801
        }
802
        return pluginPersistence;
803
    }
804

    
805
    public void savePluginProperties() {
806
        if (this.pluginPersistence == null) {
807
            return;
808
        }
809
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
810
                File persistenceFile = getPluginPersistenceFile();
811
        PersistentState state;
812
        FileOutputStream fos;
813
        try {
814
            state = manager.getState(pluginPersistence);
815
            manager.saveState(state, new FileOutputStream(persistenceFile));
816
        } catch (Exception e) {
817
            throw new PluginSaveDataException(this.getPluginName(), e);
818
        }
819

    
820

    
821
    }
822

    
823
        /**
824
         * Returns the plugin persistence file.
825
         * 
826
         * @return the plugin persistence file
827
         */
828
        private File getPluginPersistenceFile() {
829
                return new File(getPluginHomeFolder(), "plugin-persistence.dat");
830
        }
831

    
832
        /**
833
         * Returns the folder where the plugin stores its resources. That folder
834
         * will be usually a subfolder into the application folder in the user home
835
         * folder.
836
         * 
837
         * @return the folder where the plugin stores its resources
838
         */
839
        public File getPluginHomeFolder() {
840
                File persistenceFolder = new File(Launcher.getAppHomeDir()
841
                                + File.separator + "plugins" + File.separator
842
                                + this.getPluginName());
843

    
844
                if (!persistenceFolder.exists()) {
845
                        persistenceFolder.mkdirs();
846
                }
847

    
848
                return persistenceFolder;
849
        }
850

    
851
    public class PluginPersistenceNeedDefinitionException extends
852
    BaseRuntimeException {
853

    
854
        /**
855
         * 
856
         */
857
        private static final long serialVersionUID = -2036279527440882712L;
858

    
859
        PluginPersistenceNeedDefinitionException(String name, Throwable cause) {
860
            super("Can't load persistence definition of plugin %(name).",
861
                "_cant_load_persistence_definition_of_plugin_XnameX",
862
                serialVersionUID);
863
            initCause(cause);
864
            setValue("name", name);
865
        }
866
    }
867

    
868
    public class PluginPersistenceAddDefinitionException extends
869
    BaseRuntimeException {
870

    
871
        /**
872
         * 
873
         */
874
        private static final long serialVersionUID = 2227722796640780361L;
875

    
876
        PluginPersistenceAddDefinitionException(String name, Throwable cause) {
877
            super("Can't add persistence definition of plugin %(name).",
878
                "_cant_add_persistence_definition_of_plugin_XnameX",
879
                serialVersionUID);
880
            this.initCause(cause);
881
            setValue("name", name);
882
        }
883
    }
884

    
885
    public class PluginLoadDataException extends
886
    BaseRuntimeException {
887

    
888
        /**
889
         * 
890
         */
891
        private static final long serialVersionUID = 1168749231143949111L;
892

    
893
        PluginLoadDataException(String name) {
894
            super("Can't load data of plugin %(name).",
895
                "_cant_load_data_of_plugin_XnameX",
896
                serialVersionUID);
897
            setValue("name", name);
898
        }
899
    }
900

    
901
    public class PluginSaveDataException extends
902
    BaseRuntimeException {
903

    
904
        /**
905
         * 
906
         */
907
        private static final long serialVersionUID = 4893241183911774542L;
908
        private final static String MESSAGE_FORMAT = "Can't save data of plugin %(name).";
909
        private final static String MESSAGE_KEY = "_cant_save_data_of_plugin_XnameX";
910

    
911
        PluginSaveDataException(String name) {
912
            super(MESSAGE_FORMAT,
913
                MESSAGE_KEY,
914
                serialVersionUID);
915
            setValue("name", name);
916
        }
917

    
918
        public PluginSaveDataException(String name, Throwable cause) {
919
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
920
            setValue("name", name);
921

    
922
        }
923
    }
924
    
925
    @Override
926
    public String toString() {
927
        return super.toString()+" "+this.getPluginName();
928
    }
929
}