Added
Link Here
|
1 |
/* |
2 |
* Sun Public License Notice |
3 |
* |
4 |
* The contents of this file are subject to the Sun Public License |
5 |
* Version 1.0 (the "License"). You may not use this file except in |
6 |
* compliance with the License. A copy of the License is available at |
7 |
* http://www.sun.com/ |
8 |
* |
9 |
* The Original Code is NetBeans. The Initial Developer of the Original |
10 |
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun |
11 |
* Microsystems, Inc. All Rights Reserved. |
12 |
*/ |
13 |
|
14 |
package org.netbeans.api.java.project.classpath; |
15 |
|
16 |
import java.io.Externalizable; |
17 |
import java.io.IOException; |
18 |
import java.net.URI; |
19 |
import java.net.URL; |
20 |
import java.util.ArrayList; |
21 |
import java.util.List; |
22 |
import org.netbeans.api.java.classpath.ClassPath; |
23 |
import org.netbeans.api.project.FileOwnerQuery; |
24 |
import org.netbeans.api.project.Project; |
25 |
import org.netbeans.api.project.SourceGroup; |
26 |
import org.netbeans.api.project.ant.AntArtifact; |
27 |
import org.netbeans.api.project.libraries.Library; |
28 |
import org.netbeans.modules.java.project.classpath.ProjectClassPathModifierAccessor; |
29 |
import org.netbeans.spi.java.project.classpath.ProjectClassPathExtender; |
30 |
import org.netbeans.spi.java.project.classpath.ProjectClassPathModifierImplementation; |
31 |
import org.openide.filesystems.FileObject; |
32 |
import org.openide.filesystems.FileUtil; |
33 |
import org.openide.filesystems.URLMapper; |
34 |
|
35 |
/** |
36 |
* An API for project's classpaths modification. |
37 |
* An client can use this interface to add/remove classpath element (folder, archive, library, subproject) |
38 |
* to/from the project's classpath. Not all operations on all project's classpath are supported, if the project |
39 |
* type does not support a modification of a given classpath the UnsupportedOperationException is thrown. |
40 |
* @since org.netbeans.modules.java.project/1 1.10 |
41 |
*/ |
42 |
public class ProjectClassPathModifier { |
43 |
|
44 |
|
45 |
|
46 |
private ProjectClassPathModifier () { |
47 |
|
48 |
} |
49 |
|
50 |
/** |
51 |
* Adds libraries into the project's classpath if the |
52 |
* libraries are not already included. |
53 |
* @param libraries to be added |
54 |
* @param projectArtifact a file which classpath should be extended |
55 |
* @param classPathType the type of classpath to be extended, @see ClassPath |
56 |
* @return true in case the classpath was changed (at least one library was added to the classpath), |
57 |
* the value false is returned when all the libraries are already included on the classpath. |
58 |
* @exception IOException in case the project metadata cannot be changed |
59 |
* @exception UnsupportedOperationException is thrown when the project does not support |
60 |
* adding of a library to the classpath of the given id. |
61 |
*/ |
62 |
@SuppressWarnings("deprecation") //NOI18N |
63 |
public static boolean addLibraries (final Library[] libraries, final FileObject projectArtfact, final String classPathType) throws IOException, UnsupportedOperationException { |
64 |
final Extensible extensible = findExtensible (projectArtfact, classPathType); |
65 |
if (extensible != null) { |
66 |
if (extensible.pcmi != null) { |
67 |
assert extensible.sg != null; |
68 |
assert extensible.classPathType != null; |
69 |
return ProjectClassPathModifierAccessor.INSTANCE.addLibraries (libraries, extensible.pcmi, extensible.sg, extensible.classPathType); |
70 |
} |
71 |
else if (extensible.pcpe != null) { |
72 |
boolean result = false; |
73 |
for (int i=0; i< libraries.length; i++) { |
74 |
result |= extensible.pcpe.addLibrary (libraries[i]); |
75 |
} |
76 |
return result; |
77 |
} |
78 |
} |
79 |
throw new UnsupportedOperationException (); |
80 |
} |
81 |
|
82 |
|
83 |
/** |
84 |
* Removes libraries from the project's classpath if the |
85 |
* libraries are included on it. |
86 |
* @param libraries to be removed |
87 |
* @param projectArtfact a file from whose classpath the libraries should be removed |
88 |
* @param classPathType the type of classpath, @see ClassPath |
89 |
* @return true in case the classpath was changed, (at least one library was removed from the classpath), |
90 |
* the value false is returned when none of the libraries was included on the classpath. |
91 |
* @exception IOException in case the project metadata cannot be changed |
92 |
* @exception UnsupportedOperationException is thrown when the project does not support |
93 |
* removing of a library from the classpath of the given id. |
94 |
*/ |
95 |
public static boolean removeLibraries (final Library[] libraries, final FileObject projectArtfact, final String classPathType) throws IOException, UnsupportedOperationException { |
96 |
final Extensible extensible = findExtensible (projectArtfact, classPathType); |
97 |
if (extensible != null && extensible.pcmi != null) { |
98 |
assert extensible.sg != null; |
99 |
assert extensible.classPathType != null; |
100 |
return ProjectClassPathModifierAccessor.INSTANCE.removeLibraries (libraries, extensible.pcmi, extensible.sg, extensible.classPathType); |
101 |
} |
102 |
throw new UnsupportedOperationException (); |
103 |
} |
104 |
|
105 |
/** |
106 |
* Adds archive files or folders into the project's classpath if the |
107 |
* entries are not already there. |
108 |
* @param classPathRoots roots to be added, each root has to be either a root of an archive or a folder |
109 |
* @param projectArtfact a file which classpath should be extended |
110 |
* @param classPathType the type of classpath to be extended, @see ClassPath |
111 |
* @return true in case the classpath was changed, (at least one classpath root was added to the classpath), |
112 |
* the value false is returned when all the classpath roots are already included on the classpath. |
113 |
* @exception IOException in case the project metadata cannot be changed |
114 |
* @exception UnsupportedOperationException is thrown when the project does not support |
115 |
* adding of a root to the classpath of the given id. |
116 |
*/ |
117 |
@SuppressWarnings("deprecation") //NOI18N |
118 |
public static boolean addRoots (final URL[] classPathRoots, final FileObject projectArtfact, final String classPathType) throws IOException, UnsupportedOperationException { |
119 |
final Extensible extensible = findExtensible(projectArtfact, classPathType); |
120 |
if (extensible != null) { |
121 |
if (extensible.pcmi != null) { |
122 |
assert extensible.sg != null; |
123 |
assert extensible.classPathType != null; |
124 |
return ProjectClassPathModifierAccessor.INSTANCE.addRoots (classPathRoots, extensible.pcmi, extensible.sg, extensible.classPathType); |
125 |
} |
126 |
else if (extensible.pcpe != null) { |
127 |
boolean result = false; |
128 |
for (int i=0; i< classPathRoots.length; i++) { |
129 |
URL urlToAdd = classPathRoots[i]; |
130 |
if ("jar".equals(urlToAdd.getProtocol())) { |
131 |
urlToAdd = FileUtil.getArchiveFile (urlToAdd); |
132 |
} |
133 |
final FileObject fo = URLMapper.findFileObject(urlToAdd); |
134 |
if (fo == null) { |
135 |
throw new UnsupportedOperationException ("Adding of a non existent root is not supported by project."); //NOI18N |
136 |
} |
137 |
result |= extensible.pcpe.addArchiveFile (fo); |
138 |
} |
139 |
return result; |
140 |
} |
141 |
} |
142 |
throw new UnsupportedOperationException (); |
143 |
} |
144 |
|
145 |
/** |
146 |
* Removes archive files or folders from the project's classpath if the |
147 |
* entries are included on it. |
148 |
* @param classPathRoots roots to be removed, each root has to be either a root of an archive or a folder |
149 |
* @param projectArtfact a file from whose classpath the roots should be removed |
150 |
* @param classPathType the type of classpath, @see ClassPath |
151 |
* @return true in case the classpath was changed, (at least one classpath root was removed from the classpath), |
152 |
* the value false is returned when none of the classpath roots was included on the classpath. |
153 |
* @exception IOException in case the project metadata cannot be changed |
154 |
* @exception UnsupportedOperationException is thrown when the project does not support |
155 |
* removing of a root from the classpath of the given id. |
156 |
*/ |
157 |
public static boolean removeRoots (final URL[] classPathRoots, final FileObject projectArtfact, final String classPathType) throws IOException, UnsupportedOperationException { |
158 |
final Extensible extensible = findExtensible (projectArtfact, classPathType); |
159 |
if (extensible != null && extensible.pcmi != null) { |
160 |
assert extensible.sg != null; |
161 |
assert extensible.classPathType != null; |
162 |
return ProjectClassPathModifierAccessor.INSTANCE.removeRoots (classPathRoots, extensible.pcmi, extensible.sg, extensible.classPathType); |
163 |
} |
164 |
throw new UnsupportedOperationException (); |
165 |
} |
166 |
|
167 |
/** |
168 |
* Adds artifacts (e.g. subprojects) into project's classpath if the |
169 |
* artifacts are not already on it. |
170 |
* @param artifacts to be added |
171 |
* @param artifactElements the URIs of the build output, the artifactElements has to have the same length |
172 |
* as artifacts. |
173 |
* (must be owned by the artifact and be relative to it) |
174 |
* @param projectArtfact a file which classpath should be extended |
175 |
* @param classPathType the type of classpath to be extended, @see ClassPath |
176 |
* @return true in case the classpath was changed, (at least one artifact was added to the classpath), |
177 |
* the value false is returned when all the artifacts are already included on the classpath. |
178 |
* @exception IOException in case the project metadata cannot be changed |
179 |
* @exception UnsupportedOperationException is thrown when the project does not support |
180 |
* adding of an artifact to the classpath of the given id. |
181 |
*/ |
182 |
@SuppressWarnings("deprecation") //NOI18N |
183 |
public static boolean addAntArtifacts (final AntArtifact[] artifacts, final URI[] artifactElements, |
184 |
final FileObject projectArtfact, final String classPathType) throws IOException, UnsupportedOperationException { |
185 |
final Extensible extensible = findExtensible (projectArtfact, classPathType); |
186 |
if (extensible != null) { |
187 |
assert artifacts.length == artifactElements.length; |
188 |
if (extensible.pcmi != null) { |
189 |
assert extensible.sg != null; |
190 |
assert extensible.classPathType != null; |
191 |
return ProjectClassPathModifierAccessor.INSTANCE.addAntArtifacts (artifacts, artifactElements, extensible.pcmi, extensible.sg, extensible.classPathType); |
192 |
} |
193 |
else if (extensible.pcpe != null) { |
194 |
boolean result = false; |
195 |
for (int i=0; i< artifacts.length; i++) { |
196 |
result |= extensible.pcpe.addAntArtifact (artifacts[i], artifactElements[i]); |
197 |
} |
198 |
return result; |
199 |
} |
200 |
} |
201 |
throw new UnsupportedOperationException (); |
202 |
} |
203 |
|
204 |
/** |
205 |
* Removes artifacts (e.g. subprojects) from project's classpath if the |
206 |
* artifacts are included on it. |
207 |
* @param artifacts to be added |
208 |
* @param artifactElements the URIs of the build output, the artifactElements has to have the same length |
209 |
* as artifacts. |
210 |
* (must be owned by the artifact and be relative to it) |
211 |
* @param projectArtfact a file from whose classpath the dependent projects should be removed |
212 |
* @param classPathType the type of classpath, @see ClassPath |
213 |
* @return true in case the classpath was changed, (at least one artifact was removed from the classpath), |
214 |
* the value false is returned when none of the artifacts was included on the classpath. |
215 |
* @exception IOException in case the project metadata cannot be changed |
216 |
* @exception UnsupportedOperationException is thrown when the project does not support |
217 |
* removing of an artifact from the classpath of the given id. |
218 |
*/ |
219 |
public static boolean removeAntArtifacts (final AntArtifact[] artifacts, final URI[] artifactElements, |
220 |
final FileObject projectArtifact, final String classPathType) throws IOException, UnsupportedOperationException { |
221 |
final Extensible extensible = findExtensible (projectArtifact, classPathType); |
222 |
if (extensible != null && extensible.pcmi != null) { |
223 |
assert extensible.sg != null; |
224 |
assert extensible.classPathType != null; |
225 |
return ProjectClassPathModifierAccessor.INSTANCE.removeAntArtifacts (artifacts, artifactElements, extensible.pcmi, extensible.sg, extensible.classPathType); |
226 |
} |
227 |
throw new UnsupportedOperationException (); |
228 |
} |
229 |
|
230 |
|
231 |
/** |
232 |
* Returns {@link ProjectClassPathModifier#Extensible} for given project artifact and classpath type. |
233 |
* An Extensible implies a classpath to be extended. Different project type may provide different types |
234 |
* of Extensible. |
235 |
* @param projectArtifact a file owned by SourceGroup which classpath should be changed |
236 |
* @param classPathType a classpath type, @see ClassPath |
237 |
* @return an Extensible or null. In case when the project supports the {@link ProjectClassPathModifierImplementation}, |
238 |
* this interface is used to find an Extensible. If this interface is not provided, but project provides |
239 |
* the deprecated {@link ProjectClassPathExtender} interface and classpath type is {@link ClassPath@COMPILE} the |
240 |
* single Extensible, without assigned SourceGroup, is returned. |
241 |
* In case when neither {@link ProjectClassPathModifierImplementation} nor {@link ProjectClassPathExtender} |
242 |
* is supported null is returned. |
243 |
*/ |
244 |
@SuppressWarnings("deprecation") //NOI18N |
245 |
private static Extensible findExtensible (final FileObject fo, final String classPathType) { |
246 |
assert fo != null; |
247 |
assert classPathType != null; |
248 |
final Project project = FileOwnerQuery.getOwner(fo); |
249 |
if (project == null) { |
250 |
return null; |
251 |
} |
252 |
final ProjectClassPathModifierImplementation pm = (ProjectClassPathModifierImplementation) project.getLookup().lookup(ProjectClassPathModifierImplementation.class); |
253 |
if (pm != null) { |
254 |
final SourceGroup[] sgs = ProjectClassPathModifierAccessor.INSTANCE.getExtensibleSourceGroups(pm); |
255 |
assert sgs != null : "Class: " + pm.getClass() + " returned null as source groups."; //NOI18N |
256 |
for (SourceGroup sg : sgs) { |
257 |
if ((fo == sg.getRootFolder() || FileUtil.isParentOf(sg.getRootFolder(),fo)) && sg.contains(fo)) { |
258 |
final String[] types = ProjectClassPathModifierAccessor.INSTANCE.getExtensibleClassPathTypes(pm,sg); |
259 |
assert types != null : "Class: " + pm.getClass() + " returned null as classpath types."; //NOI18N |
260 |
for (String type : types) { |
261 |
if (classPathType.equals(type)) { |
262 |
return new Extensible (pm, sg, type); |
263 |
} |
264 |
} |
265 |
} |
266 |
} |
267 |
} |
268 |
else if (classPathType.equals(ClassPath.COMPILE)) { |
269 |
final ProjectClassPathExtender pe = (ProjectClassPathExtender) project.getLookup().lookup(ProjectClassPathExtender.class); |
270 |
if (pe != null) { |
271 |
return new Extensible (pe); |
272 |
} |
273 |
} |
274 |
return null; |
275 |
} |
276 |
|
277 |
|
278 |
/** |
279 |
* Extensible represents a classpath which may be changed by the |
280 |
* {@link ProjectClassPathModifier}. It encapsulates the compilation |
281 |
* unit and class path type, @see ClassPath. |
282 |
*/ |
283 |
private static final class Extensible { |
284 |
|
285 |
private final String classPathType; |
286 |
private final SourceGroup sg; |
287 |
private final ProjectClassPathModifierImplementation pcmi; |
288 |
@SuppressWarnings("deprecation") //NOI18N |
289 |
private final ProjectClassPathExtender pcpe; |
290 |
|
291 |
|
292 |
private Extensible (final ProjectClassPathModifierImplementation pcmi , final SourceGroup sg, final String classPathType) { |
293 |
assert pcmi != null; |
294 |
assert sg != null; |
295 |
assert classPathType != null; |
296 |
this.pcmi = pcmi; |
297 |
this.sg = sg; |
298 |
this.classPathType = classPathType; |
299 |
this.pcpe = null; |
300 |
} |
301 |
|
302 |
@SuppressWarnings("deprecation") //NOI18N |
303 |
private Extensible (final ProjectClassPathExtender pcpe) { |
304 |
assert pcpe != null; |
305 |
this.pcpe = pcpe; |
306 |
this.pcmi = null; |
307 |
this.sg = null; |
308 |
this.classPathType = ClassPath.COMPILE; |
309 |
} |
310 |
} |
311 |
|
312 |
} |