Statistics
| Revision:

root / trunk / frameworks / _fwAndami / src / com / iver / andami / PluginServices.java @ 23987

History | View | Annotate | Download (19.8 KB)

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

    
43
import java.awt.Component;
44
import java.awt.Frame;
45
import java.awt.KeyEventDispatcher;
46
import java.awt.Toolkit;
47
import java.awt.datatransfer.DataFlavor;
48
import java.awt.datatransfer.StringSelection;
49
import java.awt.datatransfer.UnsupportedFlavorException;
50
import java.awt.event.ActionListener;
51
import java.io.File;
52
import java.io.IOException;
53
import java.lang.reflect.InvocationTargetException;
54
import java.util.ArrayList;
55
import java.util.HashMap;
56
import java.util.Iterator;
57
import java.util.Properties;
58

    
59
import javax.swing.KeyStroke;
60
import javax.swing.SwingUtilities;
61
import javax.swing.Timer;
62

    
63
import org.apache.log4j.Logger;
64

    
65
import com.iver.andami.authentication.IAuthentication;
66
import com.iver.andami.iconthemes.IIconTheme;
67
import com.iver.andami.iconthemes.IconThemeManager;
68
import com.iver.andami.messages.Messages;
69
import com.iver.andami.messages.NotificationManager;
70
import com.iver.andami.plugins.ExclusiveUIExtension;
71
import com.iver.andami.plugins.ExtensionDecorator;
72
import com.iver.andami.plugins.IExtension;
73
import com.iver.andami.plugins.PluginClassLoader;
74
import com.iver.andami.preferences.DlgPreferences;
75
import com.iver.andami.ui.mdiFrame.MDIFrame;
76
import com.iver.andami.ui.mdiFrame.MainFrame;
77
import com.iver.andami.ui.mdiManager.MDIManager;
78
import com.iver.utiles.XMLEntity;
79
import com.iver.utiles.swing.threads.IMonitorableTask;
80
import com.iver.utiles.swing.threads.IProgressMonitorIF;
81
import com.iver.utiles.swing.threads.TaskMonitorTimerListener;
82
import com.iver.utiles.swing.threads.UndefinedProgressMonitor;
83

    
84
/**
85
 * Provides services to Plugins. Each plugin has an associated PluginServices
86
 * object, which provides specific services. Main of them: translations,
87
 * logging, access to plugin's resources, background tasks, clipboard access
88
 * and data persistence.
89
 *
90
 * @author Fernando Gonz?lez Cort?s
91
 */
