001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.ide.registry;
011:
012: import java.util.Arrays;
013: import java.util.Collections;
014: import java.util.Comparator;
015: import java.util.Hashtable;
016:
017: import org.eclipse.core.runtime.IConfigurationElement;
018: import org.eclipse.core.runtime.IExtension;
019: import org.eclipse.core.runtime.IExtensionPoint;
020: import org.eclipse.core.runtime.IExtensionRegistry;
021: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
022:
023: /**
024: * Template implementation of a registry reader that creates objects
025: * representing registry contents. Typically, an extension
026: * contains one element, but this reader handles multiple
027: * elements per extension.
028: *
029: * To start reading the extensions from the registry for an
030: * extension point, call the method <code>readRegistry</code>.
031: *
032: * To read children of an IConfigurationElement, call the
033: * method <code>readElementChildren</code> from your implementation
034: * of the method <code>readElement</code>, as it will not be
035: * done by default.
036: */
037: public abstract class IDERegistryReader {
038: protected static final String TAG_DESCRIPTION = "description"; //$NON-NLS-1$
039:
040: protected static Hashtable extensionPoints = new Hashtable();
041:
042: private static final Comparator comparer = new Comparator() {
043: public int compare(Object arg0, Object arg1) {
044: IExtension i1 = (IExtension) arg0;
045: String s1 = i1.getNamespace();
046: IExtension i2 = (IExtension) arg1;
047: String s2 = i2.getNamespace();
048: return s1.compareToIgnoreCase(s2);
049: }
050: };
051:
052: /**
053: * The constructor.
054: */
055: protected IDERegistryReader() {
056: }
057:
058: /**
059: * This method extracts description as a subelement of
060: * the given element.
061: * @return description string if defined, or empty string
062: * if not.
063: */
064: protected String getDescription(IConfigurationElement config) {
065: IConfigurationElement[] children = config
066: .getChildren(TAG_DESCRIPTION);
067: if (children.length >= 1) {
068: return children[0].getValue();
069: }
070: return "";//$NON-NLS-1$
071: }
072:
073: /**
074: * Logs the error in the workbench log using the provided
075: * text and the information in the configuration element.
076: */
077: protected void logError(IConfigurationElement element, String text) {
078: IExtension extension = element.getDeclaringExtension();
079: String pluginId = extension.getNamespace();
080: StringBuffer buf = new StringBuffer();
081: buf.append("Plugin " + pluginId + ", extension " //$NON-NLS-2$//$NON-NLS-1$
082: + extension.getExtensionPointUniqueIdentifier());
083: buf.append("\n" + text);//$NON-NLS-1$
084: IDEWorkbenchPlugin.log(buf.toString());
085: }
086:
087: /**
088: * Logs a very common registry error when a required attribute is missing.
089: */
090: protected void logMissingAttribute(IConfigurationElement element,
091: String attributeName) {
092: logError(
093: element,
094: "Required attribute '" + attributeName + "' not defined");//$NON-NLS-2$//$NON-NLS-1$
095: }
096:
097: /**
098: * Logs a very common registry error when a required child is missing.
099: */
100: protected void logMissingElement(IConfigurationElement element,
101: String elementName) {
102: logError(
103: element,
104: "Required sub element '" + elementName + "' not defined");//$NON-NLS-2$//$NON-NLS-1$
105: }
106:
107: /**
108: * Logs a registry error when the configuration element is unknown.
109: */
110: protected void logUnknownElement(IConfigurationElement element) {
111: logError(element,
112: "Unknown extension tag found: " + element.getName());//$NON-NLS-1$
113: }
114:
115: /**
116: * Apply a reproducable order to the list of extensions
117: * provided, such that the order will not change as
118: * extensions are added or removed.
119: */
120: protected IExtension[] orderExtensions(IExtension[] extensions) {
121: // By default, the order is based on plugin id sorted
122: // in ascending order. The order for a plugin providing
123: // more than one extension for an extension point is
124: // dependent in the order listed in the XML file.
125: IExtension[] sortedExtension = new IExtension[extensions.length];
126: System.arraycopy(extensions, 0, sortedExtension, 0,
127: extensions.length);
128: Collections.sort(Arrays.asList(sortedExtension), comparer);
129: return sortedExtension;
130: }
131:
132: /**
133: * Implement this method to read element's attributes.
134: * If children should also be read, then implementor
135: * is responsible for calling <code>readElementChildren</code>.
136: * Implementor is also responsible for logging missing
137: * attributes.
138: *
139: * @return true if element was recognized, false if not.
140: */
141: protected abstract boolean readElement(IConfigurationElement element);
142:
143: /**
144: * Read the element's children. This is called by
145: * the subclass' readElement method when it wants
146: * to read the children of the element.
147: */
148: protected void readElementChildren(IConfigurationElement element) {
149: readElements(element.getChildren());
150: }
151:
152: /**
153: * Read each element one at a time by calling the
154: * subclass implementation of <code>readElement</code>.
155: *
156: * Logs an error if the element was not recognized.
157: */
158: protected void readElements(IConfigurationElement[] elements) {
159: for (int i = 0; i < elements.length; i++) {
160: if (!readElement(elements[i])) {
161: logUnknownElement(elements[i]);
162: }
163: }
164: }
165:
166: /**
167: * Read one extension by looping through its
168: * configuration elements.
169: */
170: protected void readExtension(IExtension extension) {
171: readElements(extension.getConfigurationElements());
172: }
173:
174: /**
175: * Start the registry reading process using the
176: * supplied plugin ID and extension point.
177: */
178: protected void readRegistry(IExtensionRegistry registry,
179: String pluginId, String extensionPoint) {
180: String pointId = pluginId + "-" + extensionPoint; //$NON-NLS-1$
181: IExtension[] extensions = (IExtension[]) extensionPoints
182: .get(pointId);
183: if (extensions == null) {
184: IExtensionPoint point = registry.getExtensionPoint(
185: pluginId, extensionPoint);
186: if (point == null) {
187: return;
188: }
189: extensions = point.getExtensions();
190: extensions = orderExtensions(extensions);
191: extensionPoints.put(pointId, extensions);
192: }
193: for (int i = 0; i < extensions.length; i++) {
194: readExtension(extensions[i]);
195: }
196: }
197: }
|