001: /*****************************************************************************
002: * Java Plug-in Framework (JPF)
003: * Copyright (C) 2004-2007 Dmitry Olshansky
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *****************************************************************************/package org.java.plugin.registry;
019:
020: import java.net.URL;
021: import java.util.Collection;
022: import java.util.Map;
023: import java.util.Set;
024:
025: import org.java.plugin.ObjectFactory;
026: import org.java.plugin.PathResolver;
027: import org.java.plugin.PluginManager;
028: import org.java.plugin.util.ExtendedProperties;
029:
030: /**
031: * Root interface to get access to all meta-information about discovered
032: * plug-ins. All objects accessible from the registry are immutable. You can
033: * imagine registry as a read-only storage of full information about discovered
034: * plug-ins. There is only one exception from this rule: internal state of
035: * registry, plug-in descriptors and plug-in elements can be modified indirectly
036: * by {@link #register(URL[]) registering} or
037: * {@link #unregister(String[]) un-registering} plug-ins with this registry. If
038: * your code is interested to be notified on all modifications of plug-ins set,
039: * you can
040: * {@link #registerListener(PluginRegistry.RegistryChangeListener) register} an
041: * implementation of {@link PluginRegistry.RegistryChangeListener} with this
042: * registry.
043: * <p>
044: * <i>Notes on unique ID's (UID's)</i>
045: * </p>
046: * <p>
047: * There are two types of identifiers in the API: ID's and UID's. ID is an
048: * identifier that is unique within set of elements of the same type. UID is an
049: * identifier that unique globally within registry space. ID is usually defined
050: * by developer in plug-in manifest. UID always combined automatically from
051: * several other plug-in "parts". All plug-in elements have method
052: * {@link org.java.plugin.registry.Identity#getId() getId()} that come from
053: * basic {@link org.java.plugin.registry.Identity} interface, but not all
054: * elements have UID - only those that inherits
055: * {@link org.java.plugin.registry.UniqueIdentity}interface.
056: * </p>
057: * <p>
058: * There are several utility methods available in this interface that aimed to
059: * build UID from different plug-in "parts" and also split UID to it's original
060: * elements: {@link #makeUniqueId(String, Version)},
061: * {@link #makeUniqueId(String, String)}, {@link #extractPluginId(String)},
062: * {@link #extractId(String)} and {@link #extractVersion(String)}.
063: * </p>
064: *
065: * @see org.java.plugin.ObjectFactory#createRegistry()
066: *
067: * @version $Id: PluginRegistry.java,v 1.5 2007/03/03 17:16:26 ddimon Exp $
068: */
069: public interface PluginRegistry {
070: /**
071: * Registers plug-ins and plug-in fragments in this registry. Note that this
072: * method not makes plug-ins available for activation by any
073: * {@link PluginManager} instance as it is not aware of any manager. Using
074: * this method just makes plug-in meta-data available for reading from this
075: * registry.
076: * <p>
077: * If more than one version of the same plug-in or plug-in fragment given,
078: * the only latest version should be registered. If some plug-in or plug-in
079: * fragment already registered it should be ignored by this method. Client
080: * application have to un-register such plug-ins first before registering
081: * their newest versions.
082: *
083: * @param manifests
084: * array of manifest locations
085: * @return map where keys are URL's and values are registered plug-ins or
086: * plug-in fragments, URL's for unprocessed manifests are not
087: * included
088: * @throws ManifestProcessingException
089: * if manifest processing error has occurred (optional behavior)
090: *
091: * @see PluginManager#publishPlugins(PluginManager.PluginLocation[])
092: */
093: Map<String, Identity> register(URL[] manifests)
094: throws ManifestProcessingException;
095:
096: /**
097: * Reads basic information from a plug-in or plug-in fragment manifest.
098: *
099: * @param manifest
100: * manifest data URL
101: * @return manifest info
102: * @throws ManifestProcessingException
103: * if manifest data can't be read
104: */
105: ManifestInfo readManifestInfo(URL manifest)
106: throws ManifestProcessingException;
107:
108: /**
109: * Unregisters plug-ins and plug-in fragments with given ID's (including
110: * depending plug-ins and plug-in fragments).
111: *
112: * @param ids
113: * ID's of plug-ins and plug-in fragments to be unregistered
114: * @return collection of UID's of actually unregistered plug-ins and plug-in
115: * fragments
116: */
117: Collection<String> unregister(String[] ids);
118:
119: /**
120: * Returns descriptor of plug-in with given ID. <br>
121: * If plug-in descriptor with given ID can't be found or such plug-in exists
122: * but is damaged this method have to throw an
123: * {@link IllegalArgumentException}. In other words, this method shouldn't
124: * return <code>null</code>.
125: *
126: * @param pluginId
127: * plug-id ID
128: * @return plug-in descriptor
129: */
130: PluginDescriptor getPluginDescriptor(String pluginId);
131:
132: /**
133: * Checks if plug-in exists and is in valid state. If this method returns
134: * <code>true</code>, the method {@link #getPluginDescriptor(String)}
135: * should always return valid plug-in descriptor.
136: *
137: * @param pluginId
138: * plug-in ID
139: * @return <code>true</code> if plug-in exists and valid
140: */
141: boolean isPluginDescriptorAvailable(String pluginId);
142:
143: /**
144: * Returns collection of descriptors of all plug-ins that was successfully
145: * populated by this registry.
146: *
147: * @return collection of {@link PluginDescriptor} objects
148: */
149: Collection<PluginDescriptor> getPluginDescriptors();
150:
151: /**
152: * Looks for extension point. This method have throw an
153: * {@link IllegalArgumentException} if requested extension point can't be
154: * found or is in invalid state.
155: *
156: * @param pluginId
157: * plug-in ID
158: * @param pointId
159: * extension point ID
160: * @return plug-in extension point
161: * @see ExtensionPoint#isValid()
162: */
163: ExtensionPoint getExtensionPoint(String pluginId, String pointId);
164:
165: /**
166: * Looks for extension point.
167: *
168: * @param uniqueId
169: * extension point unique ID
170: * @return plug-in extension point
171: * @see #getExtensionPoint(String, String)
172: */
173: ExtensionPoint getExtensionPoint(String uniqueId);
174:
175: /**
176: * Checks if extension point exists and is in valid state. If this method
177: * returns <code>true</code>, the method
178: * {@link #getExtensionPoint(String, String)} should always return valid
179: * extension point.
180: *
181: * @param pluginId
182: * plug-in ID
183: * @param pointId
184: * extension point ID
185: * @return <code>true</code> if extension point exists and valid
186: */
187: boolean isExtensionPointAvailable(String pluginId, String pointId);
188:
189: /**
190: * Checks if extension point exists and is in valid state.
191: *
192: * @param uniqueId
193: * extension point unique ID
194: * @return <code>true</code> if extension point exists and valid
195: * @see #isExtensionPointAvailable(String, String)
196: */
197: boolean isExtensionPointAvailable(String uniqueId);
198:
199: /**
200: * Returns collection of descriptors of all plug-in fragments that was
201: * successfully populated by this registry.
202: *
203: * @return collection of {@link PluginFragment} objects
204: */
205: Collection<PluginFragment> getPluginFragments();
206:
207: /**
208: * Utility method that recursively collects all plug-ins that depends on the
209: * given plug-in.
210: *
211: * @param descr
212: * descriptor of plug-in to collect dependencies for
213: * @return collection of {@link PluginDescriptor plug-in descriptors} that
214: * depend on given plug-in
215: */
216: Collection<PluginDescriptor> getDependingPlugins(
217: PluginDescriptor descr);
218:
219: /**
220: * Performs integrity check of all registered plug-ins and generates result
221: * as a collection of standard report items.
222: *
223: * @param pathResolver
224: * optional path resolver
225: * @return integrity check report
226: */
227: IntegrityCheckReport checkIntegrity(PathResolver pathResolver);
228:
229: /**
230: * Performs integrity check of all registered plug-ins and generates result
231: * as a collection of standard report items.
232: *
233: * @param pathResolver
234: * optional path resolver
235: * @param includeRegistrationReport
236: * if <code>true</code>, the plug-ins registration report will
237: * be included into resulting report
238: * @return integrity check report
239: */
240: IntegrityCheckReport checkIntegrity(PathResolver pathResolver,
241: boolean includeRegistrationReport);
242:
243: /**
244: * @return plug-ins registration report for this registry
245: */
246: IntegrityCheckReport getRegistrationReport();
247:
248: /**
249: * Constructs unique identifier for some plug-in element from it's ID.
250: *
251: * @param pluginId
252: * plug-in ID
253: * @param elementId
254: * element ID
255: * @return unique ID
256: */
257: String makeUniqueId(String pluginId, String elementId);
258:
259: /**
260: * Constructs unique identifier for plug-in with given ID.
261: *
262: * @param pluginId
263: * plug-in ID
264: * @param version
265: * plug-in version identifier
266: * @return unique plug-in ID
267: */
268: String makeUniqueId(String pluginId, Version version);
269:
270: /**
271: * Extracts plug-in ID from some unique identifier.
272: *
273: * @param uniqueId
274: * unique ID
275: * @return plug-in ID
276: */
277: String extractPluginId(String uniqueId);
278:
279: /**
280: * Extracts plug-in element ID from some unique identifier.
281: *
282: * @param uniqueId
283: * unique ID
284: * @return element ID
285: */
286: String extractId(String uniqueId);
287:
288: /**
289: * Extracts plug-in version identifier from some unique identifier (plug-in
290: * or plug-in fragment).
291: *
292: * @param uniqueId
293: * unique ID
294: * @return plug-in version identifier
295: */
296: Version extractVersion(String uniqueId);
297:
298: /**
299: * Registers plug-in registry change event listener. If given listener has
300: * been registered before, this method should throw an
301: * {@link IllegalArgumentException}.
302: *
303: * @param listener
304: * new registry change event listener
305: */
306: void registerListener(RegistryChangeListener listener);
307:
308: /**
309: * Unregisters registry change event listener. If given listener hasn't been
310: * registered before, this method should throw an
311: * {@link IllegalArgumentException}.
312: *
313: * @param listener
314: * registered listener
315: */
316: void unregisterListener(RegistryChangeListener listener);
317:
318: /**
319: * Configures this registry instance. Usually this method is called from
320: * {@link ObjectFactory object factory} implementation.
321: *
322: * @param config
323: * registry configuration data
324: */
325: void configure(ExtendedProperties config);
326:
327: /**
328: * Plug-in registry changes callback interface.
329: *
330: * @version $Id: PluginRegistry.java,v 1.5 2007/03/03 17:16:26 ddimon Exp $
331: */
332: interface RegistryChangeListener {
333: /**
334: * This method will be called by the framework when changes are made on
335: * registry (via {@link PluginRegistry#register(URL[])} or
336: * {@link PluginRegistry#unregister(String[])} methods).
337: *
338: * @param data
339: * registry changes data
340: */
341: void registryChanged(RegistryChangeData data);
342: }
343:
344: /**
345: * Registry changes data holder interface.
346: *
347: * @version $Id: PluginRegistry.java,v 1.5 2007/03/03 17:16:26 ddimon Exp $
348: */
349: interface RegistryChangeData {
350: /**
351: * @return collection of ID's of newly added plug-ins
352: */
353: Set<String> addedPlugins();
354:
355: /**
356: * @return collection of ID's of removed plug-ins
357: */
358: Set<String> removedPlugins();
359:
360: /**
361: * @return collection of ID's of changed plug-ins
362: */
363: Set<String> modifiedPlugins();
364:
365: /**
366: * @return collection of unique ID's of newly connected extensions
367: */
368: Set<String> addedExtensions();
369:
370: /**
371: * @param extensionPointUid
372: * unique ID of extension point to filter result
373: * @return collection of unique ID's of newly connected extensions
374: */
375: Set<String> addedExtensions(String extensionPointUid);
376:
377: /**
378: * @return collection of unique ID's of disconnected extensions
379: */
380: Set<String> removedExtensions();
381:
382: /**
383: * @param extensionPointUid
384: * unique ID of extension point to filter result
385: * @return collection of unique ID's of disconnected extensions
386: */
387: Set<String> removedExtensions(String extensionPointUid);
388:
389: /**
390: * @return collection of unique ID's of modified extensions
391: */
392: Set<String> modifiedExtensions();
393:
394: /**
395: * @param extensionPointUid
396: * unique ID of extension point to filter result
397: * @return collection of unique ID's of modified extensions
398: */
399: Set<String> modifiedExtensions(String extensionPointUid);
400: }
401: }
|