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.pde.internal.core;
011:
012: import java.io.BufferedInputStream;
013: import java.io.File;
014: import java.io.FileInputStream;
015: import java.io.IOException;
016: import java.io.InputStream;
017: import java.net.URL;
018: import java.util.ArrayList;
019: import java.util.Collection;
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.Map;
023: import java.util.StringTokenizer;
024: import java.util.Vector;
025:
026: import org.eclipse.core.runtime.IProgressMonitor;
027: import org.eclipse.core.runtime.NullProgressMonitor;
028: import org.eclipse.core.runtime.Preferences;
029: import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
030: import org.eclipse.pde.core.IModelProviderEvent;
031: import org.eclipse.pde.core.IModelProviderListener;
032: import org.eclipse.pde.internal.core.feature.ExternalFeatureModel;
033: import org.eclipse.pde.internal.core.ifeature.IFeature;
034: import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
035:
036: public class ExternalFeatureModelManager implements
037: Preferences.IPropertyChangeListener {
038:
039: /**
040: *
041: * @param manifest
042: * @return ExternalFeatureModel or null
043: */
044: private static IFeatureModel createModel(File manifest) {
045: ExternalFeatureModel model = new ExternalFeatureModel();
046: model.setInstallLocation(manifest.getParent());
047: InputStream stream = null;
048: try {
049: stream = new BufferedInputStream(new FileInputStream(
050: manifest));
051: model.load(stream, false);
052: return model;
053: } catch (Exception e) {
054: } finally {
055: if (stream != null) {
056: try {
057: stream.close();
058: } catch (IOException e) {
059: }
060: }
061: }
062: return null;
063: }
064:
065: private static IFeatureModel[] createModels(URL[] featurePaths,
066: IProgressMonitor monitor) {
067: if (monitor == null)
068: monitor = new NullProgressMonitor();
069: monitor.beginTask("", featurePaths.length); //$NON-NLS-1$
070: Map uniqueFeatures = new HashMap();
071: for (int i = 0; i < featurePaths.length; i++) {
072: File manifest = new File(featurePaths[i].getFile(),
073: "feature.xml"); //$NON-NLS-1$
074: if (!manifest.exists() || !manifest.isFile()) {
075: monitor.worked(1);
076: continue;
077: }
078: IFeatureModel model = createModel(manifest);
079: if (model != null && model.isLoaded()) {
080: IFeature feature = model.getFeature();
081: uniqueFeatures.put(feature.getId()
082: + "_" + feature.getVersion(), model); //$NON-NLS-1$
083: }
084: monitor.worked(1);
085: }
086: Collection models = uniqueFeatures.values();
087: return (IFeatureModel[]) models
088: .toArray(new IFeatureModel[models.size()]);
089: }
090:
091: private Vector fListeners = new Vector();
092:
093: private IFeatureModel[] fModels;
094:
095: private String fPlatformHome;
096:
097: private Preferences fPref;
098:
099: public ExternalFeatureModelManager() {
100: fPref = PDECore.getDefault().getPluginPreferences();
101: }
102:
103: public void addModelProviderListener(IModelProviderListener listener) {
104: fListeners.add(listener);
105: }
106:
107: private boolean equalPaths(String path1, String path2) {
108: if (path1 == null) {
109: if (path2 == null) {
110: return true;
111: }
112: return false;
113: }
114: if (path2 == null) {
115: return false;
116: }
117: return new File(path1).equals(new File(path2));
118:
119: }
120:
121: private void fireModelProviderEvent(IModelProviderEvent e) {
122: for (Iterator iter = fListeners.iterator(); iter.hasNext();) {
123: IModelProviderListener listener = (IModelProviderListener) iter
124: .next();
125: listener.modelsChanged(e);
126: }
127: }
128:
129: /**
130: * @param propertyValue
131: * @return String or null
132: */
133: private String getPathString(Object propertyValue) {
134: if (propertyValue != null && propertyValue instanceof String) {
135: String path = (String) propertyValue;
136: if (path.length() > 0) {
137: return path;
138: }
139: }
140: return null;
141: }
142:
143: public static IFeatureModel[] createModels(String platformHome,
144: ArrayList additionalLocations, IProgressMonitor monitor) {
145: if (platformHome != null && platformHome.length() > 0) {
146: URL[] featureURLs = PluginPathFinder
147: .getFeaturePaths(platformHome);
148:
149: if (additionalLocations.size() == 0)
150: return createModels(featureURLs, monitor);
151:
152: File[] dirs = new File[additionalLocations.size()];
153: for (int i = 0; i < dirs.length; i++) {
154: String directory = additionalLocations.get(i)
155: .toString();
156: File dir = new File(directory, "features"); //$NON-NLS-1$
157: if (!dir.exists())
158: dir = new File(directory);
159: dirs[i] = dir;
160: }
161:
162: URL[] newUrls = PluginPathFinder.scanLocations(dirs);
163:
164: URL[] result = new URL[featureURLs.length + newUrls.length];
165: System.arraycopy(featureURLs, 0, result, 0,
166: featureURLs.length);
167: System.arraycopy(newUrls, 0, result, featureURLs.length,
168: newUrls.length);
169: return createModels(result, monitor);
170: }
171: return new IFeatureModel[0];
172: }
173:
174: public void loadModels(String platformHome,
175: String additionalLocations) {
176: IFeatureModel[] oldModels = fModels != null ? fModels
177: : new IFeatureModel[0];
178: fModels = createModels(platformHome,
179: parseAdditionalLocations(additionalLocations), null);
180: fPlatformHome = platformHome;
181: notifyListeners(oldModels, fModels);
182: }
183:
184: private ArrayList parseAdditionalLocations(
185: String additionalLocations) {
186: ArrayList result = new ArrayList();
187: StringTokenizer tokenizer = new StringTokenizer(
188: additionalLocations, ","); //$NON-NLS-1$
189: while (tokenizer.hasMoreTokens()) {
190: result.add(tokenizer.nextToken().trim());
191: }
192: return result;
193: }
194:
195: private void notifyListeners(IFeatureModel[] oldModels,
196: IFeatureModel[] newFeatureModels) {
197: if (oldModels.length > 0 || newFeatureModels.length > 0) {
198: int type = 0;
199: if (oldModels.length > 0)
200: type |= IModelProviderEvent.MODELS_REMOVED;
201: if (newFeatureModels.length > 0)
202: type |= IModelProviderEvent.MODELS_ADDED;
203: ModelProviderEvent replacedFeatures = new ModelProviderEvent(
204: this , type, newFeatureModels, oldModels, null);
205: fireModelProviderEvent(replacedFeatures);
206: }
207:
208: }
209:
210: private synchronized void platformPathChanged(String newHome) {
211: if (!equalPaths(newHome, fPlatformHome)) {
212: loadModels(newHome, fPref
213: .getString(ICoreConstants.ADDITIONAL_LOCATIONS));
214: }
215: }
216:
217: public void propertyChange(PropertyChangeEvent event) {
218: if (!ICoreConstants.PLATFORM_PATH.equals(event.getProperty())) {
219: return;
220: }
221: String newHome = getPathString(event.getNewValue());
222: platformPathChanged(newHome);
223: }
224:
225: public void removeModelProviderListener(
226: IModelProviderListener listener) {
227: fListeners.remove(listener);
228: }
229:
230: public synchronized void shutdown() {
231: fPref.removePropertyChangeListener(this );
232: }
233:
234: public synchronized void startup() {
235: fPref.addPropertyChangeListener(this );
236: loadModels(fPref.getString(ICoreConstants.PLATFORM_PATH), fPref
237: .getString(ICoreConstants.ADDITIONAL_LOCATIONS));
238: }
239:
240: public synchronized void reload() {
241: loadModels(fPref.getString(ICoreConstants.PLATFORM_PATH), fPref
242: .getString(ICoreConstants.ADDITIONAL_LOCATIONS));
243: }
244:
245: public IFeatureModel[] getModels() {
246: return fModels;
247: }
248: }
|