92
public class PluginServices {
93
        private static Logger logger = Logger.getLogger(PluginServices.class
94
                        .getName());
95

    
96
        private static String[] arguments;
97

    
98
        private static IAuthentication authentication;
99

    
100
        private static ExclusiveUIExtension exclusiveUIExtension = null;
101

    
102
        private PluginClassLoader loader;
103

    
104
        private XMLEntity persistentXML;
105

    
106

    
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
        /**
118
         * Returns the message in the current's locale language
119
         * corresponding to the provided translation key.
120
         * The key-message pairs are obtained from the plugin's
121
         * translation files (text_xx.properties files).
122
         *
123
         * @param key
124
         *            Translation key whose associated message is to be obtained
125
         *
126
         * @return The message associated with the provided key, in one of the
127
         * current locale languages, or the key if the translation is not found.
128
         */
129
        public String getText(String key) {
130
                if (key == null) return null;
131
                String translation = org.gvsig.i18n.Messages.getText(key, false);
132
                if (translation != null)
133
                        return translation;
134
                else
135
                {
136
                        logger.warn("Plugin "+getPluginName()+" -- "+org.gvsig.i18n.Messages.getText("No_se_encontro_la_traduccion_para", false)+ " " + key);
137
                        return key;
138
                }
139
        }
140

    
141
        /**
142
         * Gets the plugin's classloader.
143
         *
144
         * @return Returns the loader.
145
         */
146
        public PluginClassLoader getClassLoader() {
147
                return loader;
148
        }
149

    
150
        /**
151
         * Gets the plugin's name
152
         *
153
         * @return The plugin's name
154
         */
155
        String getPluginName() {
156
                return loader.getPluginName();
157
        }
158

    
159
        /**
160
         * Gets a reference to the PluginServices object associated with the
161
         * plugin containing the provided class.
162
         *
163
         * Obtienen una referencia al PluginServices del plugin cuyo nombre se pasa
164
         * como par?metro
165
         *
166
         * @param pluginClassInstance
167
         *            An instance of a class. This class is contained in a plugin, whose
168
         *            services are to be obtained
169
         *
170
         * @return The PluginServices object associated to the containing plugin
171
         *
172
         * @throws RuntimeException
173
         *             If the parameter was not loaded from a plugin
174
         */
175
        public static PluginServices getPluginServices(Object pluginClassInstance) {
176
                try {
177
                        PluginClassLoader loader = (PluginClassLoader) pluginClassInstance
178
                                        .getClass().getClassLoader();
179

    
180
                        return Launcher.getPluginServices(loader.getPluginName());
181
                } catch (ClassCastException e) {
182
                        /*
183
                         * throw new RuntimeException( "Parameter is not a plugin class
184
                         * instance");
185
                         */
186
                        return null;
187
                }
188
        }
189

    
190
        /**
191
         * Gets a reference to the PluginServices object associated with the
192
         * provided plugin.
193
         *
194
         * @param pluginName
195
         *            Plugin's name whose services are going to be used
196
         *
197
         * @return The PluginServices object associated with the provided plugin.
198
         */
199
        public static PluginServices getPluginServices(String pluginName) {
200
                return Launcher.getPluginServices(pluginName);
201
        }
202

    
203
        /**
204
         * Gets the window manager (MDIManager).
205
         *
206
         * @return A reference to the window manager (MDIManager).
207
         */
208
        public static MDIManager getMDIManager() {
209
                return Launcher.getFrame().getMDIManager();
210
        }
211

    
212
        /**
213
         * Gets the application's main frame.
214
         *
215
         * @return A reference to the application's main window
216
         */
217
        public static MainFrame getMainFrame() {
218
                return Launcher.getFrame();
219
        }
220

    
221
        public static void registerKeyStroke(KeyStroke key, KeyEventDispatcher a)
222
        {
223
                GlobalKeyEventDispatcher.getInstance().registerKeyStroke(key, a);
224
        }
225

    
226
        public static void unRegisterKeyStroke(KeyStroke key)
227
        {
228
                GlobalKeyEventDispatcher.getInstance().removeKeyStrokeBinding(key);
229
        }
230

    
231
        /**
232
         * Gets the instance of the extension whose class is provided.
233
         *
234
         * @param extensionClass
235
         *            Class of the extension whose instance is to be returned
236
         *
237
         * @return The instance of the extension, or null if the instance does
238
         *         not exist.Instancia de la extensi?n o null en caso de que no haya una
239
         */
240
        public static IExtension getExtension(Class extensionClass) {
241
                ExtensionDecorator extAux = (ExtensionDecorator) Launcher
242
                                .getClassesExtensions().get(extensionClass);
243
                try {
244
                        return extAux.getExtension();
245
                }
246
                catch (NullPointerException ex) {
247
                        return null;
248
                }
249
        }
250

    
251
        /**
252
         * Gets a reference to the Extension Decorator which adds some extra options
253
         * to the basic extension interface.
254
         *
255
         * @param extensionClass  The class of the extension whose decorator is to be returned
256
         * @return                The ExtensionDecorator associated with the provided extension,
257
         * or null if the extension does not exist.
258
         */
259
        public static ExtensionDecorator getDecoratedExtension(Class extensionClass) {
260
                return (ExtensionDecorator) Launcher.getClassesExtensions().get(
261
                                extensionClass);
262
        }
263

    
264
        /**
265
         * Returns an array containing references to all the loaded extensions.
266
         *
267
         * @return ExtensionDecorator[] An array of ExtensionDecorators (each
268
         * Decorator contains one extension).
269
         */
270
        public static ExtensionDecorator[] getDecoratedExtensions() {
271
                HashMap map = Launcher.getClassesExtensions();
272
                ExtensionDecorator[] extensions = (ExtensionDecorator[]) map.
273
                                values().toArray(new ExtensionDecorator[0]);
274
                return extensions;
275
        }
276

    
277
        /**
278
         * Gets an iterator with all the loaded Extensions.
279
         *
280
         * @return Iterator over the decorated extensions (each member of
281
         * the iterator is an ExtensionDecorator, which in turn contains
282
         * one IExtension object).
283
         */
284
        public static Iterator getExtensions() {
285
                return Launcher.getClassesExtensions().values().iterator();
286
        }
287

    
288
        /**
289
         * Returns the message in the current's locale language
290
         * corresponding to the provided translation key.
291
         * The key-message pairs are obtained from the plugin's
292
         * translation files (text_xx.properties files).
293
         *
294
         * @param pluginObject Any object which was loaded from a plugin
295
         *
296
         * @param key
297
         *            Translation key whose associated message is to be obtained
298
         *
299
         * @return The message associated with the provided key, in one of the
300
         * current locale languages, or the key if the translation is not found.
301
         */
302
        public static String getText(Object pluginObject, String key) {
303
                if (key == null) return null;
304
                String translation = org.gvsig.i18n.Messages.getText(key, false);
305
                if (translation != null)
306
                        return translation;
307
                else
308
                {
309
                        logger.warn(org.gvsig.i18n.Messages.getText("No_se_encontro_la_traduccion_para",false) + " "+ key);
310
                        return key;
311
                }
312
        }
313

    
314
        /**
315
         * Sets the XML data which should be saved on disk for this plugin. This
316
         * data can be retrieved on following sessions.
317
         *
318
         * @param The XMLEntity object containing the data to be persisted.
319
         *
320
         * @see PluginServices.getPersistentXML()
321
         * @see XMLEntity
322
         */
323
        public void setPersistentXML(XMLEntity entity) {
324
                persistentXML = entity;
325
        }
326

    
327
        /**
328
         * Gets the XML data which was saved on previous sessions for this
329
         *  plugins.
330
         *
331
         * @return An XMLEntity object containing the persisted data
332
         */
333
        public XMLEntity getPersistentXML() {
334
                if (persistentXML == null) {
335
                        persistentXML = new XMLEntity();
336
                }
337
                return persistentXML;
338
        }
339

    
340
        /**
341
         * A?ade un listener a un popup menu registrado en el config.xml de alg?n
342
         * plugin
343
         *
344
         * @param name
345
         *            Nombre del men? contextual
346
         * @param c
347
         *            Componente que desplegar? el men? cuando se haga click con el
348
         *            bot?n derecho
349
         * @param listener
350
         *            Listener que se ejecutar? cuando se seleccione cualquier
351
         *            entrada del men?
352
         *
353
         * @throws RuntimeException
354
         *             Si la interfaz no est? preparada todav?a. S?lo puede darse
355
         *             durante el arranque
356
         */
357
        public void addPopupMenuListener(String name, Component c,
358
                        ActionListener listener) {
359
                MDIFrame frame = Launcher.getFrame();
360

    
361
                if (frame == null) {
362
                        throw new RuntimeException("MDIFrame not loaded yet");
363
                }
364

    
365
                frame.addPopupMenuListener(name, c, listener, loader);
366
        }
367

    
368
        /**
369
         * Gets the plugin's root directory.
370
         *
371
         * @return A File pointing to the plugin's root directory.
372
         */
373
        public File getPluginDirectory() {
374
                return new File(Launcher.getPluginsDir() + File.separator
375
                                + getPluginName());
376
        }
377

    
378
        /**
379
         * Runs a background task. The events produced on the main frame will
380
         * be inhibited.
381
         *
382
         * @param r
383
         *            The task to run.
384
         *
385
         * @return The Thread on which the task is executed.
386
         */
387
        public static Thread backgroundExecution(Runnable r) {
388
                Thread t = new Thread(new RunnableDecorator(r));
389
                t.start();
390

    
391
                return t;
392
        }
393

    
394
        /**
395
         * Runs a backbround task. This task may be monitored and canceled, and
396
         * does not inhibit any event.
397
         *
398
         * @param task
399
         *            The task to run.
400
         */
401
        public static void cancelableBackgroundExecution(final IMonitorableTask task) {
402
                final com.iver.utiles.swing.threads.SwingWorker worker = new com.iver.utiles.swing.threads.SwingWorker() {
403
                        public Object construct() {
404
                                try {
405
                                        task.run();
406
                                        return task;
407
                                } catch (Exception e) {
408
                                        NotificationManager.addError(null, e);
409
                                }
410
                                return null;
411
                        }
412
                    /**
413
                     * Called on the event dispatching thread (not on the worker thread)
414
                     * after the <code>construct</code> method has returned.
415
                     */
416
                        public void finished() {
417
                                task.finished();
418
                        }
419
                };
420

    
421
                Component mainFrame = (Component) PluginServices.getMainFrame();
422

    
423
                IProgressMonitorIF progressMonitor = null;
424
                String title = getText(null, "PluginServices.Procesando");
425
                progressMonitor = new UndefinedProgressMonitor((Frame) mainFrame, title);
426
                progressMonitor.setIndeterminated(!task.isDefined());
427
                progressMonitor.setInitialStep(task.getInitialStep());
428
                progressMonitor.setLastStep(task.getFinishStep());
429
                progressMonitor.setCurrentStep(task.getCurrentStep());
430
                progressMonitor.setMainTitleLabel(task.getStatusMessage());
431
                progressMonitor.setNote(task.getNote());
432
                progressMonitor.open();
433
                int delay = 500;
434
                TaskMonitorTimerListener timerListener = new TaskMonitorTimerListener(
435
                                progressMonitor, task);
436
                Timer timer = new Timer(delay, timerListener);
437
                timerListener.setTimer(timer);
438
                timer.start();
439

    
440
                worker.start();
441

    
442
        }
443

    
444
        /**
445
         * Closes the application. Cleanly exits from the application:
446
         * terminates all the extensions, then exits.
447
         *
448
         */
449
        public static void closeApplication() {
450
                Launcher.closeApplication();
451
        }
452

    
453
        /**
454
         * DOCUMENT ME!
455
         *
456
         * @author Fernando Gonz?lez Cort?s
457
         */
458
        private static class RunnableDecorator implements Runnable {
459
                private Runnable r;
460

    
461
                /**
462
                 * Crea un nuevo RunnableDecorator.
463
                 *
464
                 * @param r
465
                 *            DOCUMENT ME!
466
                 */
467
                public RunnableDecorator(Runnable r) {
468
                        this.r = r;
469
                }
470

    
471
                /**
472
                 * @see java.lang.Runnable#run()
473
                 */
474
                public void run() {
475
                        try {
476
                                SwingUtilities.invokeAndWait(new Runnable() {
477
                                        public void run() {
478
                                                try {
479
                                                        r.run();
480
                                                } catch (RuntimeException e) {
481
                                                        NotificationManager
482
                                                                        .addError(
483
                                                                                        Messages
484
                                                                                                        .getString("PluginServices.Bug_en_el_codigo"),
485
                                                                                        e);
486
                                                } catch (Error e) {
487
                                                        NotificationManager
488
                                                                        .addError(
489
                                                                                        Messages
490
                                                                                                        .getString("PluginServices.Error_grave_de_la_aplicaci?n"),
491
                                                                                        e);
492
                                                }
493
                                        }
494
                                });
495
                        } catch (InterruptedException e) {
496
                                NotificationManager
497
                                                .addWarning(
498
                                                                Messages
499
                                                                                .getString("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
500
                                                                e);
501
                        } catch (InvocationTargetException e) {
502
                                NotificationManager
503
                                                .addWarning(
504
                                                                Messages
505
                                                                                .getString("PluginServices.No_se_pudo_poner_el_reloj_de_arena"),
506
                                                                e);
507
                        }
508
                }
509
        }
510

    
511
        /**
512
         * Gets an array containing the application's startup arguments.
513
         * <br><br>
514
         * Usually: <code>appName plugins-directory [locale] [other args]</code>
515
         *
516
         * @return the original arguments that Andami received. (app-name
517
         *         plugins-directory, locale, etc)
518
         */
519
        public static String[] getArguments() {
520
                return arguments;
521
        }
522

    
523
        /**
524
         * Replaces the original Andami arguments with the provided arguments.
525
         *
526
         * @param arguments An array of String, each element of the array
527
         * represents one
528
         * argument.
529
         */
530
        public static void setArguments(String[] arguments) {
531
                PluginServices.arguments = arguments;
532
        }
533

    
534
        /**
535
         * Returns the value of a command line named argument.
536
         *<br>
537
         *<br>
538
         * The argument format is:
539
         *<br>
540
         * -{argumentName}={argumentValue}
541
         *<br>
542
         *<br>
543
         *example:
544
         * <br>
545
         * ' -language=en '
546
         * @return String The value of the argument
547
         */
548
        public static String getArgumentByName(String name) {
549
        for (int i=2; i < PluginServices.arguments.length; i++)
550
        {
551
                int index = PluginServices.arguments[i].indexOf(name +"=");
552
                if (index != -1)
553
                        return PluginServices.arguments[i].substring(index+name.length()+1);
554
        }
555
        return null;
556
        }
557

    
558
        /**
559
         * Gets the logger. The logger is used to register important
560
         * events (errors, etc), which are stored on a file which
561
         * can be checked later.
562
         *
563
         * @return A Logger object.
564
         * @see Logger object from the Log4j library.
565
         *
566
         */
567
        public static Logger getLogger() {
568
                return logger;
569
        }
570

    
571
        public static IAuthentication getAuthentication() {
572
                return authentication;
573
        }
574

    
575
        public static void setAuthentication(IAuthentication authen) {
576
                authentication = authen;
577
        }
578
        public static DlgPreferences getDlgPreferences() {
579
                return DlgPreferences.getInstance();
580
        }
581

    
582
        /**
583
         * Stores the provided text data on the clipboard.
584
         *
585
         * @param data An String containing the data to be stored
586
         * on the clipboard.
587
         */
588
        public static void putInClipboard(String data) {
589
                StringSelection ss = new StringSelection(data);
590

    
591
                Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,ss);
592
        }
593

    
594
        /**
595
         * Gets text data from the Clipboard, if available.
596
         *
597
         * @return An String containing the clipboard's data, or
598
         * <code>null</code>
599
         * if the data was not available.
600
         */
601
        public static String getFromClipboard() {
602

    
603
                 try {
604
                        return (String)Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null).getTransferData(DataFlavor.stringFlavor);
605
                } catch (UnsupportedFlavorException e) {
606
                        return null;
607
                } catch (IOException e) {
608
                        // TODO Auto-generated catch block
609
                        return null;
610
                }
611
        }
