Statistics
| Revision:

root / branches / v2_0_0_prep / frameworks / _fwAndami / src / org / gvsig / andami / PluginServices.java @ 38574

History | View | Annotate | Download (28.8 KB)

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

    
43
import java.awt.Component;
44
import java.awt.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
    /**
121
     * Creates a new PluginServices objetct.
122
     * 
123
     * @param loader
124
     *            The Plugin's ClassLoader.
125
     */
126
    public PluginServices(PluginClassLoader loader) {
127
        this.loader = loader;
128
    }
129

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

    
157
    /**
158
     * Gets the plugin's classloader.
159
     * 
160
     * @return Returns the loader.
161
     */
162
    public PluginClassLoader getClassLoader() {
163
        return loader;
164
    }
165

    
166
    /**
167
     * Gets the plugin's name
168
     * 
169
     * @return The plugin's name
170
     */
171
    public String getPluginName() {
172
        return loader.getPluginName();
173
    }
174

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

    
210
    /**
211
     * Gets a reference to the PluginServices object associated with the
212
     * provided plugin.
213
     * 
214
     * @param pluginName
215
     *            Plugin's name whose services are going to be used
216
     * 
217
     * @return The PluginServices object associated with the provided plugin.
218
     */
219
    public static PluginServices getPluginServices(String pluginName) {
220
        return Launcher.getPluginServices(pluginName);
221
    }
222

    
223
    /**
224
     * Gets the window manager (MDIManager).
225
     * 
226
     * @return A reference to the window manager (MDIManager).
227
     */
228
    public static MDIManager getMDIManager() {
229
        return Launcher.getFrame().getMDIManager();
230
    }
231

    
232
    /**
233
     * Gets the application's main frame.
234
     * 
235
     * @return A reference to the application's main window
236
     */
237
    public static MainFrame getMainFrame() {
238
        return Launcher.getFrame();
239
    }
240

    
241
    public static void registerKeyStroke(KeyStroke key, KeyEventDispatcher a) {
242
        GlobalKeyEventDispatcher.getInstance().registerKeyStroke(key, a);
243
    }
244

    
245
    public static void unRegisterKeyStroke(KeyStroke key) {
246
        GlobalKeyEventDispatcher.getInstance().removeKeyStrokeBinding(key);
247
    }
248

    
249
    /**
250
     * Gets the instance of the extension whose class is provided.
251
     * 
252
     * @param extensionClass
253
     *            Class of the extension whose instance is to be returned
254
     * 
255
     * @return The instance of the extension, or null if the instance does
256
     *         not exist.Instancia de la extensi?n o null en caso de que no haya
257
     *         una
258
     */
259
    public static IExtension getExtension(Class extensionClass) {
260
        ExtensionDecorator extAux =
261
            (ExtensionDecorator) Launcher.getClassesExtensions()
262
            .get(extensionClass);
263
        try {
264
            return extAux.getExtension();
265
        } catch (NullPointerException ex) {
266
            return null;
267
        }
268
    }
269

    
270
    /**
271
     * Gets a reference to the Extension Decorator which adds some extra options
272
     * to the basic extension interface.
273
     * 
274
     * @param extensionClass
275
     *            The class of the extension whose decorator is to be returned
276
     * @return The ExtensionDecorator associated with the provided extension,
277
     *         or null if the extension does not exist.
278
     */
279
    public static ExtensionDecorator getDecoratedExtension(Class extensionClass) {
280
        return (ExtensionDecorator) Launcher.getClassesExtensions()
281
        .get(extensionClass);
282
    }
283

    
284
    /**
285
     * Returns an array containing references to all the loaded extensions.
286
     * 
287
     * @return ExtensionDecorator[] An array of ExtensionDecorators (each
288
     *         Decorator contains one extension).
289
     */
290
    public static ExtensionDecorator[] getDecoratedExtensions() {
291
        HashMap map = Launcher.getClassesExtensions();
292
        ExtensionDecorator[] extensions =
293
            (ExtensionDecorator[]) map.values()
294
            .toArray(new ExtensionDecorator[0]);
295
        return extensions;
296
    }
297

    
298
    /**
299
     * Gets an iterator with all the loaded Extensions.
300
     * 
301
     * @return Iterator over the decorated extensions (each member of
302
     *         the iterator is an ExtensionDecorator, which in turn contains
303
     *         one IExtension object).
304
     */
305
    public static Iterator getExtensions() {
306
        return Launcher.getClassesExtensions().values().iterator();
307
    }
