Lines 11-30
Link Here
|
11 |
|
11 |
|
12 |
package org.eclipse.gmf.runtime.emf.core.internal.resources; |
12 |
package org.eclipse.gmf.runtime.emf.core.internal.resources; |
13 |
|
13 |
|
|
|
14 |
import java.io.File; |
14 |
import java.io.IOException; |
15 |
import java.io.IOException; |
15 |
import java.net.URL; |
16 |
import java.net.URL; |
16 |
import java.util.Collection; |
17 |
import java.util.Collection; |
17 |
import java.util.Collections; |
18 |
import java.util.Collections; |
18 |
import java.util.HashMap; |
19 |
import java.util.HashMap; |
|
|
20 |
import java.util.HashSet; |
19 |
import java.util.Iterator; |
21 |
import java.util.Iterator; |
20 |
import java.util.List; |
22 |
import java.util.List; |
21 |
import java.util.Map; |
23 |
import java.util.Map; |
22 |
import java.util.Set; |
24 |
import java.util.Set; |
|
|
25 |
import java.util.StringTokenizer; |
23 |
import java.util.WeakHashMap; |
26 |
import java.util.WeakHashMap; |
24 |
import java.util.Map.Entry; |
27 |
import java.util.Map.Entry; |
25 |
|
28 |
|
|
|
29 |
import org.eclipse.core.resources.IContainer; |
30 |
import org.eclipse.core.resources.IFile; |
31 |
import org.eclipse.core.resources.IPathVariableChangeEvent; |
32 |
import org.eclipse.core.resources.IPathVariableChangeListener; |
33 |
import org.eclipse.core.resources.IPathVariableManager; |
34 |
import org.eclipse.core.resources.ResourcesPlugin; |
35 |
import org.eclipse.core.runtime.FileLocator; |
26 |
import org.eclipse.core.runtime.IConfigurationElement; |
36 |
import org.eclipse.core.runtime.IConfigurationElement; |
|
|
37 |
import org.eclipse.core.runtime.IPath; |
38 |
import org.eclipse.core.runtime.IStatus; |
27 |
import org.eclipse.core.runtime.Platform; |
39 |
import org.eclipse.core.runtime.Platform; |
|
|
40 |
import org.eclipse.core.runtime.Status; |
41 |
import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
42 |
import org.eclipse.core.runtime.preferences.IScopeContext; |
43 |
import org.eclipse.core.runtime.preferences.InstanceScope; |
44 |
import org.eclipse.emf.common.notify.Notification; |
28 |
import org.eclipse.emf.common.notify.Notifier; |
45 |
import org.eclipse.emf.common.notify.Notifier; |
29 |
import org.eclipse.emf.common.notify.impl.AdapterImpl; |
46 |
import org.eclipse.emf.common.notify.impl.AdapterImpl; |
30 |
import org.eclipse.emf.common.util.URI; |
47 |
import org.eclipse.emf.common.util.URI; |
Lines 37-42
Link Here
|
37 |
import org.eclipse.gmf.runtime.emf.core.internal.util.EMFCoreConstants; |
54 |
import org.eclipse.gmf.runtime.emf.core.internal.util.EMFCoreConstants; |
38 |
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil; |
55 |
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil; |
39 |
import org.osgi.framework.Bundle; |
56 |
import org.osgi.framework.Bundle; |
|
|
57 |
import org.osgi.service.prefs.BackingStoreException; |
40 |
|
58 |
|
41 |
/** |
59 |
/** |
42 |
* This class manages GMF path mappings for URI conversion. |
60 |
* This class manages GMF path mappings for URI conversion. |
Lines 44-51
Link Here
|
44 |
* @author rafikj |
62 |
* @author rafikj |
45 |
*/ |
63 |
*/ |
46 |
public class PathmapManager extends AdapterImpl { |
64 |
public class PathmapManager extends AdapterImpl { |
47 |
|
65 |
// path maps can be defined using an extension point: Pathmaps |
48 |
// path maps can be defined using an extension point: Pathmaps. |
66 |
// or by referencing an eclipse path variable |
|
|
67 |
// or by adding a pathmap manually |
49 |
|
68 |
|
50 |
// The variable name. |
69 |
// The variable name. |
51 |
private static final String NAME = "name"; //$NON-NLS-1$ |
70 |
private static final String NAME = "name"; //$NON-NLS-1$ |
Lines 55-66
Link Here
|
55 |
|
74 |
|
56 |
// The path. |
75 |
// The path. |
57 |
private static final String PATH = "path"; //$NON-NLS-1$ |
76 |
private static final String PATH = "path"; //$NON-NLS-1$ |
|
|
77 |
|
78 |
private static final String NODE_QUALIFIER = EMFCorePlugin.getDefault().getBundle().getSymbolicName(); |
79 |
private static final String PREFERENCE_KEY = "referenced.path.variables"; //$NON-NLS-1$ |
58 |
|
80 |
|
59 |
// The path map as defined by the extensions |
81 |
// The path map as defined by the extensions and the referenced path variables and the manually |
|
|
82 |
// added pathmaps. |
60 |
private static final Map PATH_MAP = Collections.synchronizedMap(configure()); |
83 |
private static final Map PATH_MAP = Collections.synchronizedMap(configure()); |
61 |
|
84 |
|
62 |
private static final Map instances = Collections.synchronizedMap(new WeakHashMap()); |
85 |
private static final Map instances = Collections.synchronizedMap(new WeakHashMap()); |
63 |
|
86 |
|
|
|
87 |
// The list of eclipse path variables that are being used in this path map manager |
88 |
private static Set referencedPathVariablesList; |
89 |
|
90 |
private static IEclipsePreferences preferenceStore = null; |
91 |
|
92 |
static { |
93 |
IPathVariableManager pathManager = ResourcesPlugin.getWorkspace().getPathVariableManager(); |
94 |
|
95 |
// We will get the initial list of referenced path variables from our preference store |
96 |
IEclipsePreferences preferences = getPreferenceStore(); |
97 |
String referencedPathVariables = preferences.get(PREFERENCE_KEY, ""); //$NON-NLS-1$ |
98 |
StringTokenizer tokenizer = new StringTokenizer(referencedPathVariables, " "); //$NON-NLS-1$ |
99 |
referencedPathVariablesList = new HashSet(tokenizer.countTokens()); |
100 |
for (;tokenizer.hasMoreTokens();) { |
101 |
String pathVariable = tokenizer.nextToken(); |
102 |
addPathVariableReference(pathVariable); |
103 |
} |
104 |
// Update the preference store in case some path variables have been deleted since the |
105 |
// last time we saved the store. |
106 |
updatePreferenceStore(); |
107 |
|
108 |
// Register this listener to keep up-to-date with the eclipse path variables and update our |
109 |
// referenced path variables appropriately. |
110 |
pathManager.addChangeListener(new IPathVariableChangeListener() { |
111 |
public void pathVariableChanged(IPathVariableChangeEvent event) { |
112 |
switch (event.getType()) { |
113 |
case IPathVariableChangeEvent.VARIABLE_DELETED: |
114 |
removePathVariableReference(event.getVariableName()); |
115 |
updatePreferenceStore(); |
116 |
break; |
117 |
case IPathVariableChangeEvent.VARIABLE_CHANGED: |
118 |
// We only care about variables that we are referencing that |
119 |
// have changed. |
120 |
if (referencedPathVariablesList.contains(event.getVariableName())) { |
121 |
// Check to see if it has become incompatible |
122 |
if (!isDirectory(event.getValue())) { |
123 |
removePathVariableReference(event.getVariableName()); |
124 |
} else { |
125 |
setPathVariable(event.getVariableName(), URI.createFileURI(event.getValue().toString()).toString()); |
126 |
} |
127 |
|
128 |
updatePreferenceStore(); |
129 |
} |
130 |
break; |
131 |
} |
132 |
} |
133 |
}); |
134 |
} |
135 |
|
136 |
private static IEclipsePreferences getPreferenceStore() { |
137 |
if (preferenceStore == null) { |
138 |
IScopeContext ctx = new InstanceScope(); |
139 |
preferenceStore = ctx.getNode(NODE_QUALIFIER); |
140 |
} |
141 |
|
142 |
return preferenceStore; |
143 |
} |
144 |
|
145 |
/** |
146 |
* Adds a new reference to a path variable defined in eclipse |
147 |
* to be used by this pathmap manager. It is assumed that this |
148 |
* path variable is declared in the eclipes path variable manager |
149 |
* and that it is a valid path variable for our purposes. |
150 |
* See {@link #isCompatiblePathVariable(String)} for more details. |
151 |
* |
152 |
* @param pathVariable A valid path variable that has been defined in the |
153 |
* eclipse {@link IPathVariableManager} and is compatible with our path maps. |
154 |
*/ |
155 |
public static void addPathVariableReference(String pathVariable) { |
156 |
if (referencedPathVariablesList.contains(pathVariable)) { |
157 |
// We already reference this path variable so we can assume that it is added |
158 |
// and is compatible. |
159 |
return; |
160 |
} |
161 |
|
162 |
if (!isCompatiblePathVariable(pathVariable)) { |
163 |
return; |
164 |
} |
165 |
|
166 |
IPathVariableManager pathManager = ResourcesPlugin.getWorkspace().getPathVariableManager(); |
167 |
IPath value = pathManager.getValue(pathVariable); |
168 |
if (value != null) { |
169 |
referencedPathVariablesList.add(pathVariable); |
170 |
setPathVariable(pathVariable, URI.createFileURI(value.toString()).toString()); |
171 |
} |
172 |
} |
173 |
|
174 |
/** |
175 |
* Updates the preference store with the current set of path variables that this manager |
176 |
* is currently referencing from the eclipse {@link IPathVariableManager}. |
177 |
*/ |
178 |
public static void updatePreferenceStore() { |
179 |
StringBuffer referencedPathVariables = new StringBuffer(); |
180 |
for (Iterator i = referencedPathVariablesList.iterator(); i.hasNext();) { |
181 |
referencedPathVariables.append((String)i.next()); |
182 |
referencedPathVariables.append(' '); |
183 |
} |
184 |
|
185 |
getPreferenceStore().put(PREFERENCE_KEY, referencedPathVariables.toString()); |
186 |
try { |
187 |
getPreferenceStore().flush(); |
188 |
} catch (BackingStoreException e) { |
189 |
EMFCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, EMFCorePlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e)); |
190 |
} |
191 |
} |
192 |
|
193 |
/** |
194 |
* Removes a reference to a path variable defined in eclipse that was being |
195 |
* used by this pathmap manager. |
196 |
* |
197 |
* @param pathVariable A path variable that was once referenced by this pathmap |
198 |
* manager pointing to a variable declared in the eclipse {@link IPathVariableManager}. |
199 |
*/ |
200 |
public static void removePathVariableReference(String pathVariable) { |
201 |
if (referencedPathVariablesList.contains(pathVariable)) { |
202 |
referencedPathVariablesList.remove(pathVariable); |
203 |
removePathVariable(pathVariable); |
204 |
} |
205 |
} |
206 |
|
207 |
public static Set getPathVariableReferences() { |
208 |
return Collections.unmodifiableSet(referencedPathVariablesList); |
209 |
} |
210 |
|
211 |
public static boolean isCompatiblePathVariable(String variable) { |
212 |
if (referencedPathVariablesList.contains(variable)) { |
213 |
// We assume that if this variable is already referenced then it is valid. |
214 |
return true; |
215 |
} |
216 |
|
217 |
IPathVariableManager pathManager = ResourcesPlugin.getWorkspace().getPathVariableManager(); |
218 |
IPath value = pathManager.getValue(variable); |
219 |
|
220 |
if (value == null) |
221 |
return false; |
222 |
|
223 |
// Check to see if it is a directory first. |
224 |
// EMF will not correctly handle extension parsing |
225 |
// of a pathmap URI if we point directly to a file. This |
226 |
// means that the wrong resource factory could be called. |
227 |
// This could possibly change in the future. |
228 |
return isDirectory(value); |
229 |
} |
230 |
|
231 |
private static boolean isDirectory(IPath value) { |
232 |
File f = new File(value.toString()); |
233 |
return (f.isDirectory()); |
234 |
} |
235 |
|
64 |
/** |
236 |
/** |
65 |
* Constructor. |
237 |
* Constructor. |
66 |
*/ |
238 |
*/ |
Lines 105-113
Link Here
|
105 |
* Set the value of a pathmap variable. |
277 |
* Set the value of a pathmap variable. |
106 |
* |
278 |
* |
107 |
* @param var the path map variable name |
279 |
* @param var the path map variable name |
108 |
* @param val the path map variable value (a URI) |
280 |
* @param val the path map variable value (a file URI) |
109 |
*/ |
281 |
*/ |
110 |
public static void setPathVariable(String var, String val) { |
282 |
public static void setPathVariable(String var, String val) { |
|
|
283 |
// We must try to determine if this pathmap resides in the workspace as some container |
284 |
// so that we store into the pathmap a substitution that is a platform:/resource |
285 |
// type of substitution. This is required because otherwise, pathmap URIs normalize |
286 |
// to file URIs while platform URIs do not normalize, they remain as platform URIs. |
287 |
// This will break some comparisons that might occur when trying to load a resource |
288 |
// that is already loaded because the normalized version of the platform URI to be loaded |
289 |
// will not match the normalized version of the pathmap URI causing two instances of |
290 |
// the same resource to be loaded. |
291 |
java.net.URI valURI = java.net.URI.create(val); |
292 |
IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(valURI); |
293 |
if (containers.length == 1) { |
294 |
val = URI.createPlatformResourceURI(containers[0].getFullPath().toString(),true).toString(); |
295 |
} |
296 |
IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(valURI); |
297 |
if (files.length == 1) { |
298 |
val = URI.createPlatformResourceURI(files[0].getFullPath().toString(),true).toString(); |
299 |
} |
300 |
|
111 |
PATH_MAP.put(var, val); |
301 |
PATH_MAP.put(var, val); |
112 |
|
302 |
|
113 |
for (Iterator i = allInstances().iterator(); i.hasNext();) { |
303 |
for (Iterator i = allInstances().iterator(); i.hasNext();) { |
Lines 131-137
Link Here
|
131 |
* |
321 |
* |
132 |
* @return my resource set |
322 |
* @return my resource set |
133 |
*/ |
323 |
*/ |
134 |
public ResourceSet getResourceSet() { |
324 |
private ResourceSet getResourceSet() { |
135 |
return (ResourceSet) getTarget(); |
325 |
return (ResourceSet) getTarget(); |
136 |
} |
326 |
} |
137 |
|
327 |
|
Lines 199-205
Link Here
|
199 |
String plugin = element.getAttribute(PLUGIN); |
389 |
String plugin = element.getAttribute(PLUGIN); |
200 |
|
390 |
|
201 |
if ((plugin == null) || (plugin.length() == 0)) |
391 |
if ((plugin == null) || (plugin.length() == 0)) |
202 |
plugin = element.getDeclaringExtension().getNamespace(); |
392 |
plugin = element.getDeclaringExtension().getNamespaceIdentifier(); |
203 |
|
393 |
|
204 |
Bundle bundle = Platform.getBundle(plugin); |
394 |
Bundle bundle = Platform.getBundle(plugin); |
205 |
|
395 |
|
Lines 213-219
Link Here
|
213 |
|
403 |
|
214 |
try { |
404 |
try { |
215 |
|
405 |
|
216 |
url = Platform.resolve(url); |
406 |
url = FileLocator.resolve(url); |
217 |
|
407 |
|
218 |
if (url == null) |
408 |
if (url == null) |
219 |
continue; |
409 |
continue; |
Lines 230-235
Link Here
|
230 |
|
420 |
|
231 |
return paths; |
421 |
return paths; |
232 |
} |
422 |
} |
|
|
423 |
|
424 |
public void notifyChanged(Notification msg) { |
425 |
if (msg.getFeatureID(ResourceSet.class) == ResourceSet.RESOURCE_SET__RESOURCES) { |
426 |
switch (msg.getEventType()) { |
427 |
case Notification.ADD: |
428 |
denormalize((Resource) msg.getNewValue(), getResourceSet().getURIConverter()); |
429 |
break; |
430 |
case Notification.ADD_MANY: |
431 |
for (Iterator i = ((List)msg.getNewValue()).iterator(); i.hasNext();) { |
432 |
denormalize((Resource)msg.getNewValue(), getResourceSet().getURIConverter()); |
433 |
} |
434 |
break; |
435 |
case Notification.REMOVE: |
436 |
normalize((Resource)msg.getOldValue(), getResourceSet().getURIConverter()); |
437 |
break; |
438 |
case Notification.REMOVE_MANY: |
439 |
for (Iterator i = ((List)msg.getNewValue()).iterator(); i.hasNext();) { |
440 |
normalize((Resource)msg.getNewValue(), getResourceSet().getURIConverter()); |
441 |
} |
442 |
break; |
443 |
} |
444 |
} |
445 |
} |
233 |
|
446 |
|
234 |
public void setTarget(Notifier newTarget) { |
447 |
public void setTarget(Notifier newTarget) { |
235 |
// get the old resource set |
448 |
// get the old resource set |
Lines 260-265
Link Here
|
260 |
Map savedURIs = new HashMap(); |
473 |
Map savedURIs = new HashMap(); |
261 |
|
474 |
|
262 |
ResourceSet rset = getResourceSet(); |
475 |
ResourceSet rset = getResourceSet(); |
|
|
476 |
|
477 |
if (rset == null) |
478 |
return; |
263 |
|
479 |
|
264 |
for (Iterator i = rset.getResources().iterator(); i.hasNext();) { |
480 |
for (Iterator i = rset.getResources().iterator(); i.hasNext();) { |
265 |
|
481 |
|
Lines 387-404
Link Here
|
387 |
.hasNext();) { |
603 |
.hasNext();) { |
388 |
|
604 |
|
389 |
Resource resource = (Resource) i.next(); |
605 |
Resource resource = (Resource) i.next(); |
390 |
|
606 |
normalize(resource, converter); |
391 |
URI uri = resource.getURI(); |
|
|
392 |
|
393 |
if ((EMFCoreConstants.PATH_MAP_SCHEME.equals(uri.scheme())) |
394 |
&& (resource instanceof GMFResource)) { |
395 |
|
396 |
((GMFResource) resource) |
397 |
.setRawURI(converter.normalize(uri)); |
398 |
} |
399 |
} |
607 |
} |
400 |
} |
608 |
} |
401 |
} |
609 |
} |
|
|
610 |
|
611 |
private void normalize(Resource resource, URIConverter converter) { |
612 |
URI uri = resource.getURI(); |
613 |
|
614 |
if (uri == null) |
615 |
return; |
616 |
|
617 |
if ((EMFCoreConstants.PATH_MAP_SCHEME.equals(uri.scheme())) |
618 |
&& (resource instanceof GMFResource)) { |
619 |
|
620 |
((GMFResource) resource) |
621 |
.setRawURI(converter.normalize(uri)); |
622 |
} |
623 |
} |
402 |
|
624 |
|
403 |
/** |
625 |
/** |
404 |
* Denormalize the URI of a set of resources. |
626 |
* Denormalize the URI of a set of resources. |
Lines 415-428
Link Here
|
415 |
.hasNext();) { |
637 |
.hasNext();) { |
416 |
|
638 |
|
417 |
Resource resource = (Resource) i.next(); |
639 |
Resource resource = (Resource) i.next(); |
418 |
|
640 |
denormalize(resource, converter); |
419 |
URI uri = resource.getURI(); |
|
|
420 |
|
421 |
if (resource instanceof GMFResource) |
422 |
((GMFResource) resource).setURI(converter.normalize(uri)); |
423 |
} |
641 |
} |
424 |
} |
642 |
} |
425 |
} |
643 |
} |
|
|
644 |
|
645 |
private void denormalize(Resource resource, URIConverter converter) { |
646 |
URI uri = resource.getURI(); |
647 |
|
648 |
if (uri == null) |
649 |
return; |
650 |
|
651 |
if (resource instanceof GMFResource) |
652 |
((GMFResource) resource).setURI(converter.normalize(uri)); |
653 |
} |
426 |
|
654 |
|
427 |
/** |
655 |
/** |
428 |
* Make a pathmap uri from a pathmap variable name. |
656 |
* Make a pathmap uri from a pathmap variable name. |
Lines 454-457
Link Here
|
454 |
private Map getURIMap() { |
682 |
private Map getURIMap() { |
455 |
return getResourceSet().getURIConverter().getURIMap(); |
683 |
return getResourceSet().getURIConverter().getURIMap(); |
456 |
} |
684 |
} |
|
|
685 |
|
686 |
/** |
687 |
* Denormalizes a given resource's URI to a pathmap URI if it is possible. |
688 |
* |
689 |
* @param uri A file or platform URI that has been denormalized as much |
690 |
* possible. |
691 |
* |
692 |
* @return The original URI if it could not be denormalized any further |
693 |
* or a new pathmap URI otherwise. |
694 |
*/ |
695 |
public static URI denormalizeURI(URI uri) { |
696 |
if (!uri.isFile()) { |
697 |
if (!uri.scheme().equals("platform")) { //$NON-NLS-1$ |
698 |
return uri; |
699 |
} else if (!uri.segment(0).equals("resource")) { //$NON-NLS-1$ |
700 |
return uri; |
701 |
} |
702 |
} |
703 |
|
704 |
String uriAsString = uri.toString(); |
705 |
|
706 |
String maxValueString = null; |
707 |
String maxKey = null; |
708 |
|
709 |
synchronized(PATH_MAP) { |
710 |
for (Iterator i = PATH_MAP.entrySet().iterator(); i.hasNext();) { |
711 |
Map.Entry entry = (Map.Entry)i.next(); |
712 |
String valueString = (String)entry.getValue(); |
713 |
|
714 |
// Wipe out the trailing separator from the value if necessary |
715 |
if (valueString.endsWith("/")) { //$NON-NLS-1$ |
716 |
valueString = valueString.substring(0,valueString.length()-1); |
717 |
} |
718 |
|
719 |
if (uriAsString.startsWith(valueString) |
720 |
&& (maxValueString == null || |
721 |
maxValueString.length() < valueString.length())) { |
722 |
maxValueString = valueString; |
723 |
maxKey = (String)entry.getKey(); |
724 |
} |
725 |
} |
726 |
} |
727 |
|
728 |
if (maxKey != null) { |
729 |
URI valueURI = URI.createURI(maxValueString); |
730 |
URI pathmapURI = makeURI(maxKey); |
731 |
|
732 |
int segmentStart = valueURI.segmentCount(); |
733 |
int segmentCount = uri.segmentCount(); |
734 |
|
735 |
for (int j=segmentStart; j < segmentCount; j++) { |
736 |
pathmapURI = pathmapURI.appendSegment(uri.segment(j)); |
737 |
} |
738 |
|
739 |
return pathmapURI; |
740 |
} |
741 |
|
742 |
return uri; |
743 |
} |
457 |
} |
744 |
} |