612

    
613

    
614
        /**
615
         * Gets the ExclusiveUIExtension, an special extension which
616
         * will take
617
         * control over the UI and will decide which extensions may be
618
         * enable/disabled or visible/hidden.
619
         *
620
         * @return If an ExclusiveUIExtension was set, return this extension.
621
         * Otherwise, return <code>null</code>.
622
         *
623
         *  @see com.iver.andami.Launcher#initializeExclusiveUIExtension()
624
         *  @see com.iver.andami.plugins.IExtension#isEnabled(IExtension extension)
625
         *  @see com.iver.andami.plugins.IExtension#isVisible(IExtension extension)
626
         */
627
        public static ExclusiveUIExtension getExclusiveUIExtension() {
628
                return PluginServices.exclusiveUIExtension;
629
        }
630

    
631
        /**
632
         * Sets the ExclusiveUIExtension, an special extension which
633
         * will take
634
         * control over the UI and will decide which extensions may be
635
         * enable/disabled or visible/hidden.
636
         * <br><br>
637
         * The ExclusiveUIExtension is normally set by the following
638
         * Andami startup argument:
639
         * <br><br>
640
         * <code>ExclusiveUIExtension=ExtensionName</code>
641
         *
642
         *  @see com.iver.andami.Launcher#initializeExclusiveUIExtension()
643
         *  @see com.iver.andami.plugins.IExtension#isEnabled(IExtension extension)
644
         *  @see com.iver.andami.plugins.IExtension#isVisible(IExtension extension)
645
         */
