Explorar el Código

Moving plugin metadata handling to new class

Remove dodgy plugin info test

Change-Id: I763b973cab127431cf0b70914804e142d779290c
Reviewed-on: http://gerrit.dmdirc.com/2038
Automatic-Compile: DMDirc Build Manager
Reviewed-by: Greg Holmes <greg@dmdirc.com>
tags/0.6.6b1
Chris Smith hace 13 años
padre
commit
6990211c71

+ 111
- 246
src/com/dmdirc/plugins/PluginInfo.java Ver fichero

@@ -30,8 +30,6 @@ import com.dmdirc.config.InvalidIdentityFileException;
30 30
 import com.dmdirc.logger.ErrorLevel;
31 31
 import com.dmdirc.logger.Logger;
32 32
 import com.dmdirc.updater.Version;
33
-import com.dmdirc.util.ConfigFile;
34
-import com.dmdirc.util.InvalidConfigFileException;
35 33
 import com.dmdirc.util.resourcemanager.ResourceManager;
36 34
 import com.dmdirc.util.validators.ValidationResponse;
37 35
 
@@ -42,6 +40,7 @@ import java.lang.reflect.Constructor;
42 40
 import java.lang.reflect.InvocationTargetException;
43 41
 import java.net.URL;
44 42
 import java.util.ArrayList;
43
+import java.util.Collection;
45 44
 import java.util.HashMap;
46 45
 import java.util.List;
47 46
 import java.util.Map;
@@ -57,8 +56,9 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
57 56
     /** A logger for this class. */
58 57
     private static final java.util.logging.Logger LOGGER
59 58
             = java.util.logging.Logger.getLogger(PluginInfo.class.getName());
60
-    /** Plugin Meta Data. */
61
-    private volatile ConfigFile metaData;
59
+
60
+    /** The metadata for this plugin. */
61
+    private final PluginMetaData metadata;
62 62
     /** URL that this plugin was loaded from. */
63 63
     private final URL url;
64 64
     /** Filename for this plugin (taken from URL). */
@@ -91,43 +91,48 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
91 91
     /**
92 92
      * Create a new PluginInfo.
93 93
      *
94
+     * @param metadata The plugin's metadata information
94 95
      * @param url URL to file that this plugin is stored in.
95 96
      * @throws PluginException if there is an error loading the Plugin
96
-     * @since 0.6
97
+     * @since 0.6.6
97 98
      */
