Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2011 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.wst.jsdt.debug.internal.core.model; |
12 |
|
13 |
import java.net.URI; |
14 |
import java.util.ArrayList; |
15 |
import java.util.Arrays; |
16 |
import java.util.List; |
17 |
|
18 |
import org.eclipse.core.resources.IFile; |
19 |
import org.eclipse.core.resources.IResource; |
20 |
import org.eclipse.core.resources.IWorkspaceRoot; |
21 |
import org.eclipse.core.resources.ResourcesPlugin; |
22 |
import org.eclipse.core.runtime.IConfigurationElement; |
23 |
import org.eclipse.core.runtime.IExtensionPoint; |
24 |
import org.eclipse.core.runtime.IPath; |
25 |
import org.eclipse.core.runtime.ListenerList; |
26 |
import org.eclipse.core.runtime.Path; |
27 |
import org.eclipse.core.runtime.Platform; |
28 |
import org.eclipse.core.runtime.URIUtil; |
29 |
import org.eclipse.wst.jsdt.debug.core.jsdi.ScriptReference; |
30 |
import org.eclipse.wst.jsdt.debug.core.model.IScriptResolver; |
31 |
import org.eclipse.wst.jsdt.debug.internal.core.Constants; |
32 |
import org.eclipse.wst.jsdt.debug.internal.core.JavaScriptDebugPlugin; |
33 |
import org.eclipse.wst.jsdt.debug.internal.core.Messages; |
34 |
import org.eclipse.wst.jsdt.debug.internal.core.launching.SourceLookup; |
35 |
|
36 |
/** |
37 |
* Handles the collection of {@link ScriptResolverExtension}s and provide useful utilities for path / script handling |
38 |
* @since 3.4 |
39 |
*/ |
40 |
public final class ScriptResolutionManager { |
41 |
|
42 |
static IScriptResolver[] NO_RESOLVERS = new IScriptResolver[0]; |
43 |
ListenerList resolvers = null; |
44 |
|
45 |
/** |
46 |
* This is a convenience method that consults all of the registered {@link IScriptResolver}s. |
47 |
* <br><br> |
48 |
* This method will return <code>true</code> iff any one (or all) of the {@link IScriptResolver}s returns <code>true</code> or |
49 |
* the default matching algorithm returns <code>true</code> - which is consulted after all extensions have been asked. |
50 |
* @param script the script to check |
51 |
* @param path the path to compare against |
52 |
* @return <code>true</code> if any one (or all) of the {@link IScriptResolver}s return <code>true</code>, <code>false</code> otherwise |
53 |
*/ |
54 |
public boolean matches(ScriptReference script, IPath path) { |
55 |
IScriptResolver[] res = getResolvers(); |
56 |
for (int i = 0; i < res.length; i++) { |
57 |
if(res[i].matches(script, path)) { |
58 |
return true; |
59 |
} |
60 |
} |
61 |
//no extensions matched, fall-back to the old way |
62 |
return isMatch(script, path); |
63 |
} |
64 |
|
65 |
boolean isMatch(ScriptReference script, IPath path) { |
66 |
if(guessScriptMatches(script, path)) { |
67 |
return true; |
68 |
} |
69 |
//no luck, try an exact match |
70 |
URI sourceURI = script.sourceURI(); |
71 |
if (URIUtil.isFileURI(sourceURI)) { |
72 |
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); |
73 |
URI workspaceURI = workspaceRoot.getRawLocationURI(); |
74 |
sourceURI = workspaceURI.relativize(sourceURI); |
75 |
} |
76 |
IPath spath = path; |
77 |
if(spath.segmentCount() > 0 && spath.segment(0).equals(Messages.external_javascript_source)) { |
78 |
spath = spath.removeFirstSegments(1).makeAbsolute(); |
79 |
} |
80 |
IPath uripath = SourceLookup.getSourcePath(sourceURI); |
81 |
if(uripath != null) { |
82 |
uripath = uripath.makeAbsolute(); |
83 |
} |
84 |
return spath.equals(uripath); |
85 |
} |
86 |
|
87 |
/** |
88 |
* Guesses if the paths are considered equal by walking backward from the last segment of the paths and counting the matching segments. |
89 |
* The paths are guessed to be equal iff any two or more segments match in order. |
90 |
* |
91 |
* @param script the {@link ScriptReference} |
92 |
* @param path the path to compare |
93 |
* @return <code>true</code> if the paths 'match', <code>false</code> otherwise |
94 |
*/ |
95 |
boolean guessScriptMatches(ScriptReference script, IPath path) { |
96 |
IPath newpath = path.makeAbsolute(); |
97 |
IPath uri = new Path(script.sourceURI().getPath()); |
98 |
if(SourceLookup.TOP_LEVEL_PATH.equals(newpath) && SourceLookup.TOP_LEVEL_PATH.equals(uri)) { |
99 |
return true; |
100 |
} |
101 |
uri = uri.makeAbsolute(); |
102 |
int matched_segments = 0; |
103 |
int last = uri.segmentCount()-1; |
104 |
for(int i = newpath.segmentCount()-1; i > -1; i--) { |
105 |
if(last < 0) { |
106 |
break; |
107 |
} |
108 |
if(newpath.segment(i).equals(uri.segment(last))) { |
109 |
matched_segments++; |
110 |
last--; |
111 |
} |
112 |
} |
113 |
return matched_segments > 1; |
114 |
} |
115 |
|
116 |
/** |
117 |
* Convenience method to consult all of the registered {@link IScriptResolver}s for the matching {@link IFile}. |
118 |
* <br><br> |
119 |
* This method will vote on the file to return, and return the {@link IFile} that has the most votes as follows: |
120 |
* <ul> |
121 |
* <li>If there is one contributor and it returns an {@link IFile} that one is chosen</li> |
122 |
* <li>If there is > one contributor the greatest number of matching {@link IFile}s returned is chosen. If there is a tie, the {@link IFile} |
123 |
* that matches the one selected from the default algorithm will be chosen. In the event the default algorithm returns <code>null</code> the first {@link IFile} |
124 |
* will be selected.</li> |
125 |
* <li>If there are no contributors the default algorithm is consulted</li> |
126 |
* </ul> |
127 |
* @param script |
128 |
* @return the matching {@link IFile} or <code>null</code> |
129 |
*/ |
130 |
public IFile getFile(ScriptReference script) { |
131 |
IScriptResolver[] resolvers = getResolvers(); |
132 |
ArrayList files = new ArrayList(); |
133 |
IFile file = null; |
134 |
for (int i = 0; i < resolvers.length; i++) { |
135 |
file = resolvers[i].getFile(script); |
136 |
if(file != null) { |
137 |
if(files.contains(file)) { |
138 |
return file; |
139 |
} |
140 |
files.add(file); |
141 |
} |
142 |
} |
143 |
file = null; |
144 |
IPath p = SourceLookup.getSourcePath(script.sourceURI()); |
145 |
IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(p); |
146 |
if(res.getType() == IResource.FILE) { |
147 |
file = (IFile) res; |
148 |
} |
149 |
if(files.size() > 0) { |
150 |
if(files.contains(file)) { |
151 |
return file; |
152 |
} |
153 |
return (IFile) files.get(0); |
154 |
} |
155 |
return file; |
156 |
} |
157 |
|
158 |
/** |
159 |
* Returns the complete listing of {@link IScriptResolver}s or an empty array, never <code>null</code> |
160 |
* |
161 |
* @return the complete listing of {@link IScriptResolver}s |
162 |
*/ |
163 |
public IScriptResolver[] getResolvers() { |
164 |
loadResolvers(); |
165 |
if(resolvers.size() < 1) { |
166 |
return NO_RESOLVERS; |
167 |
} |
168 |
List res = Arrays.asList(resolvers.getListeners()); |
169 |
return (IScriptResolver[]) res.toArray(new IScriptResolver[res.size()]); |
170 |
} |
171 |
|
172 |
/** |
173 |
* load up all the extension points to the delegate listeners |
174 |
*/ |
175 |
void loadResolvers() { |
176 |
if(resolvers == null) { |
177 |
resolvers = new ListenerList(); |
178 |
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(JavaScriptDebugPlugin.PLUGIN_ID, Constants.SCRIPT_RESOLVERS); |
179 |
IConfigurationElement[] elements = extensionPoint.getConfigurationElements(); |
180 |
for (int i = 0; i < elements.length; i++) { |
181 |
resolvers.add(new ScriptResolverExtension(elements[i])); |
182 |
} |
183 |
} |
184 |
} |
185 |
|
186 |
/** |
187 |
* Clean up |
188 |
*/ |
189 |
public void dispose() { |
190 |
if(resolvers != null) { |
191 |
resolvers.clear(); |
192 |
resolvers = null; |
193 |
} |
194 |
} |
195 |
} |