Statistics
| Revision:

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

History | View | Annotate | Download (30.4 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.authentication.IAuthentication;
52
// import org.gvsig.andami.messages.Messages;
53
import org.gvsig.andami.messages.NotificationManager;
54
import org.gvsig.andami.plugins.ExclusiveUIExtension;
55
import org.gvsig.andami.plugins.ExtensionDecorator;
56
import org.gvsig.andami.plugins.IExtension;
57
import org.gvsig.andami.plugins.PluginClassLoader;
58
import org.gvsig.andami.preferences.DlgPreferences;
59
import org.gvsig.andami.ui.mdiFrame.MDIFrame;
60
import org.gvsig.andami.ui.mdiFrame.MainFrame;
61
import org.gvsig.andami.ui.mdiManager.MDIManager;
62
import org.gvsig.i18n.Messages;
63
import org.gvsig.tools.ToolsLocator;
64
import org.gvsig.tools.dynobject.DynObject;
65
import org.gvsig.tools.dynobject.DynStruct;
66
import org.gvsig.tools.exception.BaseRuntimeException;
67
import org.gvsig.tools.persistence.PersistenceManager;
68
import org.gvsig.tools.persistence.PersistentState;
69
import org.gvsig.tools.persistence.exception.AddDefinitionException;
70
import org.gvsig.tools.swing.api.ToolsSwingLocator;
71
import org.gvsig.tools.swing.icontheme.IconTheme;
72
import org.gvsig.tools.swing.icontheme.IconThemeManager;
73
import org.gvsig.utils.XMLEntity;
74
import org.gvsig.utils.swing.threads.IMonitorableTask;
75
import org.gvsig.utils.swing.threads.IProgressMonitorIF;
76
import org.gvsig.utils.swing.threads.TaskMonitorTimerListener;
77
import org.gvsig.utils.swing.threads.UndefinedProgressMonitor;
78
import org.slf4j.Logger;
79
import org.slf4j.LoggerFactory;
80

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

    
91
    private static Logger logger =
92
        LoggerFactory.getLogger(PluginServices.class);
93

    
94
    private static String[] arguments;
95

    
96
    private static IAuthentication authentication;
97

    
98
    private static ExclusiveUIExtension exclusiveUIExtension = null;
99

    
100
    private PluginClassLoader loader;
101

    
102
    private XMLEntity persistentXML;
103

    
104
    private DynObject pluginPersistence = null;
105

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

    
117
    public PluginServices(PluginClassLoader loader, String[] alternativeNames) {
118
            this(loader);
119
        this.alternativeNames = alternativeNames;
120
    }
121

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

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

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

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

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

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

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

    
237
    public static void registerKeyStroke(KeyStroke key, KeyEventDispatcher a) {
238
        GlobalKeyEventDispatcher.getInstance().registerKeyStroke(key, a);
239
    }
240

    
241
    public static void unRegisterKeyStroke(KeyStroke key) {
242
        GlobalKeyEventDispatcher.getInstance().removeKeyStrokeBinding(key);
243
    }
244

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

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

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

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

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

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

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

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

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

    
386
        frame.addPopupMenuListener(name, c, listener, loader);
387
    }
388

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

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

    
412
        return t;
413
    }
414

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

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

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

    
446
        Component mainFrame = (Component) PluginServices.getMainFrame();
447

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

    
466
        worker.start();
467

    
468
    }
469

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

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

    
486
        private Runnable r;
487

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

    
498
        /**
499
         * @see java.lang.Runnable#run()
500
         */