98
-    public PluginInfo(final URL url) throws PluginException {
99
-        this(url, true);
99
+    public PluginInfo(final PluginMetaData metadata, final URL url) throws PluginException {
100
+        this(metadata, url, true);
100 101
     }
101 102
 
102 103
     /**
103 104
      * Create a new PluginInfo.
104 105
      *
106
+     * @param metadata The plugin's metadata information
105 107
      * @param url URL to file that this plugin is stored in.
106 108
      * @param load Should this plugin be loaded, or is this just a placeholder? (true for load, false for placeholder)
107 109
      * @throws PluginException if there is an error loading the Plugin
108
-     * @since 0.6
110
+     * @since 0.6.6
109 111
      */
110
-    public PluginInfo(final URL url, final boolean load) throws PluginException {
112
+    public PluginInfo(final PluginMetaData metadata, final URL url, final boolean load) throws PluginException {
111 113
         this.url = url;
112 114
         this.filename = new File(url.getPath()).getName();
115
+        this.metadata = metadata;
113 116
 
114 117
         ResourceManager res;
115 118
 
116 119
         // Check for updates.
117 120
         if (new File(getFullFilename() + ".update").exists() && new File(getFullFilename()).delete()) {
118 121
             new File(getFullFilename() + ".update").renameTo(new File(getFullFilename()));
122
+
123
+            updateMetaData();
119 124
         }
120 125
 
121 126
         if (!load) {
122
-            // Load the metaData if available.
123
-            try {
124
-                metaData = getConfigFile();
125
-            } catch (IOException ioe) {
126
-                metaData = null;
127
-            }
127
+            // TODO: This is pointless now
128 128
             return;
129 129
         }
130 130
 
131
+        if (metadata.hasErrors()) {
132
+            throw new PluginException("Plugin " + filename + " has metadata "
133
+                    + "errors: " + metadata.getErrors());
134
+        }
135
+
131 136
         try {
132 137
             res = getResourceManager();
133 138
         } catch (IOException ioe) {
@@ -135,20 +140,6 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
135 140
             throw new PluginException("Plugin " + filename + " failed to load. " + lastError, ioe);
136 141
         }
137 142
 
138
-        try {
139
-            metaData = getConfigFile();
140
-            if (metaData == null) {
141
-                lastError = "plugin.config doesn't exist in jar";
142
-                throw new PluginException("Plugin " + filename + " failed to load. " + lastError);
143
-            }
144
-        } catch (IOException e) {
145
-            lastError = "plugin.config IOException: " + e.getMessage();
146
-            throw new PluginException("Plugin " + filename + " failed to load, plugin.config failed to open - " + e.getMessage(), e);
147
-        } catch (IllegalArgumentException e) {
148
-            lastError = "plugin.config IllegalArgumentException: " + e.getMessage();
149
-            throw new PluginException("Plugin " + filename + " failed to load, plugin.config failed to open - " + e.getMessage(), e);
150
-        }
151
-
152 143
         if (!getVersion().isValid()) {
153 144
             lastError = "Incomplete plugin.config (Missing or invalid 'version')";
154 145
             throw new PluginException("Plugin " + filename + " failed to load. " + lastError);
@@ -177,10 +168,6 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
177 168
                     myClasses.add(classname);
178 169
                 }
179 170
             }
180
-
181
-            if (isPersistent() && loadAll()) {
182
-                loadEntirePlugin();
183
-            }
184 171
         } else {
185 172
             lastError = "One or more requirements not met (" + requirementsError + ")";
186 173
             throw new PluginException("Plugin " + filename + " was not loaded. " + lastError);
@@ -190,28 +177,6 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
190 177
         getDefaults();
191 178
     }
192 179
 
193
-    /**
194
-     * Get a ConfigFile object for this plugin.
195
-     * This will load a ConfigFile
196
-     *
197
-     * @return the ConfigFile object for this plugin, or null if the plugin has no config
198
-     * @throws IOException if there is an error with the ResourceManager.
199
-     */
200
-    private ConfigFile getConfigFile() throws IOException {
201
-        ConfigFile file = null;
202
-        final ResourceManager res = getResourceManager();
203
-        if (res.resourceExists("META-INF/plugin.config")) {
204
-            try {
205
-                file = new ConfigFile(res.getResourceInputStream("META-INF/plugin.config"));
206
-                file.read();
207
-            } catch (InvalidConfigFileException icfe) {
208
-                throw new IOException("Unable to read plugin.config", icfe);
209
-            }
210
-        }
211
-
212
-        return file;
213
-    }
214
-
215 180
     /**
216 181
      * Get the licence for this plugin if it exists.
217 182
      *
@@ -231,46 +196,30 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
231 196
      * Get the defaults, formatters and icons for this plugin.
232 197
      */
233 198
     private void getDefaults() {
234
-        if (metaData == null) {
235
-            return;
236
-        }
237
-
238 199
         final Identity defaults = IdentityManager.getAddonIdentity();
239 200
         final String domain = "plugin-" + getName();
240 201
 
241 202
         LOGGER.finer(getName() + ": Using domain '" + domain + "'");
242 203
 
243
-        if (metaData.isKeyDomain("defaults")) {
244
-            final Map<String, String> keysection = metaData.getKeyDomain("defaults");
245
-
246
-            for (Map.Entry<String, String> entry : keysection.entrySet()) {
247
-                final String key = entry.getKey();
248
-                final String value = entry.getValue();
204
+        for (Map.Entry<String, String> entry : metadata.getDefaultSettings().entrySet()) {
205
+            final String key = entry.getKey();
206
+            final String value = entry.getValue();
249 207
 
250
-                defaults.setOption(domain, key, value);
251
-            }
208
+            defaults.setOption(domain, key, value);
252 209
         }
253 210
 
254
-        if (metaData.isKeyDomain("formatters")) {
255
-            final Map<String, String> keysection = metaData.getKeyDomain("formatters");
256
-
257
-            for (Map.Entry<String, String> entry : keysection.entrySet()) {
258
-                final String key = entry.getKey();
259
-                final String value = entry.getValue();
211
+        for (Map.Entry<String, String> entry : metadata.getFormatters().entrySet()) {
212
+            final String key = entry.getKey();
213
+            final String value = entry.getValue();
260 214
 
261
-                defaults.setOption("formatter", key, value);
262
-            }
215
+            defaults.setOption("formatter", key, value);
263 216
         }
264 217
 
265
-        if (metaData.isKeyDomain("icons")) {
266
-            final Map<String, String> keysection = metaData.getKeyDomain("icons");
218
+        for (Map.Entry<String, String> entry : metadata.getIcons().entrySet()) {
219
+            final String key = entry.getKey();
220
+            final String value = entry.getValue();
267 221
 
268
-            for (Map.Entry<String, String> entry : keysection.entrySet()) {
269
-                final String key = entry.getKey();
270
-                final String value = entry.getValue();
271
-
272
-                defaults.setOption("icon", key, value);
273
-            }
222
+            defaults.setOption("icon", key, value);
274 223
         }
275 224
     }
276 225
 
@@ -339,7 +288,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
339 288
         }
340 289
 
341 290
         // Get services provided by this plugin
342
-        final List<String> providesList = metaData.getFlatDomain("provides");
291
+        final Collection<String> providesList = metadata.getServices();
343 292
         if (providesList != null) {
344 293
             for (String item : providesList) {
345 294
                 final String[] bits = item.split(" ");
@@ -391,19 +340,9 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
391 340
      * @return true if metaData was reloaded ok, else false.
392 341
      */
393 342
     private boolean updateMetaData() {
394
-        // Force a new resourcemanager just incase.
395
-        try {
396
-            getResourceManager(true);
397
-            final ConfigFile newMetaData = getConfigFile();
398
-            if (newMetaData != null) {
399
-                metaData = newMetaData;
400
-                return true;
401
-            }
402
-        } catch (IOException ioe) {
403
-            Logger.userError(ErrorLevel.MEDIUM, "There was an error updating the metadata for "+getName(), ioe);
404
-        }
343
+        metadata.load();
405 344
 
406
-        return false;
345
+        return !metadata.hasErrors();
407 346
     }
408 347
 
409 348
     /**
@@ -532,7 +471,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
532 471
      * @return True if the test passes, false otherwise
533 472
      */
534 473
     protected boolean checkOS(final String desired, final String actualName, final String actualVersion, final String actualArch) {
535
-        if (desired.isEmpty()) {
474
+        if (desired == null || desired.isEmpty()) {
536 475
             return true;
537 476
         }
538 477
 
@@ -552,30 +491,6 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
552 491
         return true;
553 492
     }
554 493
 
555
-    /**
556
-     * Checks to see if the UI requirements of the plugin are satisfied.
557
-     * If the desired string is empty, the test passes.
558
-     * Otherwise it is used as a regular expressions against the package of the
559
-     * UIController to test what UI is currently in use.
560
-     * On failure, the requirementsError field will contain a user-friendly
561
-     * error message.
562
-     *
563
-     * @param desired The desired UI requirements
564
-     * @param actual The package of the current UI in use.
565
-     * @return True if the test passes, false otherwise
566
-     */
567
-    protected boolean checkUI(final String desired, final String actual) {
568
-        if (desired.isEmpty()) {
569
-            return true;
570
-        }
571
-
572
-        if (!actual.toLowerCase().matches(desired)) {
573
-            requirementsError = "Invalid UI. (Wanted: '" + desired + "', actual: '" + actual + "')";
574
-            return false;
575
-        }
576
-        return true;
577
-    }
578
-
579 494
     /**
580 495
      * Checks to see if the file requirements of the plugin are satisfied.
581 496
      * If the desired string is empty, the test passes.
@@ -589,7 +504,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
589 504
      * @return True if the test passes, false otherwise
590 505
      */
591 506
     protected boolean checkFiles(final String desired) {
592
-        if (desired.isEmpty()) {
507
+        if (desired == null || desired.isEmpty()) {
593 508
             return true;
594 509
         }
595 510
 
@@ -624,7 +539,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
624 539
      * @return True if the test passes, false otherwise
625 540
      */
626 541
     protected boolean checkPlugins(final String desired) {
627
-        if (desired.isEmpty()) {
542
+        if (desired == null || desired.isEmpty()) {
628 543
             return true;
629 544
         }
630 545
 
@@ -665,15 +580,10 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
665 580
      * @return true/false (Actual error if false is in the requirementsError field)
666 581
      */
667 582
     public boolean checkRequirements(final boolean preliminary) {
668
-        if (metaData == null) {
669
-            // No meta-data, so no requirements.
670
-            return true;
671
-        }
672
-
673
-        if (!checkOS(getKeyValue("requires", "os", ""), System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"))
674
-                || !checkFiles(getKeyValue("requires", "files", ""))
675
-                || (!preliminary && !checkPlugins(getKeyValue("requires", "plugins", "")))
676
-                || (!preliminary && !checkServices(metaData.getFlatDomain("required-services")))) {
583
+        if (!checkOS(metadata.getRequirements().get("os"), System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"))
584
+                || !checkFiles(metadata.getRequirements().get("files"))
585
+                || (!preliminary && !checkPlugins(metadata.getRequirements().get("plugins")))
586
+                || (!preliminary && !checkServices(metadata.getRequiredServices()))) {
677 587
             return false;
678 588
         }
679 589
 
@@ -687,8 +597,8 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
687 597
      * @param services Required services
688 598
      * @return true if all services are available
689 599
      */
690
-    private boolean checkServices(final List<String> services) {
691
-        if (services == null || services.size() < 1) {
600
+    private boolean checkServices(final Collection<String> services) {
601
+        if (services == null || services.isEmpty()) {
692 602
             return true;
693 603
         }
694 604
 
@@ -763,7 +673,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
763 673
      * otherwise
764 674
      */
765 675
     public boolean isLoaded() {
766
-        return (plugin != null) && !tempLoaded;
676
+        return plugin != null && !tempLoaded;
767 677
     }
768 678
 
769 679
     /**
@@ -773,23 +683,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
773 683
      * otherwise
774 684
      */
775 685
     public boolean isTempLoaded() {
776
-        return (plugin != null) && tempLoaded;
777
-    }
778
-
779
-    /**
780
-     * Load entire plugin.
781
-     * This loads all files in the jar immediately.
782
-     *
783
-     * @throws PluginException if there is an error with the resourcemanager
784
-     */
785
-    private void loadEntirePlugin() throws PluginException {
786
-        // Load the main "Plugin" from the jar
787
-        loadPlugin();
788
-
789
-        // Now load all the rest.
790
-        for (String classname : myClasses) {
791
-            loadClass(classname);
792
-        }
686
+        return plugin != null && tempLoaded;
793 687
     }
794 688
 
795 689
     /**
@@ -804,7 +698,12 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
804 698
      * Load any required plugins
805 699
      */
806 700
     public void loadRequired() {
807
-        final String required = getKeyValue("requires", "plugins", "");
701
+        final String required = metadata.getRequirements().get("plugins");
702
+
703
+        if (required == null) {
704
+            return;
705
+        }
706
+
808 707
         for (String pluginName : required.split(",")) {
809 708
             final String[] data = pluginName.split(":");
810 709
             if (!data[0].trim().isEmpty()) {
@@ -826,8 +725,8 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
826 725
      * Load the plugin files.
827 726
      */
828 727
     public void loadPlugin() {
829
-        if (isLoaded() || metaData == null || isLoading) {
830
-            lastError = "Not Loading: (" + isLoaded() + "||" + (metaData == null) + "||" + isLoading + ")";
728
+        if (isLoaded() || isLoading) {
729
+            lastError = "Not Loading: (" + isLoaded() + "||" + isLoading + ")";
831 730
             return;
832 731
         }
833 732
 
@@ -912,10 +811,10 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
912 811
     private void loadClass(final String classname) {
913 812
         try {
914 813
             if (classloader == null) {
915
-                if (getKeyValue("requires", "parent", "").isEmpty()) {
814
+                if (metadata.getParent() == null) {
916 815
                     classloader = new PluginClassLoader(this);
917 816
                 } else {
918
-                    final String parentName = getKeyValue("requires", "parent", "");
817
+                    final String parentName = metadata.getParent();
919 818
                     final PluginInfo pi = PluginManager.getPluginManager().getPluginInfoByName(parentName);
920 819
                     if (pi == null) {
921 820
                         lastError = "Required parent '" + parentName + "' was not found";
@@ -1027,12 +926,8 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1027 926
      * @return true if plugin can be unloaded
1028 927
      */
1029 928
     public boolean isUnloadable() {
1030
-        if (isPersistent() || (!isLoaded() && !isTempLoaded())) {
1031
-            return false;
1032
-        } else {
1033
-            final String unloadable = getKeyValue("metadata", "unloadable", "true");
1034
-            return unloadable.equalsIgnoreCase("yes") || unloadable.equalsIgnoreCase("true") || unloadable.equalsIgnoreCase("1");
1035
-        }
929
+        return !isPersistent() && (isTempLoaded() || isLoaded())
930
+                && metadata.isUnloadable();
1036 931
     }
1037 932
 
1038 933
     /**
@@ -1048,8 +943,8 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1048 943
                     child.unloadPlugin(true);
1049 944
                 }
1050 945
                 // Delete ourself as a child of our parent.
1051
-                if (!parentUnloading && !getKeyValue("requires", "parent", "").isEmpty()) {
1052
-                    final String parentName = getKeyValue("requires", "parent", "");
946
+                final String parentName = metadata.getParent();
947
+                if (!parentUnloading && parentName != null) {
1053 948
                     final PluginInfo pi = PluginManager.getPluginManager().getPluginInfoByName(parentName);
1054 949
                     if (pi != null) {
1055 950
                         pi.delChild(this);
@@ -1103,30 +998,15 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1103 998
         return myClasses;
1104 999
     }
1105 1000
 
1106
-    /**
1107
-     * Get the value of the given key from the given keysection, or fallback.
1108
-     *
1109
-     * @param section Section to look in
1110
-     * @param key Key to check
1111
-     * @param fallback Value to use if key doesn't exist.
1112
-     * @return Value of the key in the keysection, or the fallback if not present
1113
-     */
1114
-    public String getKeyValue(final String section, final String key, final String fallback) {
1115
-        if (metaData != null && metaData.isKeyDomain(section)) {
1116
-            final Map<String, String> keysection = metaData.getKeyDomain(section);
1117
-            return keysection.containsKey(key) ? keysection.get(key) : fallback;
1118
-        }
1119
-
1120
-        return fallback;
1121
-    }
1122
-
1123 1001
     /**
1124 1002
      * Get the main Class
1125 1003
      *
1126 1004
      * @return Main Class to begin loading.
1005
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1127 1006
      */
1007
+    @Deprecated
1128 1008
     public String getMainClass() {
1129
-        return getKeyValue("metadata", "mainclass", "");
1009
+        return metadata.getMainClass();
1130 1010
     }
1131 1011
 
1132 1012
     /**
@@ -1151,18 +1031,22 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1151 1031
      * Get the plugin friendly version
1152 1032
      *
1153 1033
      * @return Plugin friendly Version
1034
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1154 1035
      */
1036
+    @Deprecated
1155 1037
     public String getFriendlyVersion() {
1156
-        return getKeyValue("version", "friendly", String.valueOf(getVersion()));
1038
+        return metadata.getFriendlyVersion();
1157 1039
     }
1158 1040
 
1159 1041
     /**
1160 1042
      * Get the plugin version
1161 1043
      *
1162 1044
      * @return Plugin Version
1045
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1163 1046
      */
1047
+    @Deprecated
1164 1048
     public Version getVersion() {
1165
-        return new Version(getKeyValue("version", "number", "0"));
1049
+        return metadata.getVersion();
1166 1050
     }
1167 1051
 
1168 1052
     /**
@@ -1175,13 +1059,11 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1175 1059
      * @return Addon Site ID number
1176 1060
      *         -1 If not present
1177 1061
      *         -2 If non-integer
1062
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1178 1063
      */
1064
+    @Deprecated
1179 1065
     public int getAddonID() {
1180
-        try {
1181
-            return Integer.parseInt(getKeyValue("updates", "id", "-1"));
1182
-        } catch (NumberFormatException nfe) {
1183
-            return -2;
1184
-        }
1066
+        return metadata.getUpdaterId();
1185 1067
     }
1186 1068
 
1187 1069
     /**
@@ -1190,12 +1072,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1190 1072
      * @return true if persistent, else false
1191 1073
      */
1192 1074
     public boolean isPersistent() {
1193
-        if (metaData != null && metaData.isFlatDomain("persistent")) {
1194
-            final List<String> items = metaData.getFlatDomain("persistent");
1195
-            return items.contains("*");
1196
-        }
1197
-
1198
-        return false;
1075
+        return metadata.getPersistentClasses().contains("*");
1199 1076
     }
1200 1077
 
1201 1078
     /**
@@ -1204,12 +1081,7 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1204 1081
      * @return true if this plugin contains any persistent classes, else false
1205 1082
      */
1206 1083
     public boolean hasPersistent() {
1207
-        if (metaData != null && metaData.isFlatDomain("persistent")) {
1208
-            final List<String> items = metaData.getFlatDomain("persistent");
1209
-            return !items.isEmpty();
1210
-        }
1211
-
1212
-        return false;
1084
+        return !metadata.getPersistentClasses().isEmpty();
1213 1085
     }
1214 1086
 
1215 1087
     /**
@@ -1217,8 +1089,8 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1217 1089
      *
1218 1090
      * @return List of all persistent classes in this plugin
1219 1091
      */
1220
-    public List<String> getPersistentClasses() {
1221
-        final List<String> result = new ArrayList<String>();
1092
+    public Collection<String> getPersistentClasses() {
1093
+        final Collection<String> result = new ArrayList<String>();
1222 1094
 
1223 1095
         if (isPersistent()) {
1224 1096
             try {
@@ -1232,11 +1104,9 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1232 1104
             } catch (IOException e) {
1233 1105
                 // Jar no longer exists?
1234 1106
             }
1235
-        } else if (metaData != null && metaData.isFlatDomain("persistent")) {
1236
-            return metaData.getFlatDomain("persistent");
1237 1107
         }
1238 1108
 
1239
-        return result;
1109
+        return metadata.getPersistentClasses();
1240 1110
     }
1241 1111
 
1242 1112
     /**
@@ -1248,11 +1118,8 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1248 1118
     public boolean isPersistent(final String classname) {
1249 1119
         if (isPersistent()) {
1250 1120
             return true;
1251
-        } else if (metaData != null && metaData.isFlatDomain("persistent")) {
1252
-            final List<String> items = metaData.getFlatDomain("persistent");
1253
-            return items.contains(classname);
1254 1121
         } else {
1255
-            return false;
1122
+            return metadata.getPersistentClasses().contains(classname);
1256 1123
         }
1257 1124
     }
1258 1125
 
@@ -1293,18 +1160,22 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1293 1160
      * Get the plugin Author.
1294 1161
      *
1295 1162
      * @return Author of plugin
1163
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1296 1164
      */
1165
+    @Deprecated
1297 1166
     public String getAuthor() {
1298
-        return getKeyValue("metadata", "author", "");
1167
+        return metadata.getAuthor();
1299 1168
     }
1300 1169
 
1301 1170
     /**
1302 1171
      * Get the plugin Description.
1303 1172
      *
1304 1173
      * @return Description of plugin
1174
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1305 1175
      */
1176
+    @Deprecated
1306 1177
     public String getDescription() {
1307
-        return getKeyValue("metadata", "description", "");
1178
+        return metadata.getDescription();
1308 1179
     }
1309 1180
 
1310 1181
     /**
@@ -1313,8 +1184,9 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1313 1184
      * @return minimum dmdirc version required to run the plugin.
1314 1185
      */
1315 1186
     public String getMinVersion() {
1316
-        final String requiredVersion = getKeyValue("requires", "dmdirc", "");
1317
-        if (!requiredVersion.isEmpty()) {
1187
+        final String requiredVersion = metadata.getRequirements().get("dmdirc");
1188
+
1189
+        if (requiredVersion != null) {
1318 1190
             final String[] bits = requiredVersion.split("-");
1319 1191
             return bits[0];
1320 1192
         }
@@ -1328,8 +1200,9 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1328 1200
      * @return optional maximum dmdirc version on which this plugin can run
1329 1201
      */
1330 1202
     public String getMaxVersion() {
1331
-        final String requiredVersion = getKeyValue("requires", "dmdirc", "");
1332
-        if (!requiredVersion.isEmpty()) {
1203
+        final String requiredVersion = metadata.getRequirements().get("dmdirc");
1204
+
1205
+        if (requiredVersion != null) {
1333 1206
             final String[] bits = requiredVersion.split("-");
1334 1207
             if (bits.length > 1) {
1335 1208
                 return bits[1];
@@ -1343,18 +1216,22 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1343 1216
      * Get the name of the plugin. (Used to identify the plugin)
1344 1217
      *
1345 1218
      * @return Name of plugin
1219
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1346 1220
      */
1221
+    @Deprecated
1347 1222
     public String getName() {
1348
-        return getKeyValue("metadata", "name", "");
1223
+        return metadata.getName();
1349 1224
     }
1350 1225
 
1351 1226
     /**
1352 1227
      * Get the nice name of the plugin. (Displayed to users)
1353 1228
      *
1354 1229
      * @return Nice Name of plugin
1230
+     * @deprecated Retrieve this from {@link PluginMetaData} directly
1355 1231
      */
1232
+    @Deprecated
1356 1233
     public String getNiceName() {
1357
-        return getKeyValue("metadata", "nicename", getName());
1234
+        return metadata.getFriendlyName();
1358 1235
     }
1359 1236
 
1360 1237
     /**
@@ -1367,16 +1244,6 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1367 1244
         return getNiceName() + " - " + filename;
1368 1245
     }
1369 1246
 
1370
-    /**
1371
-     * Does this plugin want all its classes loaded?
1372
-     *
1373
-     * @return true/false if loadall=true || loadall=yes
1374
-     */
1375
-    public boolean loadAll() {
1376
-        final String loadAll = getKeyValue("metadata", "loadall", "no");
1377
-        return loadAll.equalsIgnoreCase("true") || loadAll.equalsIgnoreCase("yes");
1378
-    }
1379
-
1380 1247
     /** {@inheritDoc} */
1381 1248
     @Override
1382 1249
     public int compareTo(final PluginInfo o) {
@@ -1390,24 +1257,22 @@ public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
1390 1257
         exports.clear();
1391 1258
 
1392 1259
         // Get exports provided by this plugin
1393
-        final List<String> exportsList = metaData.getFlatDomain("exports");
1394
-        if (exportsList != null) {
1395
-            for (String item : exportsList) {
1396
-                final String[] bits = item.split(" ");
1397
-                if (bits.length > 2) {
1398
-                    final String methodName = bits[0];
1399
-                    final String methodClass = bits[2];
1400
-                    final String serviceName = (bits.length > 4) ? bits[4] : bits[0];
1401
-
1402
-                    // Add a provides for this
1403
-                    final Service service = PluginManager.getPluginManager().getService("export", serviceName, true);
1404
-                    synchronized (provides) {
1405
-                        service.addProvider(this);
1406
-                        provides.add(service);
1407
-                    }
1408
-                    // Add is as an export
1409
-                    exports.put(serviceName, new ExportInfo(methodName, methodClass, this));
1260
+        final Collection<String> exportsList = metadata.getExports();
1261
+        for (String item : exportsList) {
1262
+            final String[] bits = item.split(" ");
1263
+            if (bits.length > 2) {
1264
+                final String methodName = bits[0];
1265
+                final String methodClass = bits[2];
1266
+                final String serviceName = (bits.length > 4) ? bits[4] : bits[0];
1267
+
1268
+                // Add a provides for this
1269
+                final Service service = PluginManager.getPluginManager().getService("export", serviceName, true);
1270
+                synchronized (provides) {
1271
+                    service.addProvider(this);
1272
+                    provides.add(service);
1410 1273
                 }
1274
+                // Add is as an export
1275
+                exports.put(serviceName, new ExportInfo(methodName, methodClass, this));
1411 1276
             }
1412 1277
         }
1413 1278
     }

+ 10
- 8
src/com/dmdirc/plugins/PluginManager.java Ver fichero

@@ -37,6 +37,7 @@ import java.io.File;
37 37
 import java.net.MalformedURLException;
38 38
 import java.net.URL;
39 39
 import java.util.ArrayList;
40
+import java.util.Arrays;
40 41
 import java.util.Collection;
41 42
 import java.util.Deque;
42 43
 import java.util.HashMap;
@@ -261,7 +262,9 @@ public class PluginManager implements ActionListener {
261 262
         }
262 263
 
263 264
         try {
264
-            final PluginInfo pluginInfo = new PluginInfo(new URL("file:" + getDirectory() + filename));
265
+            final PluginMetaData metadata = new PluginMetaData(new URL("jar:file://" + getDirectory() + filename + "!/META-INF/plugin.config"));
266
+            metadata.load();
267
+            final PluginInfo pluginInfo = new PluginInfo(metadata, new URL("file:" + getDirectory() + filename));
265 268
             final PluginInfo existing = getPluginInfoByName(pluginInfo.getName());
266 269
             if (existing != null) {
267 270
                 Logger.userError(ErrorLevel.MEDIUM, "Duplicate Plugin detected, Ignoring. (" + filename + " is the same as " + existing.getFilename() + ")");
@@ -418,19 +421,18 @@ public class PluginManager implements ActionListener {
418 421
         while (!dirs.isEmpty()) {
419 422
             final File dir = dirs.pop();
420 423
             if (dir.isDirectory()) {
421
-                for (File file : dir.listFiles()) {
422
-                    dirs.add(file);
423
-                }
424
+                dirs.addAll(Arrays.asList(dir.listFiles()));
424 425
             } else if (dir.isFile() && dir.getName().endsWith(".jar")) {
425
-                String target = dir.getPath();
426
-
427 426
                 // Remove the plugin dir
428
-                target = target.substring(myDir.length(), target.length());
427
+                final String target = dir.getPath().substring(myDir.length());
428
+
429 429
                 if (addPlugins) {
430 430
                     addPlugin(target);
431 431
                 } else {
432 432
                     try {
433
-                        final PluginInfo pi = new PluginInfo(new URL("file:" + getDirectory() + target), false);
433
+                        final PluginMetaData metadata = new PluginMetaData(new URL("jar:file://" + getDirectory() + target + "!/META-INF/plugin.config"));
434
+                        metadata.load();
435
+                        final PluginInfo pi = new PluginInfo(metadata, new URL("file:" + getDirectory() + target), false);
434 436
                         res.put(target, pi);
435 437
                     } catch (MalformedURLException mue) {
436 438
                         Logger.userError(ErrorLevel.MEDIUM, "Error creating URL for plugin " + target + ": " + mue.getMessage(), mue);

+ 553
- 0
src/com/dmdirc/plugins/PluginMetaData.java Ver fichero

@@ -0,0 +1,553 @@
1
+/*
2
+ * Copyright (c) 2006-2011 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.plugins;
24
+
25
+import com.dmdirc.updater.Version;
26
+import com.dmdirc.util.ConfigFile;
27
+import com.dmdirc.util.InvalidConfigFileException;
28
+import com.dmdirc.util.StreamUtil;
29
+
30
+import java.io.IOException;
31
+import java.io.InputStream;
32
+import java.net.URL;
33
+import java.util.ArrayList;
34
+import java.util.Collection;
35
+import java.util.Collections;
36
+import java.util.HashMap;
37
+import java.util.List;
38
+import java.util.Map;
39
+
40
+/**
41
+ * Reads metadata for a plugin. Plugin metadata is defined in a DMDirc
42
+ * {@link ConfigFile} which is typically found inside plugin jars as
43
+ * <code>META-INF/plugin.config</code>. The following sections are read from
44
+ * the config file:
45
+ * <ul>
46
+ *  <li><code>metadata</code> - generic plugin information. See {@link #readMetaData(java.util.Map)}.
47
+ *  <li><code>version</code> - versioning information. See {@link #readVersion(java.util.Map)}.
48
+ *  <li><code>defaults</code> - optional default settings to add to the configuration
49
+ *  <li><code>formatters</code> - optional default formatters to add to the configuration
50
+ *  <li><code>icons</code> - optional default icons to add to the configuration
51
+ *  <li><code>requires</code> - optional generic requirements. See {@link #readRequirements(java.util.Map, java.util.List)}.
52
+ *  <li><code>required-services</code> - optional service requirements. See {@link #readRequirements(java.util.Map, java.util.List)}.
53
+ *  <li><code>updates</code> - optional information for automated updates. See {@link #readUpdates(java.util.Map)}.
54
+ *  <li><code>provides</code> - optional list of services provided by the plugin. See {@link #readProvides(java.util.List)}.
55
+ *  <li><code>exports</code> - optional list of methods exported by the plugin. See {@link #readExports(java.util.List)}.
56
+ *  <li><code>persistent</code> - optional list of persistent classes within the plugin. See {@link #readPersistent(java.util.List)}.
57
+ * </ul>
58
+ * A collection of errors that occurred when attempting to read the metadata
59
+ * is available via the {@link #getErrors()} method.
60
+ *
61
+ * @since 0.6.6
62
+ */
63
+public class PluginMetaData {
64
+
65
+    /** A collection of errors that occurred when reading or validating the data. */
66
+    private final Collection<String> errors
67
+            = new ArrayList<String>();
68
+
69
+    /** Default settings defined in the plugin metadata. */
70
+    private final Map<String, String> defaultSettings
71
+            = new HashMap<String, String>();
72
+
73
+    /** Formatters defined in the plugin metadata. */
74
+    private final Map<String, String> formatters
75
+            = new HashMap<String, String>();
76
+
77
+    /** Icons defined in the plugin metadata. */
78
+    private final Map<String, String> icons
79
+            = new HashMap<String, String>();
80
+
81
+    /** A set of requirements made by the plugin. */
82
+    private final Map<String, String> requirements
83
+            = new HashMap<String, String>();
84
+
85
+    /** A list of required services. */
86
+    private final Collection<String> requiredServices
87
+            = new ArrayList<String>();
88
+
89
+    /** Services provided by this plugin. */
90
+    private final Collection<String> services
91
+            = new ArrayList<String>();
92
+
93
+    /** Methods exported by this plugin. */
94
+    private final Collection<String> exports
95
+            = new ArrayList<String>();
96
+
97
+    /** Persistent classes in this plugin. */
98
+    private final Collection<String> persistentClasses
99
+            = new ArrayList<String>();
100
+
101
+    /** The name of the parent plugin, if any. */
102
+    private String parent;
103
+
104
+    /** The name of the main class, if any. */
105
+    private String mainClass;
106
+
107
+    /** The friendly version name/number. */
108
+    private String friendlyVersion;
109
+
110
+    /** The version of the plugin. */
111
+    private Version version;
112
+
113
+    /** The ID to use with the updater system, if any. */
114
+    private int updaterId;
115
+
116
+    /** The author-supplied friendly name of the plugin. */
117
+    private String friendlyName;
118
+
119
+    /** The internal name of the plugin. */
120
+    private String name;
121
+
122
+    /** The name of the author of the plugin. */
123
+    private String author;
124
+
125
+    /** The author-supplied description of the plugin. */
126
+    private String description;
127
+
128
+    /** Whether or not the plugin is marked as unloadable. */
129
+    private boolean unloadable;
130
+
131
+    /** The URL to load the metadata from. */
132
+    private final URL url;
133
+
134
+    /**
135
+     * Creates a new meta data reader for a config file at the specified URL.
136
+     *
137
+     * @param url The URL to load the config file from
138
+     */
139
+    public PluginMetaData(final URL url) {
140
+        this.url = url;
141
+    }
142
+
143
+    /**
144
+     * Loads plugin metadata from a config file.
145
+     */
146
+    public void load() {
147
+        errors.clear();
148
+        InputStream stream = null;
149
+
150
+        try {
151
+            stream = url.openStream();
152
+            final ConfigFile configFile = new ConfigFile(stream);
153
+            configFile.read();
154
+            readMetaData(configFile.getKeyDomain("metadata"));
155
+            readVersion(configFile.getKeyDomain("version"));
156
+            readUpdates(configFile.getKeyDomain("updates"));
157
+            readSettings(defaultSettings, configFile.getKeyDomain("defaults"));
158
+            readSettings(formatters, configFile.getKeyDomain("formatters"));
159
+            readSettings(icons, configFile.getKeyDomain("icons"));
160
+            readRequirements(configFile.getKeyDomain("requires"),
161
+                    configFile.getFlatDomain("required-services"));
162
+            readProvides(configFile.getFlatDomain("provides"));
163
+            readPersistent(configFile.getFlatDomain("persistent"));
164
+            readExports(configFile.getFlatDomain("exports"));
165
+        } catch (IOException ex) {
166
+            errors.add("Unable to read config file: " + ex.getMessage());
167
+            StreamUtil.close(stream);
168
+        } catch (InvalidConfigFileException ex) {
169
+            errors.add("Unable to read config file: " + ex.getMessage());
170
+            StreamUtil.close(stream);
171
+        }
172
+    }
173
+
174
+    // <editor-fold desc="Read methods">
175
+
176
+    /**
177
+     * Reads information from the metadata section of the config file.
178
+     * The following entries are read from the metadata section:
179
+     * <ul>
180
+     *  <li><code>mainclass</code> - full classname of the main class to load
181
+     *  <li><code>author</code> - name of the author
182
+     *  <li><code>description</code> - user-friendly description
183
+     *  <li><code>name</code> - internal short name
184
+     *  <li><code>nicename</code> - user-friendly name
185
+     *  <li><code>unloadable</code> - boolean indicating if the plugin can
186
+     *  be unloaded. Defaults to true if not specified.
187
+     * </ul>
188
+     * It is recommended that the <code>author</code> field should take the
189
+     * form of "<code>name &lt;email@address&gt;</code>", although this is not
190
+     * enforced.
191
+     * <p>
192
+     * The short name must be a single word (i.e., no spaces) that uniquely
193
+     * identifies the plugin. This is typically the same as the plugin's jar
194
+     * name.
195
+     *
196
+     * @param data A map of config entry names to values
197
+     */
198
+    protected void readMetaData(final Map<String, String> data) {
199
+        if (data == null || data.isEmpty()) {
200
+            errors.add("'metadata' section not specified or empty");
201
+            return;
202
+        }
203
+
204
+        mainClass = data.get("mainclass");
205
+        author = data.get("author");
206
+        description = data.get("description");
207
+        name = data.get("name");
208
+        friendlyName = data.get("nicename");
209
+        unloadable = !data.containsKey("unloadable")
210
+                || !data.get("unloadable").matches("(?i)^true|1|yes$");
211
+    }
212
+
213
+    /**
214
+     * Reads information from the version section of the config file.
215
+     * The following entries are read from the version section:
216
+     * <ul>
217
+     *  <li><code>friendly</code> - a user-friendly version string
218
+     *  <li><code>number</code> - a DMDirc {@link Version} 'number'
219
+     * </ul>
220
+     * If the 'number' field is not specified it will be defaulted to a value
221
+     * of "0".
222
+     *
223
+     * @param data A map of config entry names to values
224
+     */
225
+    protected void readVersion(final Map<String, String> data) {
226
+        if (data == null || data.isEmpty()) {
227
+            errors.add("'version' section not specified or empty");
228
+            return;
229
+        }
230
+
231
+        friendlyVersion = data.get("friendly");
232
+        version = new Version(data.containsKey("number") ? data.get("number") : "0");
233
+    }
234
+
235
+    /**
236
+     * Reads information from the updates section of the config file.
237
+     * The following entries are read from the updates section:
238
+     * <ul>
239
+     *  <li><code>id</code> - a numeric ID for the plugin's entry in the DMDirc
240
+     *  updater system
241
+     * </ul>
242
+     *
243
+     * @param data A map of config entry names to values
244
+     */
245
+    protected void readUpdates(final Map<String, String> data) {
246
+        updaterId = -1;
247
+
248
+        if (data != null && data.containsKey("id")) {
249
+            try {
250
+                updaterId = Integer.parseInt(data.get("id"));
251
+            } catch (NumberFormatException ex) {
252
+                errors.add("Invalid updater id specified: " + data.get("id"));
253
+            }
254
+        }
255
+    }
256
+
257
+    /**
258
+     * Copies the specified settings (defaults, formatters, icons, etc) into
259
+     * the specified property.
260
+     *
261
+     * @param target The map to add settings to
262
+     * @param data The settings specified in the metadata
263
+     */
264
+    protected void readSettings(final Map<String, String> target,
265
+            final Map<String, String> data) {
266
+        target.clear();
267
+
268
+        if (data != null) {
269
+            target.putAll(data);
270
+        }
271
+    }
272
+
273
+    /**
274
+     * Reads the requirements and required-services sections of the config file.
275
+     * The requires section is a mapping of a requirement type to a constraint.
276
+     * No validation is performed on this section, but the following types
277
+     * are standard:
278
+     * <ul>
279
+     *  <li><code>parent</code> - internal name of a single parent plugin,
280
+     *  e.g. 'ui_swing'.
281
+     *  <li><code>plugins</code> - a comma-separated list of plugins that are
282
+     *  required. Plugins are specified by their internal names, and each entry
283
+     *  may include an optional minimum and maximum version separated by colons,
284
+     *  e.g. 'ui_swing' or 'plugin1,plugin2:0.6.3,plugin3:0.1:0.2'.
285
+     *  <li><code>os</code> - one to three colon-separated regular expressions
286
+     *  to match the OS name, version and architecture, e.g. '.*win.*'.
287
+     *  <li><code>files</code> - a comma-separated list of files that must
288
+     *  exist. Each comma-separated value may contain multiple alternatives
289
+     *  separated by a pipe, e.g. '/bin/bash' or '/bin/bash|/bin/dash,/bin/foo'.
290
+     *  <li><code>dmdirc</code> - the minimum and maximum DMDirc versions,
291
+     *  separated by a '-', e.g. '0.6.3', '0.6.3-0.6.4', '-0.6.4'.
292
+     * </ul>
293
+     * The required-services section is a flat domain which lists services that
294
+     * the plugin requires. No validation is performed on these values, but
295
+     * each service should consist of a name and a type. The magic string
296
+     * <code>any</code> may be specified in place of a name (e.g. 'any ui'
297
+     * instead of 'swing ui').
298
+     *
299
+     * @param data The specified requirements
300
+     * @param requiredServices The specified required services
301
+     */
302
+    protected void readRequirements(final Map<String, String> data,
303
+            final List<String> requiredServices) {
304
+        readSettings(requirements, data);
305
+
306
+        parent = requirements.get("parent");
307
+
308
+        this.requiredServices.clear();
309
+
310
+        if (requiredServices != null) {
311
+            this.requiredServices.addAll(requiredServices);
312
+        }
313
+    }
314
+
315
+    /**
316
+     * Reads the provides section of the config file. This is a flat domain
317
+     * containing a list of services provided by the plugin. Services are
318
+     * specified as a space-separated name and type pair, e.g. 'swing ui' or
319
+     * 'logging command'.
320
+     *
321
+     * @param services The services to be added
322
+     */
323
+    protected void readProvides(final List<String> services) {
324
+        this.services.clear();
325
+
326
+        if (services != null) {
327
+            this.services.addAll(services);
328
+        }
329
+    }
330
+
331
+    /**
332
+     * Reads the persistent section of the config file. This is a flat domain
333
+     * containing a list of classes which should be made persistent (i.e.,
334
+     * loaded globally and not unloaded).
335
+     *
336
+     * @param classes The services to be added
337
+     */
338
+    protected void readPersistent(final List<String> classes) {
339
+        this.persistentClasses.clear();
340
+
341
+        if (classes != null) {
342
+            this.persistentClasses.addAll(classes);
343
+        }
344
+    }
345
+
346
+    /**
347
+     * Reads the exports section of the config file. This is a flat domain
348
+     * containing a list of exported methods in the format
349
+     * <code>&lt;methodName&gt; in &lt;className&gt; [as &lt;methodAlias&gt;]</code>,
350
+     * e.g. 'getFoo in my.class.name as getParser' or 'getParser in my.class.name'.
351
+     *
352
+     * @param exports The exported methods for this plugin
353
+     */
354
+    protected void readExports(final List<String> exports) {
355
+        this.exports.clear();
356
+
357
+        if (exports != null) {
358
+            this.exports.addAll(exports);
359
+        }
360
+    }
361
+
362
+    // </editor-fold>
363
+
364
+    // <editor-fold defaultstate="collapsed" desc="Getters">
365
+
366
+    /**
367
+     * Retrieves a collection of errors that occurred while trying to read
368
+     * the metadata.
369
+     *
370
+     * @return A (possibly empty) collection of errors that occurred.
371
+     */
372
+    public Collection<String> getErrors() {
373
+        return Collections.unmodifiableCollection(errors);
374
+    }
375
+
376
+    /**
377
+     * Determines whether or not there were errors encountered while trying to
378
+     * read the metadata.
379
+     *
380
+     * @return True if there are errors, false otherwise
381
+     * @see #getErrors()
382
+     */
383
+    public boolean hasErrors() {
384
+        return !errors.isEmpty();
385
+    }
386
+
387
+    /**
388
+     * Retrieves the author information for the plugin.
389
+     *
390
+     * @return The plugin's specified author
391
+     */
392
+    public String getAuthor() {
393
+        return author;
394
+    }
395
+
396
+    /**
397
+     * Retrieves a user-friendly description of the plugin.
398
+     *
399
+     * @return The plugin's user-friendly description
400
+     */
401
+    public String getDescription() {
402
+        return description;
403
+    }
404
+
405
+    /**
406
+     * Retrieves a user-friendly name of the plugin.
407
+     *
408
+     * @return This plugin's user-friendly name
409
+     */
410
+    public String getFriendlyName() {
411
+        return friendlyName;
412
+    }
413
+
414
+    /**
415
+     * Retrieves the specified main class of the plugin.
416
+     *
417
+     * @return This plugin's main class
418
+     */
419
+    public String getMainClass() {
420
+        return mainClass;
421
+    }
422
+
423
+    /**
424
+     * Retrieves the internal short name of this plugin.
425
+     *
426
+     * @return This plugin's internal short name
427
+     */
428
+    public String getName() {
429
+        return name;
430
+    }
431
+
432
+    /**
433
+     * Retrieves the user-friendly version of this plugin.
434
+     *
435
+     * @return This plugin's user-friendly version
436
+     */
437
+    public String getFriendlyVersion() {
438
+        return friendlyVersion;
439
+    }
440
+
441
+    /**
442
+     * Determines whether the plugin is specified as unloadable or not.
443
+     *
444
+     * @return True if the plugin is unloadable, false otherwise
445
+     */
446
+    public boolean isUnloadable() {
447
+        return unloadable;
448
+    }
449
+
450
+    /**
451
+     * Retrieves the version of this plugin
452
+     *
453
+     * @return This plugin's version
454
+     */
455
+    public Version getVersion() {
456
+        return version;
457
+    }
458
+
459
+    /**
460
+     * Retrieves the updater ID of this plugin.
461
+     *
462
+     * @return This plugin's updater ID, or -1 if not specified
463
+     */
464
+    public int getUpdaterId() {
465
+        return updaterId;
466
+    }
467
+
468
+    /**
469
+     * Returns a map of default settings supplied by this plugin.
470
+     *
471
+     * @return A map of setting keys to values
472
+     */
473
+    public Map<String, String> getDefaultSettings() {
474
+        return Collections.unmodifiableMap(defaultSettings);
475
+    }
476
+
477
+    /**
478
+     * Returns a map of default formatters supplied by this plugin.
479
+     *
480
+     * @return A map of formatter names to values
481
+     */
482
+    public Map<String, String> getFormatters() {
483
+        return Collections.unmodifiableMap(formatters);
484
+    }
485
+
486
+    /**
487
+     * Returns a map of default icons supplied by this plugin.
488
+     *
489
+     * @return A map of icon names to values
490
+     */
491
+    public Map<String, String> getIcons() {
492
+        return Collections.unmodifiableMap(icons);
493
+    }
494
+
495
+    /**
496
+     * Retrieves this plugin's parent, if specified.
497
+     *
498
+     * @return The desired parent plugin, or null if none specified
499
+     */
500
+    public String getParent() {
501
+        return parent;
502
+    }
503
+
504
+    /**
505
+     * Retrieves the collection of required services.
506
+     *
507
+     * @see #readRequirements(java.util.Map, java.util.List)
508
+     * @return A collection of plugin-defined service requirements
509
+     */
510
+    public Collection<String> getRequiredServices() {
511
+        return Collections.unmodifiableCollection(requiredServices);
512
+    }
513
+
514
+    /**
515
+     * Retrieves the collection of plugin requirements.
516
+     *
517
+     * @see #readRequirements(java.util.Map, java.util.List)
518
+     * @return A collection of plugin-defined requirements
519
+     */
520
+    public Map<String, String> getRequirements() {
521
+        return Collections.unmodifiableMap(requirements);
522
+    }
523
+
524
+    /**
525
+     * Retrieves the collection of services exported by the plugin.
526
+     *
527
+     * @return The services which the plugin specifies it provides
528
+     */
529
+    public Collection<String> getServices() {
530
+        return Collections.unmodifiableCollection(services);
531
+    }
532
+
533
+    /**
534
+     * Retrieves the collection of methods exported by the plugin.
535
+     *
536
+     * @return The methods exported by the plugin
537
+     */
538
+    public Collection<String> getExports() {
539
+        return Collections.unmodifiableCollection(exports);
540
+    }
541
+
542
+    /**
543
+     * Retrieves the set of classes marked as persistent for this plugin.
544
+     *
545
+     * @return The classes of this plugin marked as persistent
546
+     */
547
+    public Collection<String> getPersistentClasses() {
548
+        return Collections.unmodifiableCollection(persistentClasses);
549
+    }
550
+
551
+    // </editor-fold>
552
+
553
+}

+ 0
- 117
test/com/dmdirc/plugins/PluginInfoTest.java Ver fichero

@@ -1,117 +0,0 @@
1
-/*
2
- * Copyright (c) 2006-2011 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
- *
4
- * Permission is hereby granted, free of charge, to any person obtaining a copy
5
- * of this software and associated documentation files (the "Software"), to deal
6
- * in the Software without restriction, including without limitation the rights
7
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- * copies of the Software, and to permit persons to whom the Software is
9
- * furnished to do so, subject to the following conditions:
10
- *
11
- * The above copyright notice and this permission notice shall be included in
12
- * all copies or substantial portions of the Software.
13
- *
14
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- * SOFTWARE.
21
- */
22
-
23
-package com.dmdirc.plugins;
24
-
25
-import java.io.File;
26
-import java.io.IOException;
27
-
28
-import java.net.URL;
29
-import java.net.MalformedURLException;
30
-
31
-import org.junit.Test;
32
-import static org.junit.Assert.*;
33
-
34
-public class PluginInfoTest {
35
-
36
-    private PluginInfo pi;
37
-
38
-    @Test
39
-    public void testCheckMinimum() throws PluginException {
40
-        try {
41
-            pi = new PluginInfo(new URL("file:///dev/null"), false);
42
-
43
-            assertTrue(pi.checkMinimumVersion("5", 6));
44
-            assertTrue(pi.checkMinimumVersion("5", 5));
45
-            assertTrue(pi.checkMinimumVersion("0", 17));
46
-            assertTrue(pi.checkMinimumVersion("100", 0));
47
-            assertTrue(pi.checkMinimumVersion("0", 0));
48
-            assertFalse(pi.checkMinimumVersion("abc", 6));
49
-            assertFalse(pi.checkMinimumVersion("7", 6));
50
-        } catch (MalformedURLException mue) { }
51
-    }
52
-
53
-    @Test
54
-    public void testCheckMaximim() throws PluginException {
55
-        try {
56
-            pi = new PluginInfo(new URL("file:///dev/null"), false);
57
-
58
-            assertTrue(pi.checkMaximumVersion("6", 6));
59
-            assertTrue(pi.checkMaximumVersion("7", 6));
60
-            assertTrue(pi.checkMaximumVersion("0", 6));
61
-            assertTrue(pi.checkMaximumVersion("6", 0));
62
-            assertTrue(pi.checkMaximumVersion("0", 0));
63
-            assertTrue(pi.checkMaximumVersion("", 17));
64
-            assertFalse(pi.checkMaximumVersion("abc", 6));
65
-            assertFalse(pi.checkMaximumVersion("7", 10));
66
-        } catch (MalformedURLException mue) { }
67
-    }
68
-
69
-    @Test
70
-    public void testOS() throws PluginException {
71
-        try {
72
-            pi = new PluginInfo(new URL("file:///dev/null"), false);
73
-
74
-            assertTrue(pi.checkOS("windows", "windows", "xp", "x86"));
75
-            assertFalse(pi.checkOS("windows", "linux", "2.6.2.11", "x86"));
76
-            assertTrue(pi.checkOS("windows:xp|98|3\\.1", "windows", "xp", "x86"));
77
-            assertFalse(pi.checkOS("windows:xp|98|3\\.1", "windows", "vista", "x86"));
78
-            assertFalse(pi.checkOS("windows:xp|98|3\\.1", "linux", "2.6.2.11", "x86"));
79
-            assertTrue(pi.checkOS("windows:xp|98|3\\.1:.86", "windows", "xp", "x86"));
80
-            assertFalse(pi.checkOS("windows:xp|98|3\\.1:.86", "windows", "xp", "mips"));
81
-            assertFalse(pi.checkOS("windows:xp|98|3\\.1:.86", "windows", "vista", "x86"));
82
-            assertFalse(pi.checkOS("windows:xp|98|3\\.1:.86", "linux", "2.6.2.11", "x86"));
83
-        } catch (MalformedURLException mue) { }
84
-    }
85
-
86
-    @Test
87
-    public void testLoad() throws PluginException {
88
-        PluginInfo pi = new PluginInfo(getClass().getResource("testplugin.jar"));
89
-        assertEquals("Author <em@il>", pi.getAuthor());
90
-        assertEquals("Friendly", pi.getFriendlyVersion());
91
-        assertEquals("Description goes here", pi.getDescription());
92
-        assertEquals("randomname", pi.getName());
93
-        assertEquals("Friendly name", pi.getNiceName());
94
-        assertEquals("3", pi.getVersion().toString());
95
-    }
96
-
97
-    @Test
98
-    public void testUpdate() throws PluginException, IOException {
99
-        final File dir = new File(File.createTempFile("dmdirc-plugin-test", null).getParentFile(),
100
-                "dmdirc-plugin-test-folder");
101
-        final File pluginDir = new File(dir, "plugins");
102
-
103
-        dir.deleteOnExit();
104
-        pluginDir.mkdirs();
105
-
106
-        final File target = new File(pluginDir, "test.jar");
107
-
108
-        target.createNewFile();
109
-        new File(pluginDir, "test.jar.update").createNewFile();
110
-
111
-        new PluginInfo(target.toURI().toURL(), false);
112
-
113
-        assertTrue(new File(pluginDir, "test.jar").exists());
114
-        assertFalse(new File(pluginDir, "test.jar.update").exists());
115
-    }
116
-
117
-}

BIN
test/com/dmdirc/plugins/testplugin.jar Ver fichero


Loading…
Cancelar
Guardar