Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/jdt/graph/GraphUtil.java


1   package com.port80.eclipse.jdt.graph;
2   
3   import java.io.File;
4   import java.io.FileNotFoundException;
5   import java.io.FileOutputStream;
6   import java.io.PrintWriter;
7   import java.util.HashSet;
8   import java.util.Iterator;
9   import java.util.Map;
10  import java.util.Set;
11  
12  import org.eclipse.core.runtime.IProgressMonitor;
13  import org.eclipse.core.runtime.Path;
14  import org.eclipse.core.runtime.SubProgressMonitor;
15  import org.eclipse.jdt.core.IClassFile;
16  import org.eclipse.jdt.core.ICompilationUnit;
17  import org.eclipse.jdt.core.IJavaProject;
18  import org.eclipse.jdt.core.IPackageFragment;
19  import org.eclipse.jdt.core.IPackageFragmentRoot;
20  import org.eclipse.jdt.core.IType;
21  import org.eclipse.jdt.core.JavaModelException;
22  import org.eclipse.jdt.core.dom.AST;
23  import org.eclipse.jdt.core.dom.CompilationUnit;
24  import org.eclipse.jdt.core.dom.IBinding;
25  import org.eclipse.jdt.core.dom.IMethodBinding;
26  import org.eclipse.jdt.core.dom.IPackageBinding;
27  import org.eclipse.jdt.core.dom.ITypeBinding;
28  import org.eclipse.swt.SWT;
29  import org.eclipse.swt.widgets.FileDialog;
30  
31  import com.port80.eclipse.jdt.JdtPlugin;
32  import com.port80.graph.GraphException;
33  import com.port80.graph.IGraph;
34  import com.port80.graph.IVertex;
35  import com.port80.util.Msg;
36  
37  /**
38   * @author chrisl
39   *
40   * To change this generated comment edit the template variable "typecomment":
41   * Window>Preferences>Java>Templates.
42   * To enable and disable the creation of type comments go to
43   * Window>Preferences>Java>Code Generation.
44   */
45  public class GraphUtil {
46  
47    ////////////////////////////////////////////////////////////////////////
48  
49    private static final String NAME = "GraphUtil";
50    private static final boolean DEBUG = false;
51    private static final boolean VERBOSE = false;
52  
53    ////////////////////////////////////////////////////////////////////////
54  
55    private static String fOutDir = null;
56  
57    ////////////////////////////////////////////////////////////////////////
58  
59    public static boolean saveGraph(IGraph graph) {
60      boolean ret = false;
61      FileDialog dialog = new FileDialog(JdtPlugin.getActiveWorkbenchShell(), SWT.SAVE);
62      if (fOutDir == null)
63        fOutDir = JdtPlugin.getWorkspace().getRoot().getLocation().toString();
64      dialog.setFilterPath(fOutDir);
65      String fname = dialog.open();
66      if (fname != null && fname.length() > 0) {
67        Msg.println(NAME + ".saveGraph(): filename=" + fname);
68        fOutDir = new Path(fname).removeLastSegments(1).toString();
69        ret = graph.saveImage(fname, 1f);
70        if (!fname.endsWith(".dot"))
71          fname += ".dot";
72        File ifile = Msg.createFile(fname);
73        if (ifile != null) {
74          try {
75            PrintWriter writer = new PrintWriter(new FileOutputStream(ifile));
76            writer.println(graph.sprintGraph());
77            writer.close();
78          } catch (FileNotFoundException e) {
79            Msg.println(NAME + ".saveGraph(): Can't open output .dot file: " + fname);
80          }
81        }
82      }
83      return ret;
84    }
85  
86    public static void resolveReferences(
87      Object[] selected,
88      IGraph graph,
89      Map filemap,
90      IGraphAction action,
91      IProgressMonitor monitor) {
92      monitor.beginTask("Parsing", selected.length);
93      for (int i = 0; i < selected.length; ++i) {
94        try {
95          if (selected[i] instanceof IJavaProject) {
96            IJavaProject project = (IJavaProject) selected[i];
97            addUnitsFromFragments(
98              project.getPackageFragments(),
99              graph,
100             filemap,
101             action,
102             monitor);
103         } else if (selected[i] instanceof IPackageFragmentRoot) {
104           IPackageFragmentRoot root = (IPackageFragmentRoot) selected[i];
105           addUnitsFromFragments(root.getChildren(), graph, filemap, action, monitor);
106         } else if (selected[i] instanceof IPackageFragment) {
107           addUnitsFromFragment(
108             (IPackageFragment) selected[i],
109             graph,
110             filemap,
111             action,
112             monitor);
113         } else if (selected[i] instanceof ICompilationUnit) {
114           addCompilateUnit((ICompilationUnit) selected[i], graph, filemap, action);
115           monitor.worked(1);
116         } else if (selected[i] instanceof IClassFile) {
117           IClassFile classfile = (IClassFile) selected[i];
118           addClassFile(classfile, classfile.getJavaProject(), graph, filemap, action);
119           monitor.worked(1);
120         } else {
121           System.err.println(
122             NAME
123               + ".resolveReferences(): unknown selected: type="
124               + selected[i].getClass().getName()
125               + ": "
126               + selected[i]);
127           monitor.worked(1);
128         }
129       } catch (JavaModelException e) {}
130     }
131     monitor.done();
132   }
133 
134   /**
135    *  Find the vertices for the given typenames if exists.
136    *  @return Set of vertices found, empty set if none exists or typenames==null.
137    */
138   public static Set findVerticesFromTypenames(Set typenames, IGraph graph, Map filemap) {
139     Set ret = new HashSet();
140     if (typenames == null)
141       return ret;
142     IVertex v;
143     for (Iterator it = typenames.iterator(); it.hasNext();) {
144       String typename = (String) it.next();
145       String destpath = (String) filemap.get(typename);
146       if (destpath == null)
147         continue;
148       v = graph.getVertex(destpath);
149       if (v != null)
150         ret.add(v);
151     }
152     return ret;
153   }
154 
155   /**
156    * Extract a proper label string from the given type name.
157    */
158   public static String getLabel(String typename) {
159     int index = typename.indexOf(".java");
160     if (index > 0) {
161       typename = typename.substring(0, index);
162     }
163     index = typename.lastIndexOf('/');
164     if (index >= 0) {
165       typename = typename.substring(index + 1);
166     } else {
167       index = typename.lastIndexOf('.');
168       if (index >= 0)
169         typename = typename.substring(index + 1);
170     }
171     return typename;
172   }
173 
174   /** 
175    * Create a new vertex in the given graph with the given name.
176    * If vertex of given name already exists, return the existing vertex.
177    * @return Existing vertex or new created vertex, null if create error.
178    */
179   public static IVertex newVertex(String name, IGraph graph) {
180     IVertex ret = graph.getVertex(name);
181     if (ret == null) {
182       try {
183         ret = graph.newVertex(name, null);
184         ret.setAttr("label", getLabel(name));
185       } catch (GraphException e) {
186         Msg.err(NAME + ".newVertex(): can't create vertex: name=" + name, e);
187         ret = null;
188       }
189     }
190     return ret;
191   }
192 
193   /**
194    * Add mapping FullTypeName-> ICompilationUnit full path for all types 
195    * defined in the given ICompilationUnit.
196    * 
197    * @return The full path of the given ICompilationUnit.
198    */
199   public static String addToFileMap(ICompilationUnit unit, Map filemap) {
200     // Save typename->filename mapping.
201     String unitname = unit.getPath().toString();
202     try {
203       IType[] types = unit.getTypes();
204       for (int k = 0; k < types.length; ++k)
205         filemap.put(types[k].getFullyQualifiedName(), unitname);
206     } catch (JavaModelException e) {}
207     return unitname;
208   }
209 
210   ////////////////////////////////////////////////////////////////////////
211 
212   private static void addUnitsFromFragments(
213     Object[] fragments,
214     IGraph graph,
215     Map filemap,
216     IGraphAction action,
217     IProgressMonitor monitor) {
218     SubProgressMonitor submon = new SubProgressMonitor(monitor, 1);
219     submon.beginTask("Fragments", fragments.length);
220     for (int i = 0; i < fragments.length; ++i) {
221       if (!(fragments[i] instanceof IPackageFragment)) {
222         if (DEBUG)
223           System.err.println(
224             NAME
225               + ".addUnitsFromFragments(): not a fragment: type="
226               + fragments[i].getClass().getName()
227               + ": "
228               + fragments[i]);
229         submon.worked(1);
230         continue;
231       }
232       addUnitsFromFragment((IPackageFragment) fragments[i], graph, filemap, action, submon);
233     }
234   }
235 
236   public static void addUnitsFromFragment(
237     IPackageFragment fragment,
238     IGraph graph,
239     Map filemap,
240     IGraphAction action,
241     IProgressMonitor monitor) {
242 
243     ICompilationUnit[] sources = null;
244     IClassFile[] binaries = null;
245     IJavaProject project = fragment.getJavaProject();
246     try {
247       sources = fragment.getCompilationUnits();
248       binaries = fragment.getClassFiles();
249     } catch (JavaModelException ex) {
250       Msg.err(NAME + ".addUnitsFromFragment(): fragment=" + fragment, ex);
251     }
252     //
253     // Add source 
254     //
255     if (sources != null) {
256       SubProgressMonitor submon = new SubProgressMonitor(monitor, 1);
257       submon.beginTask("sources", sources.length);
258       for (int i = 0; i < sources.length; ++i) {
259         //String unitname = updateFileMap(sources[i], filemap);
260         String unitname = sources[i].getPath().toString();
261         CompilationUnit ast = AST.parseCompilationUnit(sources[i], true);
262         action.addRef(unitname, ast, graph, filemap);
263         submon.worked(1);
264         if (submon.isCanceled())
265           break;
266       }
267       submon.done();
268     }
269     //
270     // Add binaries
271     //
272     if (binaries != null) {
273       SubProgressMonitor submon = new SubProgressMonitor(monitor, 1);
274       submon.beginTask("binaries", binaries.length);
275       for (int i = 0; i < binaries.length; ++i) {
276         addClassFile(binaries[i], project, graph, filemap, action);
277         submon.worked(1);
278         if (submon.isCanceled())
279           break;
280       }
281       submon.done();
282     }
283   }
284 
285   public static void addClassFile(
286     IClassFile binary,
287     IJavaProject project,
288     IGraph graph,
289     Map filemap,
290     IGraphAction action) {
291     String source = null;
292     IType type = null;
293     try {
294       source = binary.getSource();
295       type = binary.getType();
296     } catch (JavaModelException ex) {
297       Msg.err(NAME + ".addClassFile(): binary=" + binary, ex);
298       return;
299     }
300     String typename = type.getFullyQualifiedName();
301     String name = typename;
302     int index = name.indexOf('$');
303     if (index > 0)
304       name = name.substring(0, index);
305     name = name.replace('.', '/');
306     name = name + ".java";
307     CompilationUnit ast = AST.parseCompilationUnit(source.toCharArray(), name, project);
308     action.addRef(typename, ast, graph, filemap);
309     //filemap.put(typename, typename);
310     if (DEBUG)
311       System
312         .err
313         .println(
314           NAME
315           + ".addClassFile(): name="
316           + name
317           + ", typename="
318           + typename
319           + ", project="
320           + project.getElementName()
321           + ", source.length="
322           + source.length() //+", source="
323       //+source
324       );
325   }
326 
327   public static void addCompilateUnit(ICompilationUnit unit, IGraph graph, Map filemap, IGraphAction action) {
328     CompilationUnit ast = AST.parseCompilationUnit(unit, true);
329     //String unitpath = updateFileMap(unit, fFileMap);
330     String unitpath = unit.getPath().toString();
331     action.addRef(unitpath, ast, graph, filemap);
332   }
333 
334   ////////////////////////////////////////////////////////////////////////
335 
336   public static String getFullTypeName(IBinding binding) {
337     if (binding == null)
338       return null;
339     if (!(binding instanceof ITypeBinding))
340       return null;
341     ITypeBinding type = (ITypeBinding) binding;
342     IPackageBinding p = type.getPackage();
343     String packagename = null;
344     if (p != null)
345       packagename = p.getName();
346     //FIXME: How to get the type id ($n) of an anonymous class.
347     String typename = getSimpleTypeName(type);
348     if (packagename != null)
349       return packagename + "." + typename;
350     else
351       return typename;
352   }
353 
354   /**
355    * Simple typename without package qualifiers.
356    */
357   public static String getSimpleTypeName(ITypeBinding type) {
358     String typename;
359     if (type.isAnonymous()) {
360       ITypeBinding parent = type.getSuperclass();
361       if (parent == null || parent.getName().equals("Object")) {
362         ITypeBinding[] a = type.getInterfaces();
363         if (a != null && a.length > 0)
364           parent = a[0];
365       }
366       if (parent != null)
367         typename = "{" + parent.getName() + "}";
368       else
369         typename = "{Object}";
370     } else
371       typename = type.getName();
372     if ((type = type.getDeclaringClass()) != null) {
373       typename = getSimpleTypeName(type) + "$" + typename;
374     }
375     return typename;
376   }
377 
378   public static String getFullMethodName(IMethodBinding method) {
379     if (method == null)
380       return null;
381     ITypeBinding type = method.getDeclaringClass();
382     String typename = GraphUtil.getFullTypeName(type);
383     String methodname = getSimpleMethodName(method);
384     if (typename != null)
385       return typename + "." + methodname;
386     else
387       return methodname;
388   }
389 
390   /**
391    * Method name without type qualifier and parameter signatures.
392    */
393   public static String getSimpleMethodName(IMethodBinding method) {
394     if (method == null)
395       return null;
396     String methodname = method.getName();
397     if (methodname == null || methodname.length() == 0) {
398       // Anonymous class constructor invokation returns "()" without a valid method name!
399       ITypeBinding type = method.getDeclaringClass();
400       methodname = getSimpleTypeName(type);
401     }
402     return methodname;
403   }
404 
405   /**
406    * Method signature with full typenames.
407    */
408   public static String getMethodSignature(IMethodBinding method) {
409     if (method == null)
410       return null;
411     return getFullMethodName(method) + getMethodParamSignature(method);
412   }
413 
414   /**
415    * Method signature with simple name instead of full typenames.
416    */
417   public static String getMethodParamSignature(IMethodBinding method) {
418     if (method == null)
419       return null;
420     StringBuffer signature = new StringBuffer();
421     signature.append('(');
422     ITypeBinding[] params = method.getParameterTypes();
423     for (int i = 0; i < params.length; ++i) {
424       if (i != 0)
425         signature.append(',');
426       signature.append(getFullTypeName(params[i]));
427     }
428     signature.append(')');
429     return signature.toString();
430   }
431 
432   /**
433    * Method signature with simple name instead of full typenames.
434    */
435   public static String getSimpleMethodParamSignature(IMethodBinding method) {
436     if (method == null)
437       return null;
438     StringBuffer signature = new StringBuffer();
439     signature.append('(');
440     ITypeBinding[] params = method.getParameterTypes();
441     for (int i = 0; i < params.length; ++i) {
442       if (i != 0)
443         signature.append(',');
444       signature.append(params[i].getName());
445     }
446     signature.append(')');
447     return signature.toString();
448   }
449 
450   /**
451    * Truncate string.
452    */
453   public static String chop(String str, int max) {
454     if (str.length() <= max)
455       return str;
456     return (str.substring(0, max - 3) + "...");
457   }
458 
459   ////////////////////////////////////////////////////////////////////////
460 }