501
        public void run() {
502
            try {
503
                SwingUtilities.invokeAndWait(new Runnable() {
504

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
674
    /**
675
     * @deprecated use ToolsSwingLocator.getIconThemeManager()
676
     */
677
    public static IconThemeManager getIconThemeManager() {
678
            return ToolsSwingLocator.getIconThemeManager();
679
    }
680

    
681
    /**
682
     * @deprecated use  ToolsSwingLocator.getIconThemeManager().getCurrent()
683
     */
684
    public static IconTheme getIconTheme() {
685
            return getIconThemeManager().getCurrent(); 
686
    }
687

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

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

    
717
        File andamiJar = new File(andamiPath + File.separator + "andami.jar");
718
        if (!andamiJar.exists())
719
            return false;
720
        File projectFile = new File(andamiPath + File.separator + ".project");
721
        File classpathFile =
722
            new File(andamiPath + File.separator + ".classpath");
723
        return projectFile.exists() && classpathFile.exists();
724

    
725
    }
726

    
727
    public PluginsManager getManager() {
728
        return PluginsLocator.getManager();
729
    }
730

    
731
    private String[] getAllPluginNames() {
732
            String[] names = new String[this.alternativeNames.length+1];
733
            names[0] = this.getPluginName();
734
            for( int n=0; n<this.alternativeNames.length; n++ ) {
735
                names[n+1] = this.alternativeNames[n];
736
            }
737
            return names;
738
    }
739
    
740
    public DynObject getPluginProperties() {
741
        if (this.pluginPersistence == null) {
742
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
743
            DynStruct dynStruct = manager.getDynObjectDefinition(getPluginName());
744
            if ( dynStruct == null) {
745
                File persistenceDefinitionFile =
746
                    new File(getManager().getPluginsDirectory().getAbsolutePath()
747
                        + File.separator + this.getPluginName()
748
                        + File.separator + "plugin-persistence.def");
749
                String[] names = getAllPluginNames(); 
750
                for( int i=0; i<names.length ; i++ ) {
751
                        try {
752
                            dynStruct = manager.addDefinition(DynObject.class,
753
                                names[i],
754
                                new FileInputStream(persistenceDefinitionFile),
755
                                this.getClassLoader(),
756
                                null,
757
                                null);
758
                            break;
759
                        } catch (FileNotFoundException e) {
760
                            throw new PluginPersistenceNeedDefinitionException(this.getPluginName(), e);
761
                        } catch (AddDefinitionException e) {
762
                                if( i+1 >= names.length ) { // Si ya no hay mas nombres peta
763
                                        throw new PluginPersistenceAddDefinitionException(this.getPluginName(), e);
764
                                }
765
                        }
766
                }
767
            }
768

    
769

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

    
774
                try {
775
                    state = manager.loadState(new FileInputStream(persistenceFile));
776
                    pluginPersistence = (DynObject) manager.create(state);
777
                } catch (Exception e) {
778
                        
779
                    logger.info("Can't retrieve persistent values from plugin "+
780
                    getPluginName(), e);
781
                        JOptionPane.showMessageDialog(
782
                                        (Component) PluginServices.getMainFrame(),
783
                                        Messages.getText("_Unable_to_read_persistence_for_plugin")
784
                                        + ": " + getPluginName() + "\n" +
785
                                        Messages.getText("_Perhaps_saved_data_refers_to_missing_plugin"),
786
                                        Messages.getText("_Persistence"),
787
                                        JOptionPane.WARNING_MESSAGE);
788
                }
789
            }
790
            if (this.pluginPersistence == null) {
791
                this.pluginPersistence =
792
                    ToolsLocator.getDynObjectManager()
793
                    .createDynObject(dynStruct); 
794
            }
795
        }
796
        return pluginPersistence;
797
    }
798

    
799
    public void savePluginProperties() {
800
        if (this.pluginPersistence == null) {
801
            return;
802
        }
803
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
804
                File persistenceFile = getPluginPersistenceFile();
805
        PersistentState state;
806
        FileOutputStream fos;
807
        try {
808
            state = manager.getState(pluginPersistence);
809
            manager.saveState(state, new FileOutputStream(persistenceFile));
810
        } catch (Exception e) {
811
            throw new PluginSaveDataException(this.getPluginName(), e);
812
        }
813

    
814

    
815
    }
816

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

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

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

    
842
                return persistenceFolder;
843
        }
844

    
845
    public class PluginPersistenceNeedDefinitionException extends
846
    BaseRuntimeException {
847

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

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

    
862
    public class PluginPersistenceAddDefinitionException extends
863
    BaseRuntimeException {
864

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

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

    
879
    public class PluginLoadDataException extends
880
    BaseRuntimeException {
881

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

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

    
895
    public class PluginSaveDataException extends
896
    BaseRuntimeException {
897

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

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

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

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