001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 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.pde.internal.core.plugin;
011:
012: import java.util.ArrayList;
013: import java.util.Locale;
014:
015: import javax.xml.parsers.FactoryConfigurationError;
016: import javax.xml.parsers.ParserConfigurationException;
017: import javax.xml.parsers.SAXParser;
018: import javax.xml.parsers.SAXParserFactory;
019:
020: import org.eclipse.core.runtime.CoreException;
021: import org.eclipse.osgi.service.resolver.BundleDescription;
022: import org.eclipse.osgi.service.resolver.BundleSpecification;
023: import org.eclipse.osgi.service.resolver.VersionRange;
024: import org.eclipse.pde.core.IModelChangedEvent;
025: import org.eclipse.pde.core.plugin.IMatchRules;
026: import org.eclipse.pde.core.plugin.IPluginBase;
027: import org.eclipse.pde.core.plugin.IPluginImport;
028: import org.eclipse.pde.core.plugin.IPluginLibrary;
029: import org.eclipse.pde.internal.core.PDECoreMessages;
030: import org.eclipse.pde.internal.core.PDEState;
031: import org.eclipse.pde.internal.core.PDEStateHelper;
032: import org.osgi.framework.Version;
033: import org.w3c.dom.Node;
034: import org.w3c.dom.NodeList;
035: import org.xml.sax.SAXException;
036:
037: public abstract class PluginBase extends AbstractExtensions implements
038: IPluginBase {
039: private static final Version maxVersion = new Version(
040: Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
041:
042: private ArrayList fLibraries = new ArrayList();
043: private ArrayList fImports = new ArrayList();
044: private String fProviderName;
045: private String fId;
046: private String fVersion;
047: private boolean fHasBundleStructure;
048:
049: public PluginBase(boolean readOnly) {
050: super (readOnly);
051: }
052:
053: public void add(IPluginLibrary library) throws CoreException {
054: ensureModelEditable();
055: fLibraries.add(library);
056: ((PluginLibrary) library).setInTheModel(true);
057: ((PluginLibrary) library).setParent(this );
058: fireStructureChanged(library, IModelChangedEvent.INSERT);
059: }
060:
061: public void add(IPluginImport iimport) throws CoreException {
062: ensureModelEditable();
063: ((PluginImport) iimport).setInTheModel(true);
064: ((PluginImport) iimport).setParent(this );
065: fImports.add(iimport);
066: fireStructureChanged(iimport, IModelChangedEvent.INSERT);
067: }
068:
069: public void add(IPluginImport[] iimports) throws CoreException {
070: ensureModelEditable();
071: for (int i = 0; i < iimports.length; i++) {
072: ((PluginImport) iimports[i]).setInTheModel(true);
073: ((PluginImport) iimports[i]).setParent(this );
074: fImports.add(iimports[i]);
075: }
076: fireStructureChanged(iimports, IModelChangedEvent.INSERT);
077: }
078:
079: public IPluginLibrary[] getLibraries() {
080: return (IPluginLibrary[]) fLibraries
081: .toArray(new IPluginLibrary[fLibraries.size()]);
082: }
083:
084: public IPluginImport[] getImports() {
085: return (IPluginImport[]) fImports
086: .toArray(new IPluginImport[fImports.size()]);
087: }
088:
089: public IPluginBase getPluginBase() {
090: return this ;
091: }
092:
093: public String getProviderName() {
094: return fProviderName;
095: }
096:
097: public String getVersion() {
098: return fVersion;
099: }
100:
101: public String getId() {
102: return fId;
103: }
104:
105: void load(BundleDescription bundleDesc, PDEState state) {
106: fId = bundleDesc.getSymbolicName();
107: fVersion = bundleDesc.getVersion().toString();
108: fName = state.getPluginName(bundleDesc.getBundleId());
109: fProviderName = state.getProviderName(bundleDesc.getBundleId());
110: fHasBundleStructure = state.hasBundleStructure(bundleDesc
111: .getBundleId());
112: loadRuntime(bundleDesc, state);
113: loadImports(bundleDesc);
114: }
115:
116: public void restoreProperty(String name, Object oldValue,
117: Object newValue) throws CoreException {
118: if (name.equals(P_ID)) {
119: setId(newValue != null ? newValue.toString() : null);
120: return;
121: }
122: if (name.equals(P_VERSION)) {
123: setVersion(newValue != null ? newValue.toString() : null);
124: return;
125: }
126: if (name.equals(P_PROVIDER)) {
127: setProviderName(newValue != null ? newValue.toString()
128: : null);
129: return;
130: }
131: if (name.equals(P_LIBRARY_ORDER)) {
132: swap((IPluginLibrary) oldValue, (IPluginLibrary) newValue);
133: return;
134: }
135: super .restoreProperty(name, oldValue, newValue);
136: }
137:
138: void load(Node node, String schemaVersion) {
139: if (node == null)
140: return;
141: fSchemaVersion = schemaVersion;
142: fId = getNodeAttribute(node, "id"); //$NON-NLS-1$
143: fName = getNodeAttribute(node, "name"); //$NON-NLS-1$
144: fProviderName = getNodeAttribute(node, "provider-name"); //$NON-NLS-1$
145: fVersion = getNodeAttribute(node, "version"); //$NON-NLS-1$
146:
147: NodeList children = node.getChildNodes();
148: for (int i = 0; i < children.getLength(); i++) {
149: Node child = children.item(i);
150: if (child.getNodeType() == Node.ELEMENT_NODE) {
151: processChild(child);
152: }
153: }
154: }
155:
156: void loadRuntime(BundleDescription description, PDEState state) {
157: String[] libraryNames = state.getLibraryNames(description
158: .getBundleId());
159: for (int i = 0; i < libraryNames.length; i++) {
160: PluginLibrary library = new PluginLibrary();
161: library.setModel(getModel());
162: library.setInTheModel(true);
163: library.setParent(this );
164: library.load(libraryNames[i]);
165: fLibraries.add(library);
166: }
167: }
168:
169: void loadRuntime(Node node) {
170: NodeList children = node.getChildNodes();
171: for (int i = 0; i < children.getLength(); i++) {
172: Node child = children.item(i);
173: if (child.getNodeType() == Node.ELEMENT_NODE
174: && child.getNodeName().toLowerCase(Locale.ENGLISH)
175: .equals("library")) { //$NON-NLS-1$
176: PluginLibrary library = new PluginLibrary();
177: library.setModel(getModel());
178: library.setInTheModel(true);
179: library.setParent(this );
180: fLibraries.add(library);
181: library.load(child);
182: }
183: }
184: }
185:
186: void loadImports(BundleDescription description) {
187: BundleSpecification[] required = description
188: .getRequiredBundles();
189: for (int i = 0; i < required.length; i++) {
190: PluginImport importElement = new PluginImport();
191: importElement.setModel(getModel());
192: importElement.setInTheModel(true);
193: importElement.setParent(this );
194: fImports.add(importElement);
195: importElement.load(required[i]);
196: }
197: BundleDescription[] imported = PDEStateHelper
198: .getImportedBundles(description);
199: for (int i = 0; i < imported.length; i++) {
200: PluginImport importElement = new PluginImport();
201: importElement.setModel(getModel());
202: importElement.setInTheModel(true);
203: importElement.setParent(this );
204: fImports.add(importElement);
205: importElement.load(imported[i]);
206: }
207: }
208:
209: void loadImports(Node node) {
210: NodeList children = node.getChildNodes();
211: for (int i = 0; i < children.getLength(); i++) {
212: Node child = children.item(i);
213: if (child.getNodeType() == Node.ELEMENT_NODE
214: && child.getNodeName().toLowerCase(Locale.ENGLISH)
215: .equals("import")) { //$NON-NLS-1$
216: PluginImport importElement = new PluginImport();
217: importElement.setModel(getModel());
218: importElement.setInTheModel(true);
219: importElement.setParent(this );
220: fImports.add(importElement);
221: importElement.load(child);
222: }
223: }
224: }
225:
226: protected void processChild(Node child) {
227: String name = child.getNodeName().toLowerCase(Locale.ENGLISH);
228: if (name.equals("runtime")) { //$NON-NLS-1$
229: loadRuntime(child);
230: } else if (name.equals("requires")) { //$NON-NLS-1$
231: loadImports(child);
232: }
233: }
234:
235: public void remove(IPluginLibrary library) throws CoreException {
236: ensureModelEditable();
237: fLibraries.remove(library);
238: ((PluginLibrary) library).setInTheModel(false);
239: fireStructureChanged(library, IModelChangedEvent.REMOVE);
240: }
241:
242: public void remove(IPluginImport iimport) throws CoreException {
243: ensureModelEditable();
244: fImports.remove(iimport);
245: ((PluginImport) iimport).setInTheModel(false);
246: fireStructureChanged(iimport, IModelChangedEvent.REMOVE);
247: }
248:
249: public void remove(IPluginImport[] iimports) throws CoreException {
250: ensureModelEditable();
251: for (int i = 0; i < iimports.length; i++) {
252: fImports.remove(iimports[i]);
253: ((PluginImport) iimports[i]).setInTheModel(false);
254: }
255: fireStructureChanged(iimports, IModelChangedEvent.REMOVE);
256: }
257:
258: public void reset() {
259: fLibraries = new ArrayList();
260: fImports = new ArrayList();
261: fProviderName = null;
262: fSchemaVersion = null;
263: fVersion = ""; //$NON-NLS-1$
264: fName = ""; //$NON-NLS-1$
265: fId = ""; //$NON-NLS-1$
266: if (getModel() != null
267: && getModel().getUnderlyingResource() != null) {
268: fId = getModel().getUnderlyingResource().getProject()
269: .getName();
270: fName = fId;
271: fVersion = "0.0.0"; //$NON-NLS-1$
272: }
273: super .reset();
274: }
275:
276: public void setProviderName(String providerName)
277: throws CoreException {
278: ensureModelEditable();
279: String oldValue = fProviderName;
280: fProviderName = providerName;
281: firePropertyChanged(P_PROVIDER, oldValue, fProviderName);
282: }
283:
284: public void setVersion(String newVersion) throws CoreException {
285: ensureModelEditable();
286: String oldValue = fVersion;
287: fVersion = newVersion;
288: firePropertyChanged(P_VERSION, oldValue, fVersion);
289: }
290:
291: public void setId(String newId) throws CoreException {
292: ensureModelEditable();
293: String oldValue = fId;
294: fId = newId;
295: firePropertyChanged(P_ID, oldValue, fId);
296: }
297:
298: public void internalSetVersion(String newVersion) {
299: fVersion = newVersion;
300: }
301:
302: public void swap(IPluginLibrary l1, IPluginLibrary l2)
303: throws CoreException {
304: ensureModelEditable();
305: int index1 = fLibraries.indexOf(l1);
306: int index2 = fLibraries.indexOf(l2);
307: if (index1 == -1 || index2 == -1)
308: throwCoreException(PDECoreMessages.PluginBase_librariesNotFoundException);
309: fLibraries.set(index2, l1);
310: fLibraries.set(index1, l2);
311: firePropertyChanged(this , P_LIBRARY_ORDER, l1, l2);
312: }
313:
314: /* (non-Javadoc)
315: * @see org.eclipse.pde.core.plugin.IPluginBase#swap(org.eclipse.pde.core.plugin.IPluginImport, org.eclipse.pde.core.plugin.IPluginImport)
316: */
317: public void swap(IPluginImport import1, IPluginImport import2)
318: throws CoreException {
319: ensureModelEditable();
320: int index1 = fImports.indexOf(import1);
321: int index2 = fImports.indexOf(import2);
322: if (index1 == -1 || index2 == -1)
323: throwCoreException(PDECoreMessages.PluginBase_importsNotFoundException);
324: fImports.set(index2, import1);
325: fImports.set(index1, import2);
326: firePropertyChanged(this , P_IMPORT_ORDER, import1, import2);
327: }
328:
329: public boolean isValid() {
330: return hasRequiredAttributes();
331: }
332:
333: protected boolean hasRequiredAttributes() {
334: if (fName == null)
335: return false;
336: if (fId == null)
337: return false;
338: if (fVersion == null)
339: return false;
340:
341: // validate libraries
342: for (int i = 0; i < fLibraries.size(); i++) {
343: IPluginLibrary library = (IPluginLibrary) fLibraries.get(i);
344: if (!library.isValid())
345: return false;
346: }
347: // validate imports
348: for (int i = 0; i < fImports.size(); i++) {
349: IPluginImport iimport = (IPluginImport) fImports.get(i);
350: if (!iimport.isValid())
351: return false;
352: }
353: return super .hasRequiredAttributes();
354: }
355:
356: protected SAXParser getSaxParser()
357: throws ParserConfigurationException, SAXException,
358: FactoryConfigurationError {
359: return SAXParserFactory.newInstance().newSAXParser();
360: }
361:
362: public static int getMatchRule(VersionRange versionRange) {
363: if (versionRange == null || versionRange.getMinimum() == null)
364: return IMatchRules.NONE;
365:
366: Version minimum = versionRange.getMinimum();
367: Version maximum = versionRange.getMaximum() == null ? maxVersion
368: : versionRange.getMaximum();
369:
370: if (maximum.compareTo(maxVersion) >= 0)
371: return IMatchRules.GREATER_OR_EQUAL;
372: else if (minimum.equals(maximum))
373: return IMatchRules.PERFECT;
374: else if (!versionRange.isIncluded(minimum)
375: || versionRange.isIncluded(maximum))
376: return IMatchRules.NONE; // no real match rule for this
377: else if (minimum.getMajor() == maximum.getMajor() - 1)
378: return IMatchRules.COMPATIBLE;
379: else if (minimum.getMajor() != maximum.getMajor())
380: return IMatchRules.NONE; // no real match rule for this
381: else if (minimum.getMinor() == maximum.getMinor() - 1)
382: return IMatchRules.EQUIVALENT;
383: else if (minimum.getMinor() != maximum.getMinor())
384: return IMatchRules.NONE; // no real match rule for this
385: else if (minimum.getMicro() == maximum.getMicro() - 1)
386: return IMatchRules.PERFECT; // this is as close as we got
387:
388: return IMatchRules.NONE; // no real match rule for this
389: }
390:
391: public boolean hasBundleStructure() {
392: return fHasBundleStructure;
393: }
394:
395: }
|