KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > project > ClassPathUtils


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.form.project;
21
22 import java.io.*;
23 import java.net.*;
24 import java.util.*;
25 import java.text.MessageFormat JavaDoc;
26
27 import org.openide.ErrorManager;
28 import org.openide.filesystems.*;
29 import org.openide.util.Lookup;
30 import org.openide.util.NbBundle;
31
32 import org.netbeans.api.project.*;
33 import org.netbeans.api.project.ant.*;
34 import org.netbeans.api.project.libraries.Library;
35 import org.netbeans.api.project.libraries.LibraryManager;
36 import org.netbeans.api.java.classpath.ClassPath;
37 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
38 import org.netbeans.api.java.queries.SourceForBinaryQuery;
39 import org.netbeans.spi.java.project.classpath.ProjectClassPathExtender;
40
41 /**
42  * Utility methods related to classpath in projects.
43  *
44  * @author Tomas Pavek
45  */

46
47 public class ClassPathUtils {
48
49     private static Map loaders = new WeakHashMap();
50
51     // class loading type - desired scope of classloader
52
static final int UNSPECIFIED_CLASS = 0; // external class from user project's classpath only
53
static final int SYSTEM_CLASS = 1; // class to be loaded by IDE system classloader (e.g. from a module)
54
static final int SYSTEM_CLASS_WITH_PROJECT = 2; // class to be loaded from a module by classloader including also project classpath
55

56     /**
57      * Loads a class with a context of a project in mind (specified by arbitrary
58      * file contained in the project). Typically the class is loaded from the
59      * project's execution classpath unless it is a basic JDK class, or a class
60      * registred as a support (system) class.
61      */

62     public static Class JavaDoc loadClass(String JavaDoc name, FileObject fileInProject)
63         throws ClassNotFoundException JavaDoc
64     {
65         return Class.forName(name, true, getFormClassLoader(fileInProject));
66         // LinkageError left uncaught
67
}
68
69     public static boolean checkUserClass(String JavaDoc name, FileObject fileInProject) {
70         ClassPath classPath = ClassPath.getClassPath(fileInProject, ClassPath.EXECUTE);
71         if (classPath == null)
72             return false;
73
74         String JavaDoc fileName = name.replace('.', '/').concat(".class"); // NOI18N
75
return classPath.findResource(fileName) != null;
76     }
77
78     private static FormClassLoader getFormClassLoader(FileObject fileInProject) {
79         Project p = FileOwnerQuery.getOwner(fileInProject);
80         FormClassLoader fcl = (FormClassLoader) loaders.get(p);
81         ClassLoader JavaDoc existingProjectCL = fcl != null ? fcl.getProjectClassLoader() : null;
82         ClassLoader JavaDoc newProjectCL = ProjectClassLoader.getUpToDateClassLoader(
83                                      fileInProject, existingProjectCL);
84         if (fcl == null || newProjectCL != existingProjectCL) {
85             fcl = new FormClassLoader(newProjectCL);
86             loaders.put(p, fcl);
87         }
88         return fcl;
89     }
90
91     static int getClassLoadingType(String JavaDoc className) {
92         int i = className.lastIndexOf("[L"); // NOI18N
93
if (i != -1)
94             className = className.substring(i+2, className.length()-1);
95         if (isClassLoaderType(className, SYSTEM_CLASS))
96             return SYSTEM_CLASS;
97         if (isClassLoaderType(className, SYSTEM_CLASS_WITH_PROJECT))
98             return SYSTEM_CLASS_WITH_PROJECT;
99         return UNSPECIFIED_CLASS;
100     }
101
102     /** Loads class from classpath described by ClassSource object.
103      * @return loaded class, null if class name in ClassSource is null
104      */

105     public static Class JavaDoc loadClass(ClassSource classSource)
106         throws ClassNotFoundException JavaDoc
107     {
108         String JavaDoc className = classSource.getClassName();
109         if (className == null)
110             return null;
111
112         ClassLoader JavaDoc loader = null;
113         int cpRootCount = classSource.getCPRootCount();
114
115         if (cpRootCount == 0) {
116             // for loading JDK classes
117
loader = (ClassLoader JavaDoc) Lookup.getDefault().lookup(ClassLoader JavaDoc.class);
118         }
119         else try {
120             List urlList = new ArrayList();
121             for (int i=0; i < cpRootCount; i++) {
122                 String JavaDoc type = classSource.getCPRootType(i);
123                 String JavaDoc name = classSource.getCPRootName(i);
124
125                 if (ClassSource.JAR_SOURCE.equals(type)) {
126                     File jarFile = new File(name);
127                     urlList.add(FileUtil.getArchiveRoot(jarFile.toURI().toURL()));
128                 }
129                 else if (ClassSource.LIBRARY_SOURCE.equals(type)) {
130                     Library lib = LibraryManager.getDefault().getLibrary(name);
131                     if (lib != null) {
132                         List content = lib.getContent("classpath"); // NOI18N
133
for (Iterator it=content.iterator(); it.hasNext(); ) {
134                             URL rootURL = (URL) it.next();
135                             if (FileUtil.isArchiveFile(rootURL))
136                                 rootURL = FileUtil.getArchiveRoot(rootURL);
137                             urlList.add(rootURL);
138                         }
139                     }
140                 }
141                 else if (ClassSource.PROJECT_SOURCE.equals(type)) {
142                     File outputFile = new File(name);
143                     URL rootURL = FileUtil.getArchiveRoot(outputFile.toURI().toURL());
144                     if (FileUtil.isArchiveFile(rootURL))
145                         rootURL = FileUtil.getArchiveRoot(rootURL);
146                     urlList.add(rootURL);
147                 }
148             }
149
150             if (urlList.size() > 0) {
151                 URL[] roots = new URL[urlList.size()];
152                 urlList.toArray(roots);
153                 loader = ClassPathSupport.createClassPath(roots).getClassLoader(true);
154             }
155             else return null;
156         }
157         catch (Exception JavaDoc ex) { // could not construct the classpath
158
IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc();
159             ErrorManager.getDefault().annotate(iae, ex);
160             throw iae;
161 // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
162
}
163
164         return loader.loadClass(classSource.getClassName());
165     }
166
167     /** Creates ClassSource object corresponding to project output classpath.
168      * @param fileInProject FileObject being source (.java) or output (.class)
169      * file in a project
170      * @param classname String name of class for which the ClassSource is
171      * created
172      */

173     public static ClassSource getProjectClassSource(FileObject fileInProject,
174                                                     String JavaDoc classname)
175     {
176         Project project = FileOwnerQuery.getOwner(fileInProject);
177         if (project == null)
178             return null; // the file is not in any project
179

180         // find the project output (presumably a JAR file) where the given
181
// source file is compiled (packed) to
182
AntArtifact[] artifacts =
183             AntArtifactQuery.findArtifactsByType(project, "jar"); // NOI18N
184
if (artifacts.length == 0)
185             return null; // there is no project output
186

187         String JavaDoc[] outputs = null;
188
189         for (int i=0; i < artifacts.length; i++) {
190             URI scriptLocation = artifacts[i].getScriptLocation().toURI();
191             URI[] artifactLocations = artifacts[i].getArtifactLocations();
192             for (int k=0; k < artifactLocations.length; k++) {
193                 File outputFile = new File(scriptLocation.resolve(artifactLocations[k]).normalize());
194
195                 URL outputURL;
196                 try {
197                     outputURL = outputFile.toURI().toURL();
198                 }
199                 catch (MalformedURLException ex) { // should not happen
200
continue;
201                 }
202
203                 if (FileUtil.isArchiveFile(outputURL))
204                     outputURL = FileUtil.getArchiveRoot(outputURL);
205                 FileObject sourceRoots[] =
206                     SourceForBinaryQuery.findSourceRoots(outputURL).getRoots();
207                 for (int j=0; j < sourceRoots.length; j++)
208                     if (FileUtil.isParentOf(sourceRoots[j], fileInProject)) {
209                         outputs = new String JavaDoc[] { outputFile.getAbsolutePath() };
210                         break;
211                     }
212                 if (outputs != null)
213                     break;
214             }
215         }
216
217         if (outputs == null) {
218             // no output found for given source file - the file might not be
219
// a source file ... but a binary output file - in this case return
220
// simply all project outputs as there is no good way to recognize
221
// the right one (and j2se project has just one output anyway)
222

223             if (!fileInProject.getExt().equals("class")) // NOI18N
224
return null; // not interested in other than .class binary files
225

226             ArrayList outputList = new ArrayList(artifacts.length);
227             for (int i=0; i < artifacts.length; i++) {
228                 URI[] artifactLocations = artifacts[i].getArtifactLocations();
229                 for (int j=0; j < artifactLocations.length; j++) {
230                     File outputFile = new File(
231                         artifacts[i].getScriptLocation().getParent()
232                         + File.separator
233                         + artifactLocations[j].getPath());
234                     outputList.add(outputFile.getAbsolutePath());
235             }
236             }
237             outputs = (String JavaDoc[])outputList.toArray(new String JavaDoc[outputList.size()]);
238         }
239
240         String JavaDoc[] types = new String JavaDoc[outputs.length];
241         for (int i=0; i < types.length; i++)
242             types[i] = ClassSource.PROJECT_SOURCE;
243
244         return new ClassSource(classname, types, outputs);
245     }
246
247     public static boolean isJava6ProjectPlatform(FileObject fileInProject) {
248         ClassPath classPath = ClassPath.getClassPath(fileInProject, ClassPath.BOOT);
249         if (classPath == null)
250             return false;
251
252         return classPath.findResource("javax/swing/GroupLayout.class") != null; // NOI18N
253
}
254
255     /** Updates project'c classpath with entries from ClassSource object.
256      */

257     public static boolean updateProject(FileObject fileInProject,
258                                         ClassSource classSource)
259         throws IOException
260     {
261         if (classSource.getCPRootCount() == 0)
262             return false; // nothing to add to project
263

264         Project project = FileOwnerQuery.getOwner(fileInProject);
265     if(project==null)
266         return false;
267     
268         ProjectClassPathExtender projectClassPath = (ProjectClassPathExtender)
269             project.getLookup().lookup(ProjectClassPathExtender.class);
270         if (projectClassPath == null)
271             return false; // not a project with classpath
272

273         for (int i=0, n=classSource.getCPRootCount(); i < n; i++) {
274             String JavaDoc type = classSource.getCPRootType(i);
275             String JavaDoc name = classSource.getCPRootName(i);
276
277             if (ClassSource.JAR_SOURCE.equals(type)) {
278                 FileObject jarFile = FileUtil.toFileObject(new File(name));
279                 projectClassPath.addArchiveFile(jarFile);
280             }
281             else if (ClassSource.LIBRARY_SOURCE.equals(type)) {
282                 Library lib = LibraryManager.getDefault().getLibrary(name);
283                 projectClassPath.addLibrary(lib);
284             }
285             else if (ClassSource.PROJECT_SOURCE.equals(type)) {
286                 File jarFile = new File(name);
287                 AntArtifact artifact =
288                     AntArtifactQuery.findArtifactFromFile(jarFile);
289                 if (artifact.getProject() != project) {
290                     URI[] locs = artifact.getArtifactLocations();
291                     for (int y=0; y<locs.length; y++ ) {
292                         projectClassPath.addAntArtifact(artifact, locs[y]);
293                     }
294                 }
295             }
296         }
297
298         return true;
299     }
300
301     /** Provides description for ClassSource object usable e.g. for error
302      * messages.
303      */

304     public static String JavaDoc getClassSourceDescription(ClassSource classSource) {
305         if (classSource == null || classSource.getCPRootCount() == 0) {
306             String JavaDoc className = classSource.getClassName();
307             if (className != null) {
308                 if (className.startsWith("javax.") // NOI18N
309
|| className.startsWith("java.")) // NOI18N
310
return getBundleString("MSG_StandardJDKSource"); // NOI18N
311
if (className.startsWith("org.netbeans.")) // NOI18N
312
return getBundleString("MSG_NetBeansSource"); // NOI18N
313
}
314         }
315         else {
316             String JavaDoc type = classSource.getCPRootType(0);
317             String JavaDoc name = classSource.getCPRootName(0);
318
319             if (ClassSource.JAR_SOURCE.equals(type)) {
320                 return MessageFormat.format(
321                     getBundleString("FMT_JarSource"), // NOI18N
322
new Object JavaDoc[] { name });
323             }
324             else if (ClassSource.LIBRARY_SOURCE.equals(type)) {
325                 Library lib = LibraryManager.getDefault().getLibrary(name);
326                 return MessageFormat.format(
327                     getBundleString("FMT_LibrarySource"), // NOI18N
328
new Object JavaDoc[] { lib != null ? lib.getDisplayName() : name });
329             }
330             else if (ClassSource.PROJECT_SOURCE.equals(type)) {
331                 try {
332                     Project project = FileOwnerQuery.getOwner(new File(name).toURI());
333                     return MessageFormat.format(
334                           getBundleString("FMT_ProjectSource"), // NOI18N
335
new Object JavaDoc[] { project == null ? name :
336                                          project.getProjectDirectory().getPath()
337                                            .replace('/', File.separatorChar) });
338                 }
339                 catch (Exception JavaDoc ex) {} // ignore
340
}
341         }
342
343         return getBundleString("MSG_UnspecifiedSource"); // NOI18N
344
}
345
346     static String JavaDoc getBundleString(String JavaDoc key) {
347         return NbBundle.getBundle(ClassPathUtils.class).getString(key);
348     }
349
350     // -----
351
// Registered class patterns for class loader type
352

353     private static FileObject patternSystemFolder;
354     private static FileObject patternSystemWithProjectFolder;
355
356     private static List patternsSystem;
357     private static List patternsSystemWithProject;
358
359     private static final String JavaDoc CL_LAYER_BASE = "org-netbeans-modules-form/classloader/"; // NOI18N
360
private static final String JavaDoc CL_SYSTEM_CLASS = "system"; // NOI18N
361
private static final String JavaDoc CL_SYSTEM_CLASS_WITH_PROJECT = "system_with_project"; // NOI18N
362

363     private static boolean isClassLoaderType(String JavaDoc className, int clType) {
364         List list = getClassPatterns(clType);
365         if (list == null)
366             return false;
367
368         Iterator it = list.iterator();
369         while (it.hasNext()) {
370             ClassPattern cp = (ClassPattern) it.next();
371             switch (cp.type) {
372                 case (ClassPattern.CLASS):
373                     if (className.equals(cp.name))
374                         return true;
375                     break;
376                 case (ClassPattern.PACKAGE):
377                     if (className.startsWith(cp.name) && (className.lastIndexOf('.') <= cp.name.length()))
378                         return true;
379                     break;
380                 case (ClassPattern.PACKAGE_AND_SUBPACKAGES):
381                     if (className.startsWith(cp.name))
382                         return true;
383                     break;
384             }
385         }
386         return false;
387     }
388
389     private static List getClassPatterns(int clType) {
390         List list = null;
391         switch (clType) {
392             case SYSTEM_CLASS:
393                 list = patternsSystem;
394                 if (list == null) {
395                     list = loadClassPatterns(getClassPatternsFolder(clType));
396                     patternsSystem = list;
397                 }
398                 break;
399             case SYSTEM_CLASS_WITH_PROJECT:
400                 list = patternsSystemWithProject;
401                 if (list == null) {
402                     list = loadClassPatterns(getClassPatternsFolder(clType));
403                     patternsSystemWithProject = list;
404                 }
405                 break;
406         }
407         return list;
408     }
409
410     private static FileObject getClassPatternsFolder(int clType) {
411         FileObject folder = null;
412         switch (clType) {
413             case SYSTEM_CLASS:
414                 folder = patternSystemFolder;
415                 if (folder == null) {
416                     folder = getClassPatternsFolder(CL_SYSTEM_CLASS);
417                     if (folder == null)
418                         return null;
419                     // in case of any change in files make all the patterns reload
420
folder.addFileChangeListener(new FileChangeAdapter() {
421                         public void fileDataCreated(FileEvent ev) {
422                             patternsSystem = null;
423                             loaders.clear();
424                         }
425                         public void fileDeleted(FileEvent ev) {
426                             patternsSystem = null;
427                             if (ev.getFile() == patternSystemFolder) {
428                                 patternSystemFolder.removeFileChangeListener(this);
429                                 patternSystemFolder = null;
430                             }
431                             loaders.clear();
432                         }
433                     });
434                     patternSystemFolder = folder;
435                 }
436                 break;
437             case SYSTEM_CLASS_WITH_PROJECT:
438                 folder = patternSystemWithProjectFolder;
439                 if (folder == null) {
440                     folder = getClassPatternsFolder(CL_SYSTEM_CLASS_WITH_PROJECT);
441                     if (folder == null)
442                         return null;
443                     // in case of any change in files make all the patterns reload
444
folder.addFileChangeListener(new FileChangeAdapter() {
445                         public void fileDataCreated(FileEvent ev) {
446                             patternsSystemWithProject = null;
447                             loaders.clear();
448                         }
449                         public void fileDeleted(FileEvent ev) {
450                             patternsSystemWithProject = null;
451                             if (ev.getFile() == patternSystemFolder) {
452                                 patternSystemWithProjectFolder.removeFileChangeListener(this);
453                                 patternSystemWithProjectFolder = null;
454                             }
455                             loaders.clear();
456                         }
457                     });
458                     patternSystemWithProjectFolder = folder;
459                 }
460                 break;
461         }
462         return folder;
463     }
464
465     private static FileObject getClassPatternsFolder(String JavaDoc folderName) {
466         FileObject folder = null;
467         if (folderName != null) {
468             try {
469                 folder = Repository.getDefault().getDefaultFileSystem()
470                              .findResource(CL_LAYER_BASE + folderName); // NOI18N
471
}
472             catch (Exception JavaDoc ex) {
473                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
474             }
475         }
476         return folder;
477     }
478
479     private static List loadClassPatterns(FileObject folder) {
480         List list = new ArrayList();
481         if (folder == null)
482             return list;
483
484         FileObject[] files = folder.getChildren();
485         for (int i=0; i < files.length; i++) {
486             try {
487                 BufferedReader r = new BufferedReader(new InputStreamReader(files[i].getInputStream()));
488                 String JavaDoc line = r.readLine();
489                 while (line != null) {
490                     if (!line.equals("")) { // NOI18N
491
ClassPattern cp;
492                         if (line.endsWith("**")) { // NOI18N
493
cp = new ClassPattern(line.substring(0, line.length()-2),
494                                                   ClassPattern.PACKAGE_AND_SUBPACKAGES);
495                         }
496                         else if (line.endsWith("*")) { // NOI18N
497
cp = new ClassPattern(line.substring(0, line.length()-1),
498                                                   ClassPattern.PACKAGE);
499                         }
500                         else {
501                             cp = new ClassPattern(line, ClassPattern.CLASS);
502                         }
503                         list.add(cp);
504                     }
505                     line = r.readLine();
506                 }
507             }
508             catch (IOException ex) {
509                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
510             }
511         }
512         return list;
513     }
514
515     private static class ClassPattern {
516         static final int CLASS = 0;
517         static final int PACKAGE = 1;
518         static final int PACKAGE_AND_SUBPACKAGES = 2;
519         String JavaDoc name;
520         int type;
521         
522         ClassPattern(String JavaDoc name, int type) {
523             this.name = name;
524             this.type = type;
525         }
526     }
527 }
528
Popular Tags