001: /*******************************************************************************
002: * Copyright (c) 2003, 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;
011:
012: import java.io.BufferedInputStream;
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.util.ArrayList;
016: import java.util.Collection;
017: import java.util.Collections;
018: import java.util.HashMap;
019: import java.util.ListIterator;
020: import java.util.Map;
021:
022: import org.eclipse.core.resources.IFile;
023: import org.eclipse.core.resources.IFolder;
024: import org.eclipse.core.resources.IProject;
025: import org.eclipse.core.resources.IResource;
026: import org.eclipse.core.resources.IResourceChangeEvent;
027: import org.eclipse.core.resources.IResourceChangeListener;
028: import org.eclipse.core.resources.IResourceDelta;
029: import org.eclipse.core.resources.IResourceDeltaVisitor;
030: import org.eclipse.core.runtime.CoreException;
031: import org.eclipse.pde.core.IModel;
032: import org.eclipse.pde.core.IModelProviderEvent;
033: import org.eclipse.team.core.RepositoryProvider;
034:
035: public abstract class WorkspaceModelManager extends
036: AbstractModelManager implements IResourceChangeListener,
037: IResourceDeltaVisitor {
038:
039: public static boolean isPluginProject(IProject project) {
040: if (project.isOpen())
041: return project.exists(ICoreConstants.MANIFEST_PATH)
042: || project.exists(ICoreConstants.PLUGIN_PATH)
043: || project.exists(ICoreConstants.FRAGMENT_PATH);
044: return false;
045: }
046:
047: public static boolean isFeatureProject(IProject project) {
048: return project.isOpen()
049: && project.exists(ICoreConstants.FEATURE_PATH);
050: }
051:
052: public static boolean isBinaryProject(IProject project) {
053: try {
054: if (project.isOpen()) {
055: String binary = project
056: .getPersistentProperty(PDECore.EXTERNAL_PROJECT_PROPERTY);
057: if (binary != null) {
058: RepositoryProvider provider = RepositoryProvider
059: .getProvider(project);
060: return provider == null
061: || provider instanceof BinaryRepositoryProvider;
062: }
063: }
064: } catch (CoreException e) {
065: PDECore.logException(e);
066: }
067: return false;
068: }
069:
070: public static boolean isUnsharedProject(IProject project) {
071: return RepositoryProvider.getProvider(project) == null
072: || isBinaryProject(project);
073: }
074:
075: class ModelChange {
076: IModel model;
077: int type;
078:
079: public ModelChange(IModel model, int type) {
080: this .model = model;
081: this .type = type;
082: }
083:
084: public boolean equals(Object obj) {
085: if (obj instanceof ModelChange) {
086: ModelChange change = (ModelChange) obj;
087: IProject project = change.model.getUnderlyingResource()
088: .getProject();
089: int type = change.type;
090: return model.getUnderlyingResource().getProject()
091: .equals(project)
092: && this .type == type;
093: }
094: return false;
095: }
096: }
097:
098: protected Map fModels = null;
099: private ArrayList fChangedModels;
100:
101: protected synchronized void initialize() {
102: if (fModels != null)
103: return;
104:
105: fModels = Collections.synchronizedMap(new HashMap());
106: IProject[] projects = PDECore.getWorkspace().getRoot()
107: .getProjects();
108: for (int i = 0; i < projects.length; i++) {
109: if (isInterestingProject(projects[i]))
110: createModel(projects[i], false);
111: }
112: addListeners();
113: }
114:
115: protected abstract boolean isInterestingProject(IProject project);
116:
117: protected abstract void createModel(IProject project, boolean notify);
118:
119: protected abstract void addListeners();
120:
121: protected Object getModel(IProject project) {
122: initialize();
123: return fModels.get(project);
124: }
125:
126: protected Object[] getModels() {
127: initialize();
128: return fModels.values().toArray();
129: }
130:
131: /*
132: * (non-Javadoc)
133: *
134: * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
135: */
136: public void resourceChanged(IResourceChangeEvent event) {
137: switch (event.getType()) {
138: case IResourceChangeEvent.POST_CHANGE:
139: handleResourceDelta(event.getDelta());
140: processModelChanges();
141: break;
142: case IResourceChangeEvent.PRE_CLOSE:
143: removeModel((IProject) event.getResource());
144: processModelChanges();
145: break;
146: }
147: }
148:
149: private void handleResourceDelta(IResourceDelta delta) {
150: try {
151: delta.accept(this );
152: } catch (CoreException e) {
153: PDECore.logException(e);
154: }
155: }
156:
157: /*
158: * (non-Javadoc)
159: * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
160: */
161: public boolean visit(IResourceDelta delta) throws CoreException {
162: if (delta != null) {
163: IResource resource = delta.getResource();
164: if (resource instanceof IProject) {
165: IProject project = (IProject) resource;
166: if (isInterestingProject(project)
167: && (delta.getKind() == IResourceDelta.ADDED || (delta
168: .getFlags() & IResourceDelta.OPEN) != 0)) {
169: createModel(project, true);
170: return false;
171: } else if (delta.getKind() == IResourceDelta.REMOVED) {
172: removeModel(project);
173: return false;
174: }
175: return true;
176: } else if (resource instanceof IFile) {
177: handleFileDelta(delta);
178: } else if (resource instanceof IFolder) {
179: return isInterestingFolder((IFolder) resource);
180: }
181: }
182: return true;
183: }
184:
185: protected boolean isInterestingFolder(IFolder folder) {
186: return false;
187: }
188:
189: protected abstract void handleFileDelta(IResourceDelta delta);
190:
191: protected Object removeModel(IProject project) {
192: Object model = fModels != null ? fModels.remove(project) : null;
193: addChange(model, IModelProviderEvent.MODELS_REMOVED);
194: return model;
195: }
196:
197: protected void addChange(Object model, int eventType) {
198: if (model instanceof IModel) {
199: if (fChangedModels == null)
200: fChangedModels = new ArrayList();
201: ModelChange change = new ModelChange((IModel) model,
202: eventType);
203: if (!fChangedModels.contains(change))
204: fChangedModels.add(change);
205: }
206: }
207:
208: protected void processModelChanges() {
209: processModelChanges(
210: "org.eclipse.pde.core.IModelProviderEvent", fChangedModels); //$NON-NLS-1$
211: fChangedModels = null;
212: }
213:
214: protected void processModelChanges(String changeId,
215: ArrayList changedModels) {
216: if (changedModels == null)
217: return;
218:
219: if (changedModels.size() == 0) {
220: return;
221: }
222:
223: ArrayList added = new ArrayList();
224: ArrayList removed = new ArrayList();
225: ArrayList changed = new ArrayList();
226: for (ListIterator li = changedModels.listIterator(); li
227: .hasNext();) {
228: ModelChange change = (ModelChange) li.next();
229: switch (change.type) {
230: case IModelProviderEvent.MODELS_ADDED:
231: added.add(change.model);
232: break;
233: case IModelProviderEvent.MODELS_REMOVED:
234: removed.add(change.model);
235: break;
236: case IModelProviderEvent.MODELS_CHANGED:
237: changed.add(change.model);
238: }
239: }
240:
241: int type = 0;
242: if (added.size() > 0)
243: type |= IModelProviderEvent.MODELS_ADDED;
244: if (removed.size() > 0)
245: type |= IModelProviderEvent.MODELS_REMOVED;
246: if (changed.size() > 0)
247: type |= IModelProviderEvent.MODELS_CHANGED;
248:
249: if (type != 0) {
250: createAndFireEvent(changeId, type, added, removed, changed);
251: }
252: }
253:
254: protected void loadModel(IModel model, boolean reload) {
255: IFile file = (IFile) model.getUnderlyingResource();
256: InputStream stream = null;
257: try {
258: stream = new BufferedInputStream(file.getContents(true));
259: if (reload)
260: model.reload(stream, false);
261: else
262: model.load(stream, false);
263: } catch (CoreException e) {
264: PDECore.logException(e);
265: } finally {
266: try {
267: if (stream != null)
268: stream.close();
269: } catch (IOException e) {
270: PDECore.log(e);
271: }
272: }
273: }
274:
275: protected void createAndFireEvent(String eventId, int type,
276: Collection added, Collection removed, Collection changed) {
277: if (eventId.equals("org.eclipse.pde.core.IModelProviderEvent")) { //$NON-NLS-1$
278: final ModelProviderEvent event = new ModelProviderEvent(
279: this , type, (IModel[]) added
280: .toArray(new IModel[added.size()]),
281: (IModel[]) removed.toArray(new IModel[removed
282: .size()]), (IModel[]) changed
283: .toArray(new IModel[changed.size()]));
284: fireModelProviderEvent(event);
285: }
286: }
287: }
|