Statistics
| Revision:

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

History | View | Annotate | Download (30.1 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
     */
135
    public String getText(String key) {
136
        if (key == null)
137
            return null;
138
        String translation = org.gvsig.i18n.Messages.getText(key, false);
139
        if (translation != null)
140
            return translation;
141
        else {
142
            logger.debug("Can't find translation for ''{}'' in plugin ''{}''.",
143
                key,
144
                getPluginName());
145
            return key;
146
        }
147
    }
148

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
382
        frame.addPopupMenuListener(name, c, listener, loader);
383
    }
384

    
385
    /**
386
     * Gets the plugin's root directory.
387
     * 
388
     * @return A File pointing to the plugin's root directory.
389
     */
390
    public File getPluginDirectory() {
391
        return new File(Launcher.getPluginsDir() + File.separator
392
            + getPluginName());
393
    }
394

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

    
408
        return t;
409
    }
410

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

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

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

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

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

    
462
        worker.start();
463

    
464
    }
465

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

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

    
482
        private Runnable r;
483

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

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

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

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

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

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

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

    
584
    public static DlgPreferences getDlgPreferences() {
585
        return DlgPreferences.getInstance();
586
    }
587

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

    
598
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, ss);
599
    }
600

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

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

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

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

    
658
    public static void addLoaders(ArrayList classLoaders) {
659
        PluginClassLoader.addLoaders(classLoaders);
660
    }
661

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

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

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

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

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

    
713
    }
714

    
715
    public PluginsManager getManager() {
716
        return PluginsLocator.getManager();
717
    }
718

    
719
    private String[] getAllPluginNames() {
720
            String[] names = new String[this.alternativeNames.length+1];
721
            names[0] = this.getPluginName();
722
            for( int n=0; n<this.alternativeNames.length; n++ ) {
723
                names[n+1] = this.alternativeNames[n];
724
            }
725
            return names;
726
    }
727
    
728
    public DynObject getPluginProperties() {
729
        if (this.pluginPersistence == null) {
730
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
731
            DynStruct dynStruct = manager.getDynObjectDefinition(getPluginName());
732
            if ( dynStruct == null) {
733
                File persistenceDefinitionFile =
734
                    new File(getManager().getPluginsDirectory().getAbsolutePath()
735
                        + File.separator + this.getPluginName()
736
                        + File.separator + "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

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

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

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

    
802

    
803
    }
804

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

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

    
826
                if (!persistenceFolder.exists()) {
827
                        persistenceFolder.mkdirs();
828
                }
829

    
830
                return persistenceFolder;
831
        }
832

    
833
    public class PluginPersistenceNeedDefinitionException extends
834
    BaseRuntimeException {
835

    
836
        /**
837
         * 
838
         */
839
        private static final long serialVersionUID = -2036279527440882712L;
840

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

    
850
    public class PluginPersistenceAddDefinitionException extends
851
    BaseRuntimeException {
852

    
853
        /**
854
         * 
855
         */
856
        private static final long serialVersionUID = 2227722796640780361L;
857

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

    
867
    public class PluginLoadDataException extends
868
    BaseRuntimeException {
869

    
870
        /**
871
         * 
872
         */
873
        private static final long serialVersionUID = 1168749231143949111L;
874

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

    
883
    public class PluginSaveDataException extends
884
    BaseRuntimeException {
885

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

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

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

    
904
        }
905
    }
906
    
907
    @Override
908
    public String toString() {
909
        return super.toString()+" "+this.getPluginName();
910
    }
911
    
912
    public void addDependencyWithPlugin(PluginServices otherPlugin) {
913
        this.getClassLoader().addPluginClassLoader(otherPlugin.getClassLoader());
914
    }
915
}