308

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

    
337
    /**
338
     * Sets the XML data which should be saved on disk for this plugin. This
339
     * data can be retrieved on following sessions.
340
     * 
341
     * @param The
342
     *            XMLEntity object containing the data to be persisted.
343
     * 
344
     * @see PluginServices.getPersistentXML()
345
     * @see XMLEntity
346
     */
347
    public void setPersistentXML(XMLEntity entity) {
348
        persistentXML = entity;
349
    }
350

    
351
    /**
352
     * Gets the XML data which was saved on previous sessions for this
353
     * plugins.
354
     * 
355
     * @return An XMLEntity object containing the persisted data
356
     */
357
    public XMLEntity getPersistentXML() {
358
        if (persistentXML == null) {
359
            persistentXML = new XMLEntity();
360
        }
361
        return persistentXML;
362
    }
363

    
364
    /**
365
     * A?ade un listener a un popup menu registrado en el config.xml de alg?n
366
     * plugin
367
     * 
368
     * @param name
369
     *            Nombre del men? contextual
370
     * @param c
371
     *            Componente que desplegar? el men? cuando se haga click con el
372
     *            bot?n derecho
373
     * @param listener
374
     *            Listener que se ejecutar? cuando se seleccione cualquier
375
     *            entrada del men?
376
     * 
377
     * @throws RuntimeException
378
     *             Si la interfaz no est? preparada todav?a. S?lo puede darse
379
     *             durante el arranque
380
     */
381
    public void addPopupMenuListener(String name,
382
        Component c,
383
        ActionListener listener) {
384
        MDIFrame frame = Launcher.getFrame();
385

    
386
        if (frame == null) {
387
            throw new RuntimeException("MDIFrame not loaded yet");
388
        }
389

    
390
        frame.addPopupMenuListener(name, c, listener, loader);
391
    }
392

    
393
    /**
394
     * Gets the plugin's root directory.
395
     * 
396
     * @return A File pointing to the plugin's root directory.
397
     */
398
    public File getPluginDirectory() {
399
        return new File(Launcher.getPluginsDir() + File.separator
400
            + getPluginName());
401
    }
402

    
403
    /**
404
     * Runs a background task. The events produced on the main frame will
405
     * be inhibited.
406
     * 
407
     * @param r
408
     *            The task to run.
409
     * 
410
     * @return The Thread on which the task is executed.
411
     */
412
    public static Thread backgroundExecution(Runnable r) {
413
        Thread t = new Thread(new RunnableDecorator(r));
414
        t.start();
415

    
416
        return t;
417
    }
418

    
419
    /**
420
     * Runs a backbround task. This task may be monitored and canceled, and
421
     * does not inhibit any event.
422
     * 
423
     * @param task
424
     *            The task to run.
425
     */
426
    public static void cancelableBackgroundExecution(final IMonitorableTask task) {
427
        final org.gvsig.utils.swing.threads.SwingWorker worker =
428
            new org.gvsig.utils.swing.threads.SwingWorker() {
429

    
430
            public Object construct() {
431
                try {
432
                    task.run();
433
                    return task;
434
                } catch (Exception e) {
435
                    NotificationManager.addError(null, e);
436
                }
437
                return null;
438
            }
439

    
440
            /**
441
             * Called on the event dispatching thread (not on the worker
442
             * thread)
443
             * after the <code>construct</code> method has returned.
444
             */
445
            public void finished() {
446
                task.finished();
447
            }
448
        };
449

    
450
        Component mainFrame = (Component) PluginServices.getMainFrame();
451

    
452
        IProgressMonitorIF progressMonitor = null;
453
        String title = getText(null, "PluginServices.Procesando");
454
        progressMonitor =
455
            new UndefinedProgressMonitor((Frame) mainFrame, title);
456
        progressMonitor.setIndeterminated(!task.isDefined());
457
        progressMonitor.setInitialStep(task.getInitialStep());
458
        progressMonitor.setLastStep(task.getFinishStep());
459
        progressMonitor.setCurrentStep(task.getCurrentStep());
460
        progressMonitor.setMainTitleLabel(task.getStatusMessage());
461
        progressMonitor.setNote(task.getNote());
462
        progressMonitor.open();
463
        int delay = 500;
464
        TaskMonitorTimerListener timerListener =
465
            new TaskMonitorTimerListener(progressMonitor, task);
466
        Timer timer = new Timer(delay, timerListener);
467
        timerListener.setTimer(timer);
468
        timer.start();
469

    
470
        worker.start();
471

    
472
    }