646
        public static void setExclusiveUIExtension(ExclusiveUIExtension extension) {
647
                PluginServices.exclusiveUIExtension = extension;
648
        }
649

    
650
        public static void addLoaders(ArrayList classLoaders) {
651
                PluginClassLoader.addLoaders(classLoaders);
652
        }
653

    
654
        public static IconThemeManager getIconThemeManager() {
655
                return IconThemeManager.getIconThemeManager();
656
        }
657

    
658
        public static IIconTheme getIconTheme() {
659
                return IconThemeManager.getIconThemeManager().getCurrent();
660
        }
661

    
662
        /** Try to detect if the application is running in a development
663
         * environment.
664
         * <br>
665
         * This look for <b>.project</b> and <b>.classpath</b> files in the starts path of the application.
666
         *
667
         * @return true if <b>.project</b> and <b>.classpath</b> are in the development path
668
         */
669
        public static boolean runningInDevelopment(){
670
                String andamiPath;
671
                Properties props = System.getProperties();
672

    
673
                try {
674
                        try {
675
                                andamiPath = (new File(Launcher.class.getResource(".").getFile() + File.separator + ".." + File.separator + ".." + File.separator +".." + File.separator+ "..")).getCanonicalPath();
676
                        } catch (IOException e) {
677
                                andamiPath = (new File(Launcher.class.getResource(".").getFile() + File.separator + ".." + File.separator + ".." + File.separator +".."+ File.separator+ "..")).getAbsolutePath();
678
                        }
679
                } catch (Exception e1) {
680
                        andamiPath = (String)props.get("user.dir");
681
                }
682

    
683
                File andamiJar = new File(andamiPath + File.separator +"andami.jar");
684
                if (!andamiJar.exists())
685
                        return false;
686
                File projectFile = new File(andamiPath + File.separator +".project");
687
                File classpathFile = new File(andamiPath + File.separator +".classpath");
688
                return projectFile.exists() && classpathFile.exists();
689

    
690
        }
691
}