001: /*
002: * uDig - User Friendly Desktop Internet GIS client
003: * http://udig.refractions.net
004: * (C) 2004, Refractions Research Inc.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package net.refractions.udig.core.internal;
018:
019: import java.util.Arrays;
020: import java.util.Collections;
021: import java.util.Comparator;
022:
023: import org.eclipse.core.runtime.IConfigurationElement;
024: import org.eclipse.core.runtime.IExtension;
025: import org.eclipse.core.runtime.IExtensionPoint;
026: import org.eclipse.core.runtime.IExtensionRegistry;
027: import org.eclipse.core.runtime.ILog;
028: import org.eclipse.core.runtime.IStatus;
029: import org.eclipse.core.runtime.Status;
030:
031: /**
032: * Abstract implementation of a registry reader that creates objects representing registry contents.
033: * <p>
034: * Typically, an extension contains one element, but this reader handles multiple elements per
035: * extension.
036: * </p>
037: * <p>
038: * To start reading the extensions from the registry for an extension point, call the method
039: * <code>readRegistry</code>.
040: * </p>
041: * <p>
042: * To read children of an IConfigurationElement, call the method <code>readElementChildren</code>
043: * from your implementation of the method <code>readElement</code>, as it will not be done by
044: * default.
045: * </p>
046: * <p>
047: * This class is similar to the internal class RegistryReader provided by the framework.
048: * </p>
049: */
050: public abstract class AbstractRegistryReader {
051: protected static final String TAG_DESCRIPTION = "description"; //$NON-NLS-1$
052: final private ILog pluginLog;
053: final private String pluginId;
054:
055: /**
056: * The constructor (requires a workbench for logging).
057: *
058: * @param log ILog for status messages
059: * @param id Plugin ID for status messages
060: */
061: protected AbstractRegistryReader(ILog log, String id) {
062: this .pluginLog = log;
063: this .pluginId = id;
064: }
065:
066: /**
067: * This method extracts description as a subelement of the given element.
068: *
069: * @param config Configuration defining extention point
070: * @return description string if defined, or empty string if not.
071: */
072: protected String getDescription(IConfigurationElement config) {
073: IConfigurationElement[] children = config
074: .getChildren(TAG_DESCRIPTION);
075: if (children.length >= 1) {
076: return children[0].getValue();
077: }
078: return "";//$NON-NLS-1$
079: }
080:
081: /**
082: * Logs the error in the plugin log using the provided text and the information in the
083: * configuration element.
084: *
085: * @param element
086: * @param text
087: */
088: protected void logError(IConfigurationElement element, String text) {
089: IExtension extension = element.getDeclaringExtension();
090: StringBuffer buf = new StringBuffer();
091: buf
092: .append("Plugin " + extension.getNamespace() + ", extension " + extension.getExtensionPointUniqueIdentifier());//$NON-NLS-2$//$NON-NLS-1$
093: buf.append("\n" + text);//$NON-NLS-1$
094: String message = buf.toString();
095:
096: this .pluginLog.log(newStatus(IStatus.ERROR, message, null));
097: System.err.println(message);
098: }
099:
100: /**
101: * Logs a very common registry error when a required attribute is missing.
102: *
103: * @param element
104: * @param attributeName
105: */
106: protected void logMissingAttribute(IConfigurationElement element,
107: String attributeName) {
108: logError(
109: element,
110: "Required attribute '" + attributeName + "' not defined");//$NON-NLS-2$//$NON-NLS-1$
111: }
112:
113: /**
114: * Logs a very common registry error when a required child is missing.
115: *
116: * @param element
117: * @param elementName
118: */
119: protected void logMissingElement(IConfigurationElement element,
120: String elementName) {
121: logError(
122: element,
123: "Required sub element '" + elementName + "' not defined");//$NON-NLS-2$//$NON-NLS-1$
124: }
125:
126: /**
127: * Logs a registry error when the configuration element is unknown.
128: *
129: * @param element
130: */
131: protected void logUnknownElement(IConfigurationElement element) {
132: logError(element,
133: "Unknown extension tag found: " + element.getName());//$NON-NLS-1$
134: }
135:
136: /**
137: * IStatus creations (with respect to plugin id).
138: *
139: * @param severity IStatus constant such as IStatus.OK, or IStatus.ERROR
140: * @param message Status message
141: * @param exception Cause of message, may be null
142: * @return IStatus suitable for use with plugin.getLog.log( IStatus )
143: */
144: protected IStatus newStatus(int severity, String message,
145: Throwable exception) {
146: String statusMessage = message;
147: if (message == null || message.trim().length() == 0) {
148: if (exception.getMessage() == null)
149: statusMessage = exception.toString();
150: else
151: statusMessage = exception.getMessage();
152: }
153: // Not sure if this is the correct way to grab Id
154: return new Status(severity, pluginId, severity, statusMessage,
155: exception);
156: }
157:
158: /**
159: * Apply a reproducable order to the list of extensions provided, such that the order will not
160: * change as extensions are added or removed.
161: *
162: * @param extensions Ordered Extentions
163: * @return IExtentions
164: */
165: @SuppressWarnings("unchecked")
166: protected IExtension[] orderExtensions(IExtension[] extensions) {
167: // By default, the order is based on plugin id sorted
168: // in ascending order. The order for a plugin providing
169: // more than one extension for an extension point is
170: // dependent in the order listed in the XML file.
171: IExtension[] sortedExtension = new IExtension[extensions.length];
172: System.arraycopy(extensions, 0, sortedExtension, 0,
173: extensions.length);
174: Comparator comparer = new Comparator() {
175: public int compare(Object arg0, Object arg1) {
176: String s1 = ((IExtension) arg0).getNamespace();
177: String s2 = ((IExtension) arg1).getNamespace();
178: return s1.compareToIgnoreCase(s2);
179: }
180: };
181: Collections.sort(Arrays.asList(sortedExtension), comparer);
182: return sortedExtension;
183: }
184:
185: /**
186: * Implement this method to read element's attributes. If children should also be read, then
187: * implementor is responsible for calling <code>readElementChildren</code>. Implementor is
188: * also responsible for logging missing attributes.
189: *
190: * @param element
191: * @return true if element was recognized, false if not.
192: */
193: protected abstract boolean readElement(IConfigurationElement element);
194:
195: /**
196: * Read the element's children. This is called by the subclass' readElement method when it wants
197: * to read the children of the element.
198: *
199: * @param element
200: */
201: protected void readElementChildren(IConfigurationElement element) {
202: readElements(element.getChildren());
203: }
204:
205: /**
206: * Read each element one at a time by calling the subclass implementation of
207: * <code>readElement</code>. Logs an error if the element was not recognized.
208: *
209: * @param elements
210: */
211: protected void readElements(IConfigurationElement[] elements) {
212: for (int i = 0; i < elements.length; i++) {
213: if (!readElement(elements[i]))
214: logUnknownElement(elements[i]);
215: }
216: }
217:
218: /**
219: * Read one extension by looping through its configuration elements.
220: *
221: * @param extension
222: */
223: protected void readExtension(IExtension extension) {
224: readElements(extension.getConfigurationElements());
225: }
226:
227: /**
228: * Start the registry reading process using the supplied plugin ID and extension point.
229: *
230: * @param registry
231: * @param targetPluginId
232: * @param extensionPoint
233: */
234: public void readRegistry(IExtensionRegistry registry,
235: String targetPluginId, String extensionPoint) {
236: IExtensionPoint point = registry.getExtensionPoint(
237: targetPluginId, extensionPoint);
238: if (point == null)
239: return;
240: IExtension[] extensions = point.getExtensions();
241: extensions = orderExtensions(extensions);
242: for (int i = 0; i < extensions.length; i++)
243: readExtension(extensions[i]);
244: }
245: }
|