KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > projects > SourcePathProviderImpl


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.debugger.jpda.projects;
21
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.beans.PropertyChangeSupport JavaDoc;
24 import java.io.File JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.*;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.TreeSet JavaDoc;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33 import java.util.regex.Pattern JavaDoc;
34 import java.util.regex.Matcher JavaDoc;
35
36 import org.netbeans.api.java.platform.JavaPlatformManager;
37
38 import org.netbeans.spi.debugger.jpda.SourcePathProvider;
39 import org.netbeans.api.debugger.Session;
40 import org.netbeans.spi.debugger.ContextProvider;
41
42 import org.netbeans.api.java.classpath.ClassPath;
43 import org.netbeans.api.java.classpath.GlobalPathRegistry;
44 import org.netbeans.api.java.platform.JavaPlatform;
45 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
46
47 import org.openide.filesystems.FileObject;
48 import org.openide.filesystems.FileStateInvalidException;
49 import org.openide.filesystems.FileSystem;
50 import org.openide.filesystems.FileUtil;
51 import org.openide.filesystems.JarFileSystem;
52 import org.openide.filesystems.Repository;
53 import org.openide.filesystems.URLMapper;
54
55
56 /**
57  *
58  * @author Jan Jancura
59  */

60 public class SourcePathProviderImpl extends SourcePathProvider {
61     
62     private static boolean verbose =
63         System.getProperty ("netbeans.debugger.sourcepathproviderimpl") != null;
64     
65     private static Logger JavaDoc logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.projects");
66     
67     private static final Pattern JavaDoc thisDirectoryPattern = Pattern.compile("(/|\\A)\\./");
68     private static final Pattern JavaDoc parentDirectoryPattern = Pattern.compile("(/|\\A)([^/]+?)/\\.\\./");
69
70     private Session session;
71     // contains source path + jdk source path for JPDAStart task
72
private ClassPath originalSourcePath;
73     private ClassPath smartSteppingSourcePath;
74     private String JavaDoc[] sourceRoots;
75     private PropertyChangeSupport JavaDoc pcs;
76     
77
78     public SourcePathProviderImpl (ContextProvider contextProvider) {
79         pcs = new PropertyChangeSupport JavaDoc (this);
80         this.session = (Session) contextProvider.lookupFirst
81             (null, Session.class);
82         Map properties = (Map) contextProvider.lookupFirst
83             (null, Map.class);
84         
85         // 2) get default allSourceRoots of source roots used for stepping
86
if (properties != null) {
87             smartSteppingSourcePath = (ClassPath) properties.get ("sourcepath");
88             ClassPath jdkCP = (ClassPath) properties.get ("jdksources");
89             if ( (jdkCP == null) && (JavaPlatform.getDefault () != null) )
90                 jdkCP = JavaPlatform.getDefault ().getSourceFolders ();
91             originalSourcePath = jdkCP == null ?
92                 smartSteppingSourcePath :
93                 ClassPathSupport.createProxyClassPath (
94                     new ClassPath[] {
95                         smartSteppingSourcePath,
96                         jdkCP
97                     }
98             );
99         } else {
100             Set JavaDoc allSourceRoots = new HashSet JavaDoc (
101                 GlobalPathRegistry.getDefault ().getSourceRoots ()
102             );
103             originalSourcePath = ClassPathSupport.createClassPath (
104                 (FileObject[]) allSourceRoots.toArray
105                     (new FileObject [allSourceRoots.size()])
106             );
107             
108             JavaPlatform[] platforms = JavaPlatformManager.getDefault ().
109                 getInstalledPlatforms ();
110             int i, k = platforms.length;
111             for (i = 0; i < k; i++) {
112                 FileObject[] roots = platforms [i].getSourceFolders ().
113                     getRoots ();
114                 int j, jj = roots.length;
115                 for (j = 0; j < jj; j++)
116                     allSourceRoots.remove (roots [j]);
117             }
118             smartSteppingSourcePath = ClassPathSupport.createClassPath (
119                 (FileObject[]) allSourceRoots.toArray
120                     (new FileObject [allSourceRoots.size()])
121             );
122         }
123         sourceRoots = getRoots (
124             Arrays.asList (smartSteppingSourcePath.getRoots ()).iterator ()
125         );
126         
127         if (verbose)
128             System.out.println
129                 ("SPPI: init originalSourcePath " + originalSourcePath);
130         if (verbose)
131             System.out.println (
132                 "SPPI: init smartSteppingSourcePath " + smartSteppingSourcePath
133             );
134     }
135
136     /**
137      * Translates a relative path ("java/lang/Thread.java") to url
138      * ("file:///C:/Sources/java/lang/Thread.java"). Uses GlobalPathRegistry
139      * if global == true.
140      *
141      * @param relativePath a relative path (java/lang/Thread.java)
142      * @param global true if global path should be used
143      * @return url
144      */

145     public String JavaDoc getURL (String JavaDoc relativePath, boolean global) { if (verbose) System.out.println ("SPPI: getURL " + relativePath + " global " + global);
146         FileObject fo = null;
147         relativePath = normalize(relativePath);
148         if (!global) {
149             fo = smartSteppingSourcePath.findResource
150                 (relativePath); if (verbose) System.out.println ("SPPI: fo " + fo);
151         } else {
152             fo = originalSourcePath.findResource
153                 (relativePath); if (verbose) System.out.println ("SPPI: fo " + fo);
154             if (fo == null)
155                 fo = GlobalPathRegistry.getDefault ().findResource (relativePath); if (verbose) System.out.println ("SPPI: fo2 " + fo);
156         }
157         if (fo == null) return null;
158         try {
159             return fo.getURL ().toString ();
160         } catch (FileStateInvalidException e) { if (verbose) System.out.println ("SPPI: FileStateInvalidException");
161             return null;
162         }
163     }
164     
165     /**
166      * Returns relative path for given url.
167      *
168      * @param url a url of resource file
169      * @param directorySeparator a directory separator character
170      * @param includeExtension whether the file extension should be included
171      * in the result
172      *
173      * @return relative path
174      */

175     public String JavaDoc getRelativePath (
176         String JavaDoc url,
177         char directorySeparator,
178         boolean includeExtension
179     ) {
180         // 1) url -> FileObject
181
FileObject fo = null; if (verbose) System.out.println ("SPPI: getRelativePath " + url);
182         try {
183             fo = URLMapper.findFileObject (new URL JavaDoc (url)); if (verbose) System.out.println ("SPPI: fo " + fo);
184         } catch (MalformedURLException JavaDoc e) {
185             //e.printStackTrace ();
186
return null;
187         }
188         ClassPath cp = ClassPath.getClassPath (fo, ClassPath.SOURCE);
189         if (cp == null)
190             cp = ClassPath.getClassPath (fo, ClassPath.COMPILE);
191         if (cp == null) return null;
192         return cp.getResourceName (
193             fo,
194             directorySeparator,
195             includeExtension
196         );
197     }
198     
199     /**
200      * Returns the source root (if any) for given url.
201      *
202      * @param url a url of resource file
203      *
204      * @return the source root or <code>null</code> when no source root was found.
205      */

206     public String JavaDoc getSourceRoot(String JavaDoc url) {
207         Iterator JavaDoc it = GlobalPathRegistry.getDefault().getSourceRoots().iterator();
208         while (it.hasNext()) {
209             FileObject fileObject = (FileObject) it.next ();
210             try {
211                 String JavaDoc rootURL = fileObject.getURL().toString();
212                 if (url.startsWith(rootURL)) {
213                     File JavaDoc f = null;
214                     if (fileObject.getFileSystem () instanceof JarFileSystem)
215                         f = ((JarFileSystem) fileObject.getFileSystem ()).
216                             getJarFile ();
217                     else
218                         f = FileUtil.toFile (fileObject);
219                     if (f != null) {
220                         return f.getAbsolutePath ();
221                     }
222                 }
223             } catch (FileStateInvalidException ex) {
224                 // Invalid source root - skip
225
}
226         }
227         return null; // not found
228
}
229     
230     /**
231      * Returns allSourceRoots of original source roots.
232      *
233      * @return allSourceRoots of original source roots
234      */

235     public String JavaDoc[] getOriginalSourceRoots () {
236         return getRoots (GlobalPathRegistry.getDefault ().getSourceRoots ().
237             iterator ());
238     }
239     
240     /**
241      * Returns array of source roots.
242      *
243      * @return array of source roots
244      */

245     public String JavaDoc[] getSourceRoots () {
246         return sourceRoots;
247     }
248     
249     /**
250      * Sets array of source roots.
251      *
252      * @param sourceRoots a new array of sourceRoots
253      */

254     public void setSourceRoots (String JavaDoc[] sourceRoots) {
255         if (logger.isLoggable(Level.FINE)) {
256             logger.fine("SourcePathProviderImpl.setSourceRoots("+java.util.Arrays.asList(sourceRoots)+")");
257         }
258         int i, k = sourceRoots.length;
259         FileObject[] fos = new FileObject [k];
260         for (i = 0; i < k; i++)
261             fos [i] = getFileObject (sourceRoots [i]);
262         Object JavaDoc old = smartSteppingSourcePath;
263         smartSteppingSourcePath = ClassPathSupport.createClassPath (fos);
264         this.sourceRoots = sourceRoots;
265         pcs.firePropertyChange (
266             PROP_SOURCE_ROOTS, old, smartSteppingSourcePath
267         );
268     }
269     
270     /**
271      * Adds property change listener.
272      *
273      * @param l new listener.
274      */

275     public void addPropertyChangeListener (PropertyChangeListener JavaDoc l) {
276         pcs.addPropertyChangeListener (l);
277     }
278
279     /**
280      * Removes property change listener.
281      *
282      * @param l removed listener.
283      */

284     public void removePropertyChangeListener (
285         PropertyChangeListener JavaDoc l
286     ) {
287         pcs.removePropertyChangeListener (l);
288     }
289     
290     
291     // helper methods ..........................................................
292

293     /**
294      * Normalizes the given path by removing unnecessary "." and ".." sequences.
295      * This normalization is needed because the compiler stores source paths like "foo/../inc.jsp" into .class files.
296      * Such paths are not supported by our ClassPath API.
297      * TODO: compiler bug? report to JDK?
298      *
299      * @param path path to normalize
300      * @return normalized path without "." and ".." elements
301      */

302     private static String JavaDoc normalize(String JavaDoc path) {
303       for (Matcher JavaDoc m = thisDirectoryPattern.matcher(path); m.find(); )
304       {
305         path = m.replaceAll("$1");
306         m = thisDirectoryPattern.matcher(path);
307       }
308       for (Matcher JavaDoc m = parentDirectoryPattern.matcher(path); m.find(); )
309       {
310         if (!m.group(2).equals("..")) {
311           path = path.substring(0, m.start()) + m.group(1) + path.substring(m.end());
312           m = parentDirectoryPattern.matcher(path);
313         }
314       }
315       return path;
316     }
317     
318     /**
319      * Returns array of source roots for given ClassPath as Strings.
320      */

321     private static String JavaDoc[] getRoots (Iterator JavaDoc it) {
322         Set JavaDoc roots = new TreeSet JavaDoc ();
323         while (it.hasNext ()) {
324             FileObject fileObject = (FileObject) it.next ();
325             File JavaDoc f = null;
326             try {
327                 if (fileObject.getFileSystem () instanceof JarFileSystem)
328                     f = ((JarFileSystem) fileObject.getFileSystem ()).
329                         getJarFile ();
330                 else
331                     f = FileUtil.toFile (fileObject);
332             } catch (FileStateInvalidException ex) {
333             }
334             if (f != null)
335                 roots.add (f.getAbsolutePath ());
336         }
337         String JavaDoc[] fs = new String JavaDoc [roots.size ()];
338         return (String JavaDoc[]) roots.toArray (fs);
339     }
340
341     /**
342      * Returns FileObject for given String.
343      */

344     private FileObject getFileObject (String JavaDoc file) {
345         File JavaDoc f = new File JavaDoc (file);
346         FileObject fo = FileUtil.toFileObject (f);
347         if (FileUtil.isArchiveFile (fo))
348             fo = FileUtil.getArchiveRoot (fo);
349         return fo;
350     }
351 }
352
Popular Tags