Statistics
| Revision:

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

History | View | Annotate | Download (29.4 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.HashMap;
59
import java.util.Iterator;
60
import java.util.Properties;
61

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

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

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

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

    
108
    private static String[] arguments;
109

    
110
    private static IAuthentication authentication;
111

    
112
    private static ExclusiveUIExtension exclusiveUIExtension = null;
113

    
114
    private PluginClassLoader loader;
115

    
116
    private XMLEntity persistentXML;
117

    
118
    private DynObject pluginPersistence = null;
119

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
426
        return t;
427
    }
428

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

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

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

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

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

    
480
        worker.start();
481

    
482
    }
483

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

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

    
500
        private Runnable r;
501

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
739
    }
740

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

    
745
    public DynObject getPluginProperties() {
746
        if (this.pluginPersistence == null) {
747
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
748
            DynStruct dynStruct = manager.getDynObjectDefinition(getPluginName());
749
            if ( dynStruct == null) {
750
                File persistenceDefinitionFile =
751
                    new File(getManager().getPluginsDirectory().getAbsolutePath()
752
                        + File.separator + this.getPluginName()
753
                        + File.separator + "plugin-persistence.def");
754
                try {
755
                    dynStruct = manager.addDefinition(DynObject.class,
756
                        this.getPluginName(),
757
                        new FileInputStream(persistenceDefinitionFile),
758
                        this.getClassLoader(),
759
                        null,
760
                        null);
761
                } catch (AddDefinitionException e) {
762
                    throw new PluginPersistenceAddDefinitionException(this.getPluginName(), e);
763
                } catch (FileNotFoundException e) {
764
                    throw new PluginPersistenceNeedDefinitionException(this.getPluginName(), e);
765
                }
766
            }
767

    
768

    
769
                        File persistenceFile = getPluginPersistenceFile();
770
            if (persistenceFile.exists()) {
771
                PersistentState state;
772

    
773
                try {
774
                    state = manager.loadState(new FileInputStream(persistenceFile));
775
                    pluginPersistence = (DynObject) manager.create(state);
776
                } catch (Exception e) {
777
                    logger.error("Can't retrieve persistent values from plugin "+this.getPluginName(), e);
778
                }
779
            }
780
            if (this.pluginPersistence == null) {
781
                this.pluginPersistence =
782
                    ToolsLocator.getDynObjectManager()
783
                    .createDynObject(dynStruct); 
784
            }
785
        }
786
        return pluginPersistence;
787
    }
788

    
789
    public void savePluginProperties() {
790
        if (this.pluginPersistence == null) {
791
            return;
792
        }
793
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
794
                File persistenceFile = getPluginPersistenceFile();
795
        PersistentState state;
796
        FileOutputStream fos;
797
        try {
798
            state = manager.getState(pluginPersistence);
799
            manager.saveState(state, new FileOutputStream(persistenceFile));
800
        } catch (Exception e) {
801
            throw new PluginSaveDataException(this.getPluginName(), e);
802
        }
803

    
804

    
805
    }
806

    
807
        /**
808
         * Returns the plugin persistence file.
809
         * 
810
         * @return the plugin persistence file
811
         */
812
        private File getPluginPersistenceFile() {
813
                return new File(getPluginHomeFolder(), "plugin-persistence.dat");
814
        }
815

    
816
        /**
817
         * Returns the folder where the plugin stores its resources. That folder
818
         * will be usually a subfolder into the application folder in the user home
819
         * folder.
820
         * 
821
         * @return the folder where the plugin stores its resources
822
         */
823
        public File getPluginHomeFolder() {
824
                File persistenceFolder = new File(Launcher.getAppHomeDir()
825
                                + File.separator + "plugins" + File.separator
826
                                + this.getPluginName());
827

    
828
                if (!persistenceFolder.exists()) {
829
                        persistenceFolder.mkdirs();
830
                }
831

    
832
                return persistenceFolder;
833
        }
834

    
835
    public class PluginPersistenceNeedDefinitionException extends
836
    BaseRuntimeException {
837

    
838
        /**
839
         * 
840
         */
841
        private static final long serialVersionUID = -2036279527440882712L;
842

    
843
        PluginPersistenceNeedDefinitionException(String name, Throwable cause) {
844
            super("Can't load persistence definition of plugin %(name).",
845
                "_cant_load_persistence_definition_of_plugin_XnameX",
846
                serialVersionUID);
847
            initCause(cause);
848
            setValue("name", name);
849
        }
850
    }
851

    
852
    public class PluginPersistenceAddDefinitionException extends
853
    BaseRuntimeException {
854

    
855
        /**
856
         * 
857
         */
858
        private static final long serialVersionUID = 2227722796640780361L;
859

    
860
        PluginPersistenceAddDefinitionException(String name, Throwable cause) {
861
            super("Can't add persistence definition of plugin %(name).",
862
                "_cant_add_persistence_definition_of_plugin_XnameX",
863
                serialVersionUID);
864
            this.initCause(cause);
865
            setValue("name", name);
866
        }
867
    }
868

    
869
    public class PluginLoadDataException extends
870
    BaseRuntimeException {
871

    
872
        /**
873
         * 
874
         */
875
        private static final long serialVersionUID = 1168749231143949111L;
876

    
877
        PluginLoadDataException(String name) {
878
            super("Can't load data of plugin %(name).",
879
                "_cant_load_data_of_plugin_XnameX",
880
                serialVersionUID);
881
            setValue("name", name);
882
        }
883
    }
884

    
885
    public class PluginSaveDataException extends
886
    BaseRuntimeException {
887

    
888
        /**
889
         * 
890
         */
891
        private static final long serialVersionUID = 4893241183911774542L;
892
        private final static String MESSAGE_FORMAT = "Can't save data of plugin %(name).";
893
        private final static String MESSAGE_KEY = "_cant_save_data_of_plugin_XnameX";
894

    
895
        PluginSaveDataException(String name) {
896
            super(MESSAGE_FORMAT,
897
                MESSAGE_KEY,
898
                serialVersionUID);
899
            setValue("name", name);
900
        }
901

    
902
        public PluginSaveDataException(String name, Throwable cause) {
903
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
904
            setValue("name", name);
905

    
906
        }
907
    }
908
    
909
    @Override
910
    public String toString() {
911
        return super.toString()+" "+this.getPluginName();
912
    }
913
}