Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.framework / org.gvsig.andami / src / main / java / org / gvsig / andami / PluginServices.java @ 43328

History | View | Annotate | Download (30.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.andami;
25

    
26
import java.awt.Component;
27
import java.awt.Frame;
28
import java.awt.KeyEventDispatcher;
29
import java.awt.Toolkit;
30
import java.awt.datatransfer.DataFlavor;
31
import java.awt.datatransfer.StringSelection;
32
import java.awt.datatransfer.UnsupportedFlavorException;
33
import java.awt.event.ActionListener;
34
import java.io.File;
35
import java.io.FileInputStream;
36
import java.io.FileNotFoundException;
37
import java.io.FileOutputStream;
38
import java.io.IOException;
39
import java.lang.reflect.InvocationTargetException;
40
import java.util.ArrayList;
41
import java.util.Arrays;
42
import java.util.HashMap;
43
import java.util.Iterator;
44
import java.util.Properties;
45

    
46
import javax.swing.JOptionPane;
47
import javax.swing.KeyStroke;
48
import javax.swing.SwingUtilities;
49
import javax.swing.Timer;
50

    
51
import org.gvsig.andami.messages.NotificationManager;
52
import org.gvsig.andami.plugins.ExclusiveUIExtension;
53
import org.gvsig.andami.plugins.ExtensionDecorator;
54
import org.gvsig.andami.plugins.IExtension;
55
import org.gvsig.andami.plugins.PluginClassLoader;
56
import org.gvsig.andami.preferences.DlgPreferences;
57
import org.gvsig.andami.ui.mdiFrame.MDIFrame;
58
import org.gvsig.andami.ui.mdiFrame.MainFrame;
59
import org.gvsig.andami.ui.mdiManager.MDIManager;
60
import org.gvsig.i18n.Messages;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.dynobject.DynObject;
63
import org.gvsig.tools.dynobject.DynStruct;
64
import org.gvsig.tools.exception.BaseRuntimeException;
65
import org.gvsig.tools.persistence.PersistenceManager;
66
import org.gvsig.tools.persistence.PersistentState;
67
import org.gvsig.tools.persistence.exception.AddDefinitionException;
68
import org.gvsig.tools.swing.api.ToolsSwingLocator;
69
import org.gvsig.tools.swing.icontheme.IconTheme;
70
import org.gvsig.tools.swing.icontheme.IconThemeManager;
71
import org.gvsig.utils.XMLEntity;
72
import org.gvsig.utils.swing.threads.IMonitorableTask;
73
import org.gvsig.utils.swing.threads.IProgressMonitorIF;
74
import org.gvsig.utils.swing.threads.TaskMonitorTimerListener;
75
import org.gvsig.utils.swing.threads.UndefinedProgressMonitor;
76
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
78

    
79
/**
80
 * Provides services to Plugins. Each plugin has an associated PluginServices
81
 * object, which provides specific services. Main of them: translations,
82
 * logging, access to plugin's resources, background tasks, clipboard access
83
 * and data persistence.
84
 * 
85
 * @author Fernando Gonz�lez Cort�s
86
 */
87
public class PluginServices {
88

    
89
    private static Logger logger =
90
        LoggerFactory.getLogger(PluginServices.class);
91

    
92
    private static String[] arguments;
93

    
94
    private static ExclusiveUIExtension exclusiveUIExtension = null;
95

    
96
    private PluginClassLoader loader;
97

    
98
    private XMLEntity persistentXML;
99

    
100
    private DynObject pluginPersistence = null;
101

    
102
    private String[] alternativeNames = null;
103
    /**
104
     * Creates a new PluginServices objetct.
105
     * 
106
     * @param loader
107
     *            The Plugin's ClassLoader.
108
     */
109
    public PluginServices(PluginClassLoader loader) {
110
        this.loader = loader;
111
    }
112

    
113
    public PluginServices(PluginClassLoader loader, String[] alternativeNames) {
114
            this(loader);
115
        this.alternativeNames = alternativeNames;
116
    }
117

    
118
    public String[] getAlternativeNames() {
119
            return this.alternativeNames;
120
    }
121
    
122
    /**
123
     * Returns the message in the current's locale language
124
     * corresponding to the provided translation key.
125
     * The key-message pairs are obtained from the plugin's
126
     * translation files (text_xx.properties files).
127
     * 
128
     * @param key
129
     *            Translation key whose associated message is to be obtained
130
     * 
131
     * @return The message associated with the provided key, in one of the
132
     *         current locale languages, or the key if the translation is not
133
     *         found.
134
     * @deprecated use I18NManager
135
     */
136
    public String getText(String key) {
137
        if (key == null)
138
            return null;
139
        String translation = org.gvsig.i18n.Messages.getText(key, false);
140
        if (translation != null)
141
            return translation;
142
        else {
143
            logger.debug("Can't find translation for ''{}'' in plugin ''{}''.",
144
                key,
145
                getPluginName());
146
            return key;
147
        }
148
    }
149

    
150
    /**
151
     * Gets the plugin's classloader.
152
     * 
153
     * @return Returns the loader.
154
     */
155
    public PluginClassLoader getClassLoader() {
156
        return loader;
157
    }
158

    
159
    /**
160
     * Gets the plugin's name
161
     * 
162
     * @return The plugin's name
163
     */
164
    public String getPluginName() {
165
        return loader.getPluginName();
166
    }
167

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

    
203
    /**
204
     * Gets a reference to the PluginServices object associated with the
205
     * provided plugin.
206
     * 
207
     * @param pluginName
208
     *            Plugin's name whose services are going to be used
209
     * 
210
     * @return The PluginServices object associated with the provided plugin.
211
     */
212
    public static PluginServices getPluginServices(String pluginName) {
213
        return Launcher.getPluginServices(pluginName);
214
    }
215

    
216
    /**
217
     * Gets the window manager (MDIManager).
218
     * 
219
     * @return A reference to the window manager (MDIManager).
220
     */
221
    public static MDIManager getMDIManager() {
222
        return Launcher.getFrame().getMDIManager();
223
    }
224

    
225
    /**
226
     * Gets the application's main frame.
227
     * 
228
     * @return A reference to the application's main window
229
     */
230
    public static MainFrame getMainFrame() {
231
        return Launcher.getFrame();
232
    }
233

    
234
    public static void registerKeyStroke(KeyStroke key, KeyEventDispatcher a) {
235
        GlobalKeyEventDispatcher.getInstance().registerKeyStroke(key, a);
236
    }
237

    
238
    public static void unRegisterKeyStroke(KeyStroke key) {
239
        GlobalKeyEventDispatcher.getInstance().removeKeyStrokeBinding(key);
240
    }
241

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

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

    
277
    /**
278
     * Returns an array containing references to all the loaded extensions.
279
     * 
280
     * @return ExtensionDecorator[] An array of ExtensionDecorators (each
281
     *         Decorator contains one extension).
282
     */
283
    public static ExtensionDecorator[] getDecoratedExtensions() {
284
        HashMap map = Launcher.getClassesExtensions();
285
        ExtensionDecorator[] extensions =
286
            (ExtensionDecorator[]) map.values()
287
            .toArray(new ExtensionDecorator[0]);
288
        return extensions;
289
    }
290

    
291
    /**
292
     * Gets an iterator with all the loaded Extensions.
293
     * 
294
     * @return Iterator over the decorated extensions (each member of
295
     *         the iterator is an ExtensionDecorator, which in turn contains
296
     *         one IExtension object).
297
     */
298
    public static Iterator getExtensions() {
299
        return Launcher.getClassesExtensions().values().iterator();
300
    }
301

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

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

    
345
    /**
346
     * Gets the XML data which was saved on previous sessions for this
347
     * plugins.
348
     * 
349
     * @return An XMLEntity object containing the persisted data
350
     */
351
    public XMLEntity getPersistentXML() {
352
        if (persistentXML == null) {
353
            persistentXML = new XMLEntity();
354
        }
355
        return persistentXML;
356
    }
357

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

    
380
        if (frame == null) {
381
            throw new RuntimeException("MDIFrame not loaded yet");
382
        }
383

    
384
        frame.addPopupMenuListener(name, c, listener, loader);
385
    }
386

    
387
    /**
388
     * Gets the plugin's root directory.
389
     * 
390
     * @return A File pointing to the plugin's root directory.
391
     */
392
    public File getPluginDirectory() {
393
        return Launcher.getPluginFolder(this.getPluginName());
394
    }
395

    
396
    /**
397
     * Runs a background task. The events produced on the main frame will
398
     * be inhibited.
399
     * 
400
     * @param r
401
     *            The task to run.
402
     * 
403
     * @return The Thread on which the task is executed.
404
     */
405
    public static Thread backgroundExecution(Runnable r) {
406
        Thread t = new Thread(new RunnableDecorator(r));
407
        t.start();
408

    
409
        return t;
410
    }
411

    
412
    /**
413
     * Runs a backbround task. This task may be monitored and canceled, and
414
     * does not inhibit any event.
415
     * 
416
     * @param task
417
     *            The task to run.
418
     */
419
    public static void cancelableBackgroundExecution(final IMonitorableTask task) {
420
        final org.gvsig.utils.swing.threads.SwingWorker worker =
421
            new org.gvsig.utils.swing.threads.SwingWorker() {
422

    
423
            public Object construct() {
424
                try {
425
                    task.run();
426
                    return task;
427
                } catch (Exception e) {
428
                    NotificationManager.addError(null, e);
429
                }
430
                return null;
431
            }
432

    
433
            /**
434
             * Called on the event dispatching thread (not on the worker
435
             * thread)
436
             * after the <code>construct</code> method has returned.
437
             */
438
            public void finished() {
439
                task.finished();
440
            }
441
        };
442

    
443
        Component mainFrame = (Component) PluginServices.getMainFrame();
444

    
445
        IProgressMonitorIF progressMonitor = null;
446
        String title = getText(null, "PluginServices.Procesando");
447
        progressMonitor =
448
            new UndefinedProgressMonitor((Frame) mainFrame, title);
449
        progressMonitor.setIndeterminated(!task.isDefined());
450
        progressMonitor.setInitialStep(task.getInitialStep());
451
        progressMonitor.setLastStep(task.getFinishStep());
452
        progressMonitor.setCurrentStep(task.getCurrentStep());
453
        progressMonitor.setMainTitleLabel(task.getStatusMessage());
454
        progressMonitor.setNote(task.getNote());
455
        progressMonitor.open();
456
        int delay = 500;
457
        TaskMonitorTimerListener timerListener =
458
            new TaskMonitorTimerListener(progressMonitor, task);
459
        Timer timer = new Timer(delay, timerListener);
460
        timerListener.setTimer(timer);
461
        timer.start();
462

    
463
        worker.start();
464

    
465
    }
466

    
467
    /**
468
     * Closes the application. Cleanly exits from the application:
469
     * terminates all the extensions, then exits.
470
     * 
471
     */
472
    public static void closeApplication() {
473
        Launcher.closeApplication();
474
    }
475

    
476
    /**
477
     * DOCUMENT ME!
478
     * 
479
     * @author Fernando Gonz�lez Cort�s
480
     */
481
    private static class RunnableDecorator implements Runnable {
482

    
483
        private Runnable r;
484

    
485
        /**
486
         * Crea un nuevo RunnableDecorator.
487
         * 
488
         * @param r
489
         *            DOCUMENT ME!
490
         */
491
        public RunnableDecorator(Runnable r) {
492
            this.r = r;
493
        }
494

    
495
        /**
496
         * @see java.lang.Runnable#run()
497
         */
498
        public void run() {
499
            try {
500
                SwingUtilities.invokeAndWait(new Runnable() {
501

    
502
                    public void run() {
503
                        try {
504
                            r.run();
505
                        } catch (RuntimeException e) {
506
                            NotificationManager.addError(Messages.getText("PluginServices.Bug_en_el_codigo"),
507
                                e);
508
                        } catch (Error e) {
509
                            NotificationManager.addError(Messages.getText("PluginServices.Error_grave_de_la_aplicaci�n"),
510
                                e);
511
                        }
512
                    }
513
                });
514
            } catch (InterruptedException e) {
515
                NotificationManager.addWarning(Messages.getText("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
516
                    e);
517
            } catch (InvocationTargetException e) {
518
                NotificationManager.addWarning(Messages.getText("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
519
                    e);
520
            }
521
        }
522
    }
523

    
524
    /**
525
     * Gets an array containing the application's startup arguments. <br>
526
     * <br>
527
     * Usually: <code>appName plugins-directory [locale] [other args]</code>
528
     * 
529
     * @return the original arguments that Andami received. (app-name
530
     *         plugins-directory, locale, etc)
531
     */
532
    public static String[] getArguments() {
533
        return arguments;
534
    }
535

    
536
    /**
537
     * Replaces the original Andami arguments with the provided arguments.
538
     * 
539
     * @param arguments
540
     *            An array of String, each element of the array
541
     *            represents one
542
     *            argument.
543
     */
544
    public static void setArguments(String[] arguments) {
545
        PluginServices.arguments = arguments;
546
    }
547

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

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

    
586
    public static DlgPreferences getDlgPreferences() {
587
        return DlgPreferences.getInstance();
588
    }
589

    
590
    /**
591
     * Stores the provided text data on the clipboard.
592
     * 
593
     * @param data
594
     *            An String containing the data to be stored
595
     *            on the clipboard.
596
     */
597
    public static void putInClipboard(String data) {
598
        StringSelection ss = new StringSelection(data);
599

    
600
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, ss);
601
    }
602

    
603
    /**
604
     * Gets text data from the Clipboard, if available.
605
     * 
606
     * @return An String containing the clipboard's data, or <code>null</code>
607
     *         if the data was not available.
608
     */
609
    public static String getFromClipboard() {
610

    
611
        try {
612
            return (String) Toolkit.getDefaultToolkit()
613
            .getSystemClipboard()
614
            .getContents(null)
615
            .getTransferData(DataFlavor.stringFlavor);
616
        } catch (UnsupportedFlavorException e) {
617
            return null;
618
        } catch (IOException e) {
619
            // TODO Auto-generated catch block
620
            return null;
621
        }
622
    }
623

    
624
    /**
625
     * Gets the ExclusiveUIExtension, an special extension which
626
     * will take
627
     * control over the UI and will decide which extensions may be
628
     * enable/disabled or visible/hidden.
629
     * 
630
     * @return If an ExclusiveUIExtension was set, return this extension.
631
     *         Otherwise, return <code>null</code>.
632
     * 
633
     * @see org.gvsig.andami.Launcher#initializeExclusiveUIExtension()
634
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
635
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
636
     */
637
    public static ExclusiveUIExtension getExclusiveUIExtension() {
638
        return PluginServices.exclusiveUIExtension;
639
    }
640

    
641
    /**
642
     * Sets the ExclusiveUIExtension, an special extension which
643
     * will take
644
     * control over the UI and will decide which extensions may be
645
     * enable/disabled or visible/hidden. <br>
646
     * <br>
647
     * The ExclusiveUIExtension is normally set by the following
648
     * Andami startup argument: <br>
649
     * <br>
650
     * <code>ExclusiveUIExtension=ExtensionName</code>
651
     * 
652
     * @see org.gvsig.andami.Launcher#initializeExclusiveUIExtension()
653
     * @see org.gvsig.andami.plugins.IExtension#isEnabled(IExtension extension)
654
     * @see org.gvsig.andami.plugins.IExtension#isVisible(IExtension extension)
655
     */
656
    public static void setExclusiveUIExtension(ExclusiveUIExtension extension) {
657
        PluginServices.exclusiveUIExtension = extension;
658
    }
659

    
660
    public static void addLoaders(ArrayList classLoaders) {
661
        PluginClassLoader.addLoaders(classLoaders);
662
    }
663

    
664
    /**
665
     * @deprecated use ToolsSwingLocator.getIconThemeManager()
666
     */
667
    public static IconThemeManager getIconThemeManager() {
668
            return ToolsSwingLocator.getIconThemeManager();
669
    }
670

    
671
    /**
672
     * @deprecated use  ToolsSwingLocator.getIconThemeManager().getCurrent()
673
     */
674
    public static IconTheme getIconTheme() {
675
            return getIconThemeManager().getCurrent(); 
676
    }
677

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

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

    
707
        File andamiJar = new File(andamiPath + File.separator + "andami.jar");
708
        if (!andamiJar.exists())
709
            return false;
710
        File projectFile = new File(andamiPath + File.separator + ".project");
711
        File classpathFile =
712
            new File(andamiPath + File.separator + ".classpath");
713
        return projectFile.exists() && classpathFile.exists();
714

    
715
    }
716

    
717
    public PluginsManager getManager() {
718
        return PluginsLocator.getManager();
719
    }
720

    
721
    private String[] getAllPluginNames() {
722
            String[] names = new String[this.alternativeNames.length+1];
723
            names[0] = this.getPluginName();
724
            for( int n=0; n<this.alternativeNames.length; n++ ) {
725
                names[n+1] = this.alternativeNames[n];
726
            }
727
            return names;
728
    }
729
    
730
    public DynObject getPluginProperties() {
731
        if (this.pluginPersistence == null) {
732
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
733
            DynStruct dynStruct = manager.getDynObjectDefinition(getPluginName());
734
            if ( dynStruct == null) {
735
                File persistenceDefinitionFile =
736
                    new File(this.getPluginDirectory(), "plugin-persistence.def");
737
                String[] names = getAllPluginNames(); 
738
                for( int i=0; i<names.length ; i++ ) {
739
                        try {
740
                            dynStruct = manager.addDefinition(DynObject.class,
741
                                names[i],
742
                                new FileInputStream(persistenceDefinitionFile),
743
                                this.getClassLoader(),
744
                                null,
745
                                null);
746
                            break;
747
                        } catch (FileNotFoundException e) {
748
                            throw new PluginPersistenceNeedDefinitionException(this.getPluginName(), e);
749
                        } catch (AddDefinitionException e) {
750
                                if( i+1 >= names.length ) { // Si ya no hay mas nombres peta
751
                                        throw new PluginPersistenceAddDefinitionException(this.getPluginName(), e);
752
                                }
753
                        }
754
                }
755
            }
756

    
757
            File persistenceFile = getPluginPersistenceFile();
758
            if (persistenceFile.exists()) {
759
                PersistentState state;
760

    
761
                try {
762
                    state = manager.loadState(new FileInputStream(persistenceFile));
763
                    pluginPersistence = (DynObject) manager.create(state);
764
                } catch (Throwable e) {
765
                        
766
                    logger.info("Can't retrieve persistent values from plugin "+
767
                    getPluginName(), e);
768
                    showMessageDialogDelayed(Messages.getText("_Unable_to_read_persistence_for_plugin")
769
                                    + ": " + getPluginName() + "\n" +
770
                                    Messages.getText("_Perhaps_saved_data_refers_to_missing_plugin"),
771
                                    Messages.getText("_Persistence"),
772
                                    JOptionPane.WARNING_MESSAGE);
773
                }
774
            }
775
            if (this.pluginPersistence == null) {
776
                logger.info("Creating default values for plugin persistence ("+this.getPluginName()+").");
777
                this.pluginPersistence =
778
                    ToolsLocator.getDynObjectManager()
779
                    .createDynObject(dynStruct); 
780
            }
781
        }
782
        return pluginPersistence;
783
    }
784

    
785
    private void showMessageDialogDelayed(final String msg, final String title, final int type) {
786
        PluginsManager pluginManger = PluginsLocator.getManager();
787
        pluginManger.addStartupTask("Persistence_"+getPluginName(), new Runnable() {
788
           public void run() {
789
                JOptionPane.showMessageDialog(
790
                                (Component) PluginServices.getMainFrame(),
791
                                msg,
792
                                title,
793
                                type);
794
                    }
795
        }, true, 100);
796
    }
797
    
798
    public void savePluginProperties() {
799
        if (this.pluginPersistence == null) {
800
            return;
801
        }
802
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
803
                File persistenceFile = getPluginPersistenceFile();
804
        PersistentState state;
805
        FileOutputStream fos;
806
        try {
807
            state = manager.getState(pluginPersistence);
808
            manager.saveState(state, new FileOutputStream(persistenceFile));
809
        } catch (Exception e) {
810
            throw new PluginSaveDataException(this.getPluginName(), e);
811
        }
812

    
813

    
814
    }
815

    
816
        /**
817
         * Returns the plugin persistence file.
818
         * 
819
         * @return the plugin persistence file
820
         */
821
        private File getPluginPersistenceFile() {
822
                return new File(getPluginHomeFolder(), "plugin-persistence.dat");
823
        }
824

    
825
        /**
826
         * Returns the folder where the plugin stores its resources. That folder
827
         * will be usually a subfolder into the application folder in the user home
828
         * folder.
829
         * 
830
         * @return the folder where the plugin stores its resources
831
         */
832
        public File getPluginHomeFolder() {
833
                File persistenceFolder = new File(Launcher.getAppHomeDir()
834
                                + File.separator + "plugins" + File.separator
835
                                + this.getPluginName());
836

    
837
                if (!persistenceFolder.exists()) {
838
                        persistenceFolder.mkdirs();
839
                }
840

    
841
                return persistenceFolder;
842
        }
843

    
844
    public class PluginPersistenceNeedDefinitionException extends
845
    BaseRuntimeException {
846

    
847
        /**
848
         * 
849
         */
850
        private static final long serialVersionUID = -2036279527440882712L;
851

    
852
        PluginPersistenceNeedDefinitionException(String name, Throwable cause) {
853
            super("Can't load persistence definition of plugin %(name).",
854
                "_cant_load_persistence_definition_of_plugin_XnameX",
855
                serialVersionUID);
856
            initCause(cause);
857
            setValue("name", name);
858
        }
859
    }
860

    
861
    public class PluginPersistenceAddDefinitionException extends
862
    BaseRuntimeException {
863

    
864
        /**
865
         * 
866
         */
867
        private static final long serialVersionUID = 2227722796640780361L;
868

    
869
        PluginPersistenceAddDefinitionException(String name, Throwable cause) {
870
            super("Can't add persistence definition of plugin %(name).",
871
                "_cant_add_persistence_definition_of_plugin_XnameX",
872
                serialVersionUID);
873
            this.initCause(cause);
874
            setValue("name", name);
875
        }
876
    }
877

    
878
    public class PluginLoadDataException extends
879
    BaseRuntimeException {
880

    
881
        /**
882
         * 
883
         */
884
        private static final long serialVersionUID = 1168749231143949111L;
885

    
886
        PluginLoadDataException(String name) {
887
            super("Can't load data of plugin %(name).",
888
                "_cant_load_data_of_plugin_XnameX",
889
                serialVersionUID);
890
            setValue("name", name);
891
        }
892
    }
893

    
894
    public class PluginSaveDataException extends
895
    BaseRuntimeException {
896

    
897
        /**
898
         * 
899
         */
900
        private static final long serialVersionUID = 4893241183911774542L;
901
        private final static String MESSAGE_FORMAT = "Can't save data of plugin %(name).";
902
        private final static String MESSAGE_KEY = "_cant_save_data_of_plugin_XnameX";
903

    
904
        PluginSaveDataException(String name) {
905
            super(MESSAGE_FORMAT,
906
                MESSAGE_KEY,
907
                serialVersionUID);
908
            setValue("name", name);
909
        }
910

    
911
        public PluginSaveDataException(String name, Throwable cause) {
912
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
913
            setValue("name", name);
914

    
915
        }
916
    }
917
    
918
    @Override
919
    public String toString() {
920
        return super.toString()+" "+this.getPluginName();
921
    }
922
    
923
    public void addDependencyWithPlugin(PluginServices otherPlugin) {
924
        if( otherPlugin==null ) {
925
            return;
926
        }
927
        this.getClassLoader().addPluginClassLoader(otherPlugin.getClassLoader());
928
    }
929
}