473

    
474
    /**
475
     * Closes the application. Cleanly exits from the application:
476
     * terminates all the extensions, then exits.
477
     * 
478
     */
479
    public static void closeApplication() {
480
        Launcher.closeApplication();
481
    }
482

    
483
    /**
484
     * DOCUMENT ME!
485
     * 
486
     * @author Fernando Gonz?lez Cort?s
487
     */
488
    private static class RunnableDecorator implements Runnable {
489

    
490
        private Runnable r;
491

    
492
        /**
493
         * Crea un nuevo RunnableDecorator.
494
         * 
495
         * @param r
496
         *            DOCUMENT ME!
497
         */
498
        public RunnableDecorator(Runnable r) {
499
            this.r = r;
500
        }
501

    
502
        /**
503
         * @see java.lang.Runnable#run()
504
         */
505
        public void run() {
506
            try {
507
                SwingUtilities.invokeAndWait(new Runnable() {
508

    
509
                    public void run() {
510
                        try {
511
                            r.run();
512
                        } catch (RuntimeException e) {
513
                            NotificationManager.addError(Messages.getString("PluginServices.Bug_en_el_codigo"),
514
                                e);
515
                        } catch (Error e) {
516
                            NotificationManager.addError(Messages.getString("PluginServices.Error_grave_de_la_aplicaci?n"),
517
                                e);
518
                        }
519
                    }
520
                });
521
            } catch (InterruptedException e) {
522
                NotificationManager.addWarning(Messages.getString("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
523
                    e);
524
            } catch (InvocationTargetException e) {
525
                NotificationManager.addWarning(Messages.getString("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
526
                    e);
527
            }
528
        }
529
    }
530

    
531
    /**
532
     * Gets an array containing the application's startup arguments. <br>
533
     * <br>
534
     * Usually: <code>appName plugins-directory [locale] [other args]</code>
535
     * 
536
     * @return the original arguments that Andami received. (app-name
537
     *         plugins-directory, locale, etc)
538
     */
539
    public static String[] getArguments() {
540
        return arguments;
541
    }
542

    
543
    /**
544
     * Replaces the original Andami arguments with the provided arguments.
545
     * 
546
     * @param arguments
547
     *            An array of String, each element of the array
548
     *            represents one
549
     *            argument.
550
     */
551
    public static void setArguments(String[] arguments) {
552
        PluginServices.arguments = arguments;
553
    }
554

    
555
    /**
556
     * Returns the value of a command line named argument. <br>
557
     * <br>
558
     * The argument format is: <br>
559
     * -{argumentName}={argumentValue} <br>
560
     * <br>
561
     * example: <br>
562
     * ' -language=en '
563
     * 
564
     * @return String The value of the argument
565
     */
566
    public static String getArgumentByName(String name) {
567
        for (int i = 2; i < PluginServices.arguments.length; i++) {
568
            int index = PluginServices.arguments[i].indexOf(name + "=");
569
            if (index != -1)
570
                return PluginServices.arguments[i].substring(index
571
                    + name.length() + 1);
572
        }
573
        return null;
574
    }
575

    
576
    /**
577
     * Gets the logger. The logger is used to register important
578
     * events (errors, etc), which are stored on a file which
579
     * can be checked later.
580
     * 
581
     * @return A Logger object.
582
     * @see Logger object from the Log4j library.
583
     * 
584
     */
585
    public static Logger getLogger() {
586
        return logger;
587
    }
588

    
589
    public static IAuthentication getAuthentication() {
590
        return authentication;
591
    }
592

    
593
    public static void setAuthentication(IAuthentication authen) {
594
        authentication = authen;
595
    }
596

    
597
    public static DlgPreferences getDlgPreferences() {
598
        return DlgPreferences.getInstance();
599
    }
600

    
601
    /**
602
     * Stores the provided text data on the clipboard.
603
     * 
604
     * @param data
605
     *            An String containing the data to be stored
606
     *            on the clipboard.
607
     */
608
    public static void putInClipboard(String data) {
609
        StringSelection ss = new StringSelection(data);
610

    
611
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, ss);
612
    }
613

    
614
    /**
615
     * Gets text data from the Clipboard, if available.
616
     * 
617
     * @return An String containing the clipboard's data, or <code>null</code>
618
     *         if the data was not available.
619
     */
620
    public static String getFromClipboard() {
621

    
622
        try {
623
            return (String) Toolkit.getDefaultToolkit()
624
            .getSystemClipboard()
625
            .getContents(null)
626
            .getTransferData(DataFlavor.stringFlavor);
627
        } catch (UnsupportedFlavorException e) {
628
            return null;
629
        } catch (IOException e) {
630
            // TODO Auto-generated catch block
631
            return null;
632
        }
633
    }
634

    
635
    /**
636
     * Gets the ExclusiveUIExtension, an special extension which
637
     * will take
638
     * control over the UI and will decide which extensions may be
639
     * enable/disabled or visible/hidden.
640
     * 
641
     * @return If an ExclusiveUIExtension was set, return this extension.
642
     *         Otherwise, return <code>null</code>.
643
     * 
644
     * @see org.gvsig.andami.Launcher#initializeExclusiveUIExtension()
645
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
646
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
647
     */
648
    public static ExclusiveUIExtension getExclusiveUIExtension() {
649
        return PluginServices.exclusiveUIExtension;
650
    }
651

    
652
    /**
653
     * Sets the ExclusiveUIExtension, an special extension which
654
     * will take
655
     * control over the UI and will decide which extensions may be
656
     * enable/disabled or visible/hidden. <br>
657
     * <br>
658
     * The ExclusiveUIExtension is normally set by the following
659
     * Andami startup argument: <br>
660
     * <br>
661
     * <code>ExclusiveUIExtension=ExtensionName</code>
662
     * 
663
     * @see org.gvsig.andami.Launcher#initializeExclusiveUIExtension()
664
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
665
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
666
     */
667
    public static void setExclusiveUIExtension(ExclusiveUIExtension extension) {
668
        PluginServices.exclusiveUIExtension = extension;
669
    }
670

    
671
    public static void addLoaders(ArrayList classLoaders) {
672
        PluginClassLoader.addLoaders(classLoaders);
673
    }
674

    
675
    public static IconThemeManager getIconThemeManager() {
676
            return ToolsSwingLocator.getIconThemeManager();
677
    }
678

    
679
    public static IconTheme getIconTheme() {
680
        return getIconThemeManager().getCurrent();
681
    }
682

    
683
    /**
684
     * Try to detect if the application is running in a development
685
     * environment. <br>
686
     * This look for <b>.project</b> and <b>.classpath</b> files in the starts
687
     * path of the application.
688
     * 
689
     * @return true if <b>.project</b> and <b>.classpath</b> are in the
690
     *         development path
691
     */
692
    public static boolean runningInDevelopment() {
693
        String andamiPath;
694
        Properties props = System.getProperties();
695

    
696
        try {
697
            try {
698
                andamiPath =
699
                    (new File(Launcher.class.getResource(".").getFile()
700
                        + File.separator + ".." + File.separator + ".."
701
                        + File.separator + ".." + File.separator + "..")).getCanonicalPath();
702
            } catch (IOException e) {
703
                andamiPath =
704
                    (new File(Launcher.class.getResource(".").getFile()
705
                        + File.separator + ".." + File.separator + ".."
706
                        + File.separator + ".." + File.separator + "..")).getAbsolutePath();
707
            }
708
        } catch (Exception e1) {
709
            andamiPath = (String) props.get("user.dir");
710
        }
711

    
712
        File andamiJar = new File(andamiPath + File.separator + "andami.jar");
713
        if (!andamiJar.exists())
714
            return false;
715
        File projectFile = new File(andamiPath + File.separator + ".project");
716
        File classpathFile =
717
            new File(andamiPath + File.separator + ".classpath");
718
        return projectFile.exists() && classpathFile.exists();
719

    
720
    }
721

    
722
    public PluginsManager getManager() {
723
        return PluginsLocator.getManager();
724
    }
725

    
726
    public DynObject getPluginProperties() {
727
        if (this.pluginPersistence == null) {
728
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
729
            DynStruct dynStruct = manager.getDynObjectDefinition(getPluginName());
730
            if ( dynStruct == null) {
731
                File persistenceDefinitionFile =
732
                    new File(getManager().getPluginsDirectory().getAbsolutePath()
733
                        + File.separator + this.getPluginName()
734
                        + File.separator + "plugin-persistence.def");
735
                try {
736
                    dynStruct = manager.addDefinition(DynObject.class,
737
                        this.getPluginName(),
738
                        new FileInputStream(persistenceDefinitionFile),
739
                        this.getClassLoader(),
740
                        null,
741
                        null);
742
                } catch (AddDefinitionException e) {
743
                    throw new PluginPersistenceAddDefinitionException(this.getPluginName());
744
                } catch (FileNotFoundException e) {
745
                    throw new PluginPersistenceNeedDefinitionException(this.getPluginName());
746
                }
747
            }
748

    
749

    
750
                        File persistenceFile = getPluginPersistenceFile();
751
            if (persistenceFile.exists()) {
752
                PersistentState state;
753

    
754
                try {
755
                    state = manager.loadState(new FileInputStream(persistenceFile));
756
                    pluginPersistence = (DynObject) manager.create(state);
757
                } catch (Exception e) {
758
                    logger.error("Can't retrieve persistent values from plugin "+this.getPluginName(), e);
759
                }
760
            }
761
            if (this.pluginPersistence == null) {
762
                this.pluginPersistence =
763
                    ToolsLocator.getDynObjectManager()
764
                    .createDynObject(dynStruct); 
765
            }
766
        }
767
        return pluginPersistence;
768
    }
769

    
770
    public void savePluginProperties() {
771
        if (this.pluginPersistence == null) {
772
            return;
773
        }
774
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
775
                File persistenceFile = getPluginPersistenceFile();
776
        PersistentState state;
777
        FileOutputStream fos;
778
        try {
779
            state = manager.getState(pluginPersistence);
780
            manager.saveState(state, new FileOutputStream(persistenceFile));
781
        } catch (Exception e) {
782
            throw new PluginSaveDataException(this.getPluginName(), e);
783
        }
784

    
785

    
786
    }
787

    
788
        /**
789
         * Returns the plugin persistence file.
790
         * 
791
         * @return the plugin persistence file
792
         */
793
        private File getPluginPersistenceFile() {
794
                return new File(getPluginHomeFolder(), "plugin-persistence.dat");
795
        }
796

    
797
        /**
798
         * Returns the folder where the plugin stores its resources. That folder
799
         * will be usually a subfolder into the application folder in the user home
800
         * folder.
801
         * 
802
         * @return the folder where the plugin stores its resources
803
         */
804
        public File getPluginHomeFolder() {
805
                File persistenceFolder = new File(Launcher.getAppHomeDir()
806
                                + File.separator + "plugins" + File.separator
807
                                + this.getPluginName());
808

    
809
                if (!persistenceFolder.exists()) {
810
                        persistenceFolder.mkdirs();
811
                }
812

    
813
                return persistenceFolder;
814
        }
815

    
816
    public class PluginPersistenceNeedDefinitionException extends
817
    BaseRuntimeException {
818

    
819
        /**
820
         * 
821
         */
822
        private static final long serialVersionUID = -2036279527440882712L;
823

    
824
        PluginPersistenceNeedDefinitionException(String name) {
825
            super("Can't load persistence definition of plugin %(name).",
826
                "_cant_load_persistence_definition_of_plugin_XnameX",
827
                serialVersionUID);
828
            setValue("name", name);
829
        }
830
    }
831

    
832
    public class PluginPersistenceAddDefinitionException extends
833
    BaseRuntimeException {
834

    
835
        /**
836
         * 
837
         */
838
        private static final long serialVersionUID = 2227722796640780361L;
839

    
840
        PluginPersistenceAddDefinitionException(String name) {
841
            super("Can't add persistence definition of plugin %(name).",
842
                "_cant_add_persistence_definition_of_plugin_XnameX",
843
                serialVersionUID);
844
            setValue("name", name);
845
        }
846
    }
847

    
848
    public class PluginLoadDataException extends
849
    BaseRuntimeException {
850

    
851
        /**
852
         * 
853
         */
854
        private static final long serialVersionUID = 1168749231143949111L;
855

    
856
        PluginLoadDataException(String name) {
857
            super("Can't load data of plugin %(name).",
858
                "_cant_load_data_of_plugin_XnameX",
859
                serialVersionUID);
860
            setValue("name", name);
861
        }
862
    }
863

    
864
    public class PluginSaveDataException extends
865
    BaseRuntimeException {
866

    
867
        /**
868
         * 
869
         */
870
        private static final long serialVersionUID = 4893241183911774542L;
871
        private final static String MESSAGE_FORMAT = "Can't save data of plugin %(name).";
872
        private final static String MESSAGE_KEY = "_cant_save_data_of_plugin_XnameX";
873

    
874
        PluginSaveDataException(String name) {
875
            super(MESSAGE_FORMAT,
876
                MESSAGE_KEY,
877
                serialVersionUID);
878
            setValue("name", name);
879
        }
880

    
881
        public PluginSaveDataException(String name, Throwable cause) {
882
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
883
            setValue("name", name);
884

    
885
        }
886
    }
887
    
888
    @Override
889
    public String toString() {
890
        return super.toString()+" "+this.getPluginName();
891
    }
892
}