C:\Java WorkShop\Lexx\src\lexx\api\JavaPackages.java

1    package lexx.api; 
2     
3    import java.io.BufferedInputStream; 
4    import java.io.BufferedOutputStream; 
5    import java.io.File; 
6    import java.io.FileInputStream; 
7    import java.io.FileOutputStream; 
8    import java.io.IOException; 
9    import java.io.ObjectInputStream; 
10   import java.io.ObjectOutputStream; 
11   import java.util.Collections; 
12   import java.util.Comparator; 
13   import java.util.ConcurrentModificationException; 
14   import java.util.Enumeration; 
15   import java.util.HashMap; 
16   import java.util.List; 
17   import java.util.StringTokenizer; 
18   import java.util.Vector; 
19   import java.util.jar.JarFile; 
20    
21   import javax.swing.JLabel; 
22   import javax.swing.JTree; 
23   import javax.swing.event.TreeSelectionEvent; 
24   import javax.swing.event.TreeSelectionListener; 
25   import javax.swing.tree.DefaultMutableTreeNode; 
26    
27   import lexx.gui.EditorFrame; 
28   import lexx.trie.MultiTrie; 
29   import lexx.trie.RootNode; 
30   import lexx.trie.Trie; 
31   import lexx.utils.StringSearch; 
32    
33   /** 
34    * <p>Reads in Class Files</p> 
35    * <p>This class reads class files from jar/direcotry and stores them in 
36    * a trie</p> 
37    * <p>Copyright (c) 2002-2003</p> 
38    * @since 19/03/2003 
39    * @author Mohammed Imran 
40    * @version 1.0 
41    */ 
42    
43   public final class JavaPackages implements Packages 
44   { 
45     private static final org.apache.log4j.Logger log = org.apache.log4j.Logger. 
46         getLogger(JavaPackages.class); 
47    
48     /** 
49      * Stores the full name of the classes/objects such as javax.swing.JFrame 
50      */ 
51     private RootNode classes; 
52     /** 
53      * Store the short name of each class/object such as JFrame 
54      */ 
55     private RootNode shortNames; 
56     /** 
57      * Stores the classes/objects in a lsit 
58      */ 
59     private List classMap; 
60     private final String pathSeparator = System.getProperty("path.separator"); 
61     private String classPath = ""; 
62     private String sourcePath = ""; 
63     private final File jreStore = new File(System.getProperty("java.io.tmpdir") + 
64                                            System.getProperty("file.separator") + 
65                                            "lexxJRE" + 
66                                            System.getProperty("java.version") + 
67                                            ".obj"); 
68     private final File classMapStore = new File(System.getProperty( 
69         "java.io.tmpdir") + 
70                                                 System.getProperty( 
71         "file.separator") + 
72                                                 "lexxClassMap" + ".obj"); 
73    
74     //used in debugging 
75     private JTree tree; 
76     private EditorFrame frame; 
77    
78     private boolean hasFinished = false; 
79    
80     /** 
81      * @param projectPath - directory which contains the source code and external libraries 
82      * @param statusLabel - uses the label to log information regarding what this class is doing 
83      * @param libPath - directory which contains any external libararies 
84      */ 
85     public JavaPackages(String projectPath, JLabel statusLabel, String libPath) 
86     { 
87       this(statusLabel, libPath); 
88    
89       if("".equals(classPath)) 
90       { 
91         classPath = projectPath; 
92       } 
93       else 
94       { 
95         classPath += ";" + projectPath; 
96    
97       } 
98       sourcePath = projectPath; 
99       File f = new File(projectPath); 
100      this.getClassesFromFile(f, projectPath); 
101    } 
102   
103    /** 
104     * @param statusLabel - uses the label to log information regarding what this class is doing 
105     * @param libPath - directory which contains any external libararies 
106     */ 
107    private JavaPackages(JLabel status, String libPath) 
108    { 
109      hasFinished = false; 
110      classMap = new Vector(); 
111   
112      classes = new RootNode("Contains All Possible Java Classes - " + 
113                             "created in JavaPackages"); 
114      shortNames = new RootNode("Contains All Possible Java Classes without " + 
115                                "including the package names - created in JavaPackages"); 
116      boolean success = false; 
117   
118      if(jreStore.exists()) //load jre from file - quicker 
119      { //very import when comes to testing 
120        log.fine("JavaPackages: now reading java file"); 
121        try 
122        { 
123          if(status != null) 
124          { 
125            status.setText("Reading java runtime"); 
126          } 
127          ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new 
128              FileInputStream(jreStore))); 
129   
130          if(status != null) 
131          { 
132            status.setText("Reading java runtime 1/3"); 
133          } 
134          shortNames = (RootNode) in.readObject(); 
135          if(status != null) 
136          { 
137            status.setText("Reading java runtime 2/3"); 
138          } 
139          classes = (RootNode) in.readObject(); 
140          if(status != null) 
141          { 
142            status.setText("Reading java runtime 3/3"); 
143          } 
144          classMap = (List) in.readObject(); 
145          in.close(); 
146          success = true; 
147        } 
148        catch(Exception ex) 
149        { 
150          log.warn("Unable to load previously stored java files\n" + ex, ex); 
151          jreStore.delete(); 
152        } 
153      } 
154   
155      if(!success) 
156      { 
157        String jars = System.getProperty("sun.boot.class.path"); //System.getProperty("java.class.path") ;//+ pathSeparator + System.getProperty("java.ext.dirs") + pathSeparator + System.getProperty("sun.boot.class.path"); 
158        this.update(jars, status); 
159   
160        try 
161        { 
162          /** Information about writing/reading objects from Core Java 2 Vol. 1 chapter 12 by Cay S.Horstmann + Gary Cornell */ 
163          if(status != null) 
164          { 
165            status.setText("Storing java runtime"); 
166          } 
167          ObjectOutputStream out = new ObjectOutputStream(new 
168              BufferedOutputStream(new FileOutputStream(jreStore))); 
169          out.writeObject(shortNames); 
170          out.writeObject(classes); 
171          out.writeObject(classMap); 
172          out.close(); 
173        } 
174        catch(IOException ex) 
175        { 
176          log.fatal(ex, ex); 
177        } 
178      } 
179   
180      if(libPath != null) 
181      { 
182        classPath += ";" + libPath; 
183      } 
184   
185      this.update(classPath, status); 
186   
187      if(status != null) 
188      { 
189        status.setText("Sorting API"); 
190      } 
191      if(log.isDebugEnabled()) 
192      { 
193        log.debug("Sorting API"); 
194   
195      } 
196      this.sort(classMap); 
197   
198      //this ensures that the trees arent' stored in memory as they can be quite big 
199      //note I am still working on this 
200      if(lexx.utils.Config.converseMemory()) 
201      { 
202        if(status != null) 
203        { 
204          status.setText("Conserving Memory 1/3"); 
205        } 
206        conserveMemory(status); 
207        if(status != null) 
208        { 
209          status.setText("Conserving Memory 2/3"); 
210        } 
211        classes = (RootNode) classes.cloneToDisk("C:/k/1", 3); 
212        if(status != null) 
213        { 
214          status.setText("Conserving Memory 3/3"); 
215        } 
216        shortNames = (RootNode) shortNames.cloneToDisk("C:/k/2", 2); 
217      } 
218   
219      if( lexx.utils.Config.isDebug() ) 
220      { 
221        lexx.trie.TrieDebug.showList( this.getClassEnvironment() ); 
222        lexx.trie.TrieDebug.showList( this.getEveryPossibleClass()  ); 
223      } 
224   
225      hasFinished = true; 
226    } 
227   
228    /** 
229     * Shuts down this class to save more memory, only required in Testing 
230     * @return - weither it was sucessessful in closing the files 
231     */ 
232    public boolean close() 
233    { 
234      this.classes = null; 
235      this.classMap = null; 
236      this.shortNames = null; 
237      return true; 
238    } 
239   
240    /** 
241     * Under construction 
242     */ 
243    private void conserveMemory(JLabel status) 
244    { 
245      if(status != null && hasFinished) 
246      { 
247        status.setText("Conserving Memory"); 
248   
249      } 
250      try 
251      { 
252        ObjectOutputStream out = new ObjectOutputStream(new 
253            BufferedOutputStream(new FileOutputStream( 
254            classMapStore))); 
255        out.writeObject(classMap); 
256        out.close(); 
257        classMapStore.deleteOnExit(); 
258        classMap = null; 
259        /* 
260              if( status != null) 
261                status.setText("Conserving Memory: 2/3" ); 
262              out = new ObjectOutputStream(new 
263             BufferedOutputStream(new FileOutputStream( 
264                  classesStore))); 
265              out.writeObject(classes); 
266              out.close(); 
267              classesStore.deleteOnExit(); 
268              classes = null; 
269              System.gc(); 
270              if( status != null) 
271                status.setText("Conserving Memory: 1/3" ); 
272              out = new ObjectOutputStream(new 
273                  BufferedOutputStream(new FileOutputStream(allClassesStore))); 
274              out.writeObject(allClasses); 
275              out.close(); 
276              allClassesStore.deleteOnExit(); 
277              allClasses = null; 
278              System.gc(); 
279         */ 
280      } 
281      catch(IOException ex) 
282      { 
283        lexx.utils.Config.setConverseMemory(false); 
284        log.fatal(ex, ex); 
285      } 
286    } 
287   
288    /** 
289     * @return a string containing the class path for the project 
290     */ 
291    public final String getClassPath() 
292    { 
293      return classPath; 
294    } 
295   
296    /** 
297     * This updates internal data structures 
298     * @param path - the jar file/directory which has been changed/added 
299     * @param status - logs what exactly is happening 
300     */ 
301    private void update(String path, JLabel status) 
302    { 
303      StringTokenizer st = new StringTokenizer(path, pathSeparator); 
304   
305      HashMap names = new HashMap(); 
306      while(st.hasMoreTokens()) 
307      { //use map since it automatically removes any duplicates 
308        String fileName = st.nextToken(); 
309        names.put(fileName, fileName); 
310      } 
311   
312      Object[] tmpNames = names.values().toArray(); 
313      for(int i = 0; i < tmpNames.length; i++) 
314      { 
315        String fileName = tmpNames[i].toString(); 
316   
317        if(status != null) 
318        { 
319          status.setText("Reading API: " + fileName); 
320        } 
321        if(log.isDebugEnabled()) 
322        { 
323          log.debug("Reading API: " + fileName); 
324   
325        } 
326        if(".".equals(fileName)) //it means current directory 
327        { 
328          fileName = System.getProperty("user.dir"); 
329   
330        } 
331        this.update(new File(fileName)); 
332      } 
333    } 
334   
335    /** 
336     * This updates internal data structures 
337     * @param f - the jar file/directory which has been changed/added 
338     */ 
339    public final void update(File f) 
340    { 
341      if(classMap == null) 
342      { 
343        classMap = this.getClassMap(); 
344      } 
345   
346      if(!f.exists()) 
347      { 
348        return; 
349      } 
350   
351      try 
352      { 
353        String fileName = f.toString(); 
354   
355        if(fileName.endsWith(".jar")) 
356        { 
357          JarFile file = new JarFile(f); 
358          Enumeration em = file.entries(); 
359          while(em.hasMoreElements()) 
360          { 
361            String tmp = em.nextElement().toString(); 
362            if(tmp.endsWith("class") && !StringSearch.contains("$", tmp)) 
363            { //removes helper methods 
364              StringTokenizer token = new StringTokenizer(tmp, "/\\"); 
365              this.add(token, classMap, tmp, fileName); 
366            } 
367          } 
368        } 
369        else 
370        { 
371          this.getClassesFromFile(f, fileName); 
372        } 
373      } 
374      catch(IOException ex) 
375      { 
376        log.fatal("Unable to update tree with " + f + "\n\n" + ex, ex); 
377      } 
378   
379      if(lexx.utils.Config.converseMemory() && hasFinished) 
380      { 
381        this.conserveMemory(null); 
382      } 
383    } 
384   
385    /** 
386     * This method searchs recursivly throw directories and adding an class files 
387     * @param f the directory you want to search 
388     * @param path the path where the directory is 
389     */ 
390    private void getClassesFromFile(File f, String path) 
391    { 
392      File[] files = f.listFiles(); 
393   
394      if(files == null) 
395      { 
396        return; 
397      } 
398   
399      for(int i = 0; i < files.length; i++) 
400      { 
401        if(files[i].isDirectory()) 
402        { 
403          this.getClassesFromFile(files[i], path); 
404        } 
405        else 
406        { 
407   
408          String tmp = files[i].getAbsolutePath(); 
409          tmp = tmp.substring(path.length() + 1, tmp.length()).trim(); 
410          if(tmp != null && tmp.endsWith(".class") && 
411             !StringSearch.contains("$", tmp)) 
412          { //removes helper methods 
413            StringTokenizer token = new StringTokenizer(tmp, "/\\"); 
414            this.add(token, this.getClassMap(), tmp, files[i].toString()); 
415          } 
416        } 
417      } 
418    } 
419   
420    /** 
421     * @return a list of all the classes 
422     */ 
423    public final List getClassMap() 
424    { 
425      if(classMap == null) 
426      { 
427        try 
428        { 
429          ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new 
430              FileInputStream(classMapStore))); 
431          return(List) in.readObject(); 
432        } 
433        catch(Exception ex) 
434        { 
435          log.fatal(ex, ex); 
436        } 
437      } 
438      return classMap; 
439    } 
440   
441    public final String toString() 
442    { 
443      return "JavaPackages: contains " + " classes"; 
444    } 
445   
446    /** 
447     * Takes the string in the form Java/Lang/Process.class and returns Process.class 
448     * @param name fullName of class file 
449     * @return just the name of the class file 
450     */ 
451    private static ClassName getClassName(String name, String filePath) 
452        throws CantReadClassException 
453    { 
454      StringTokenizer st = new StringTokenizer(name, "/\\"); 
455      String path = ""; 
456      while(st.hasMoreTokens()) 
457      { 
458        String s = st.nextToken(); 
459        if(s.endsWith(".class")) //is a class 
460        { //so it ignores the first . 
461          if(path.length() > 0) 
462          { 
463            return new ClassName(path.substring(1, path.length()), s, filePath, true); 
464          } 
465          else 
466          { 
467            return new ClassName("", s, filePath); 
468          } 
469        } 
470        path += "." + s; 
471      } 
472      return null; 
473    } 
474   
475    /** 
476     * Checks if a given directory name exists in an arraylist 
477     */ 
478    private static boolean doesContainDirectory(List l, String dirName) 
479    { 
480      for(int i = 0; i < l.size(); i++) 
481      { 
482        if(l.get(i)instanceof Directory) 
483        { 
484          Directory d = (Directory) l.get(i); 
485          if(dirName.equals(d.getDirectoryName())) 
486          { 
487            return true; 
488          } 
489        } 
490      } 
491      return false; 
492    } 
493   
494    /** 
495     * Retruns a directory if it exists in an arraylist 
496     */ 
497    private static Directory getDirectory(List l, String dirName) 
498    { 
499      for(int i = 0; i < l.size(); i++) 
500      { 
501        if(l.get(i)instanceof Directory) 
502        { 
503          Directory d = (Directory) l.get(i); 
504          if(dirName.equals(d.getDirectoryName())) 
505          { 
506            return d; 
507          } 
508        } 
509      } 
510      return null; 
511    } 
512   
513    /** 
514     * A recursive method that breaks down A String into directories and classnames 
515     * For example javax.swing.JFrame 
516     *    + javax 
517     *    --+ swing 
518     *      --- JFrame 
519     */ 
520    private void add(StringTokenizer st, List map, String originalName, 
521                     String fullPath) 
522    { 
523      String filePath = fullPath; 
524   
525      if(!filePath.endsWith("jar")) 
526      { 
527        try 
528        { 
529          File f = new File(fullPath); 
530          if(f.isFile()) //that means it needs to be cut down 
531          { 
532            filePath = fullPath.substring(0, 
533                                          fullPath.length() - originalName.length()); 
534          } 
535        } 
536        catch(Exception ex) 
537        { 
538          log.fatal(ex, ex); 
539        } 
540      } 
541   
542      if(st.hasMoreElements()) 
543      { 
544        String s = st.nextToken(); 
545        if(s.endsWith(".class")) // is a class 
546        { 
547          try 
548          { 
549            ClassName c = this.getClassName(originalName, filePath); 
550            ClassName shortC = (ClassName) c.clone(); 
551            shortC.setShowFullName(false); 
552            map.add(shortC); 
553            classes.add(c.toString(), c, false); 
554            shortNames.add(c.getName(), c, false); 
555          } 
556          catch(Exception ex) 
557          { 
558            log.warn(ex); 
559          } 
560        } 
561        else 
562        { 
563          Directory child; 
564          if(this.doesContainDirectory(map, s)) 
565          { 
566            child = this.getDirectory(map, s); 
567          } 
568          else 
569          { 
570            child = new Directory(s, new Vector(), false); 
571            map.add(child); 
572          } 
573          this.add(st, child.getList(), originalName, filePath); 
574        } 
575      } 
576    } 
577   
578    /** 
579     * This method is used in testing allow you to see how the classes look like 
580     */ 
581    public final JTree setupTree(lexx.gui.EditorFrame editFrame) 
582    { 
583      //sets up tree 
584      frame = editFrame; 
585      DefaultMutableTreeNode top = new DefaultMutableTreeNode("Java Class"); 
586      this.setupTree(top, this.getClassMap()); 
587      tree = new JTree(top); 
588   
589      tree.addTreeSelectionListener(new TreeSelectionListener() 
590      { 
591        public void valueChanged(TreeSelectionEvent e) 
592        { 
593          DefaultMutableTreeNode node = (DefaultMutableTreeNode) 
594                                        tree.getLastSelectedPathComponent(); 
595   
596          if(node == null) 
597          { 
598            return; 
599          } 
600   
601          Object nodeInfo = node.getUserObject(); 
602          if(nodeInfo instanceof ClassName) 
603          { 
604            ClassName c = (ClassName) nodeInfo; 
605            frame.addClass(c); 
606          } 
607        } 
608      }); 
609   
610      return tree; 
611    } 
612   
613    /** 
614     * This is a helper method for setupTree 
615     */ 
616    private void setupTree(DefaultMutableTreeNode top, List code) 
617    { 
618      for(int i = 0; i < code.size(); i++) 
619      { 
620        DefaultMutableTreeNode tmp = new DefaultMutableTreeNode(code.get(i)); 
621        top.add(tmp); 
622        if(code.get(i)instanceof Directory) 
623        { 
624          setupTree(tmp, ( (Directory) (code.get(i))).getList()); 
625        } 
626      } 
627    } 
628   
629    /** 
630     * This sorts an arraylist alphabetically (ignoring case) 
631     */ 
632    private static void sort(List list) 
633    { 
634      for(int i = 0; i < list.size(); i++) 
635      { 
636        if(list.get(i) == null) 
637        { 
638          list.remove(i); 
639        } 
640        list.remove(null); 
641      } 
642   
643      lexx.utils.Utilities.removeDuplicates(list); 
644   
645      for(int i = 0; i < list.size(); i++) 
646      { 
647        if(list.get(i)instanceof Directory) 
648        { 
649          Directory d = (Directory) list.get(i); 
650          try 
651          { 
652            sort(d.getList()); 
653          } 
654          catch(ConcurrentModificationException ex) 
655          { 
656            log.warn(ex, ex); 
657          } 
658        } 
659      } 
660   
661      Collections.sort(list, new Comparator() 
662      { 
663        public int compare(Object a, Object b) 
664        { 
665          String a1, b1; 
666   
667          if(a == null || b == null) 
668          { 
669            System.err.println( 
670                "ERROR in class lexx.api.JavaPackages: during the method sort, object " + 
671                a + " and object " + b); 
672   
673            if(a == null && b == null) 
674            { 
675              return 0; 
676            } 
677   
678            if(a == null) 
679            { 
680              return -1; 
681            } 
682            else 
683            { 
684              return 1; 
685            } 
686          } 
687   
688          if(a instanceof Directory) 
689          { 
690            a1 = ( (Directory) a).getDirectoryName().toLowerCase(); 
691          } 
692          else 
693          { 
694            a1 = ( (ClassName) a).getName().toLowerCase(); 
695   
696          } 
697          if(b instanceof Directory) 
698          { 
699            b1 = ( (Directory) b).getDirectoryName().toLowerCase(); 
700          } 
701          else 
702          { 
703            b1 = ( (ClassName) b).getName().toLowerCase(); 
704   
705          } 
706          return a1.compareTo(b1); 
707        } 
708      }); 
709    } 
710   
711    public static Object getObject(String name, List classList) 
712    { 
713      Comparator c = new Comparator() 
714      { 
715        public int compare(Object classname, Object name) 
716        { 
717          String c = ( (ClassName) classname).getName(); 
718          String findName = (String) name; 
719   
720          //have to use toLowerCase since objects are sorted irrespective of case 
721          return c.toLowerCase().compareTo(findName.toLowerCase()); 
722        } 
723      }; 
724      try 
725      { 
726        return classList.get(Collections.binarySearch(classList, name, c)); 
727      } 
728      catch(Exception ex) 
729      { 
730        log.fatal(ex, ex); 
731        return null; 
732      } 
733    } 
734   
735    /** 
736     * Stores all the available classes in the project. However it 
737     * contains both the short and full name of the class, such as 
738     * <br>java.awt.Frame :: java.awt.Frame 
739     * <br>         Frame :: java.awt.Frame 
740     * @return a trie data structure containing these classes 
741     */ 
742    public final Trie getEveryPossibleClass() 
743    { 
744      Trie[] nodes = new Trie[2]; 
745      nodes[0] = shortNames; 
746      nodes[1] = classes; 
747      return new MultiTrie(nodes); 
748    } 
749   
750    /** 
751     * Stores all the available classes in the project. However this only stores 
752     * the full name of the class, such as 
753     * <br>java.awt.Frame :: java.awt.Frame, but not <i> 
754     * <br>         Frame :: java.awt.Frame</i> 
755     * @return a trie data structure containing these classes 
756     */ 
757    public final Trie getClassEnvironment() 
758    { 
759      return classes; 
760    } 
761   
762    public final List getClassNames(List imports) 
763    { 
764      String[] result = new String[imports.size()]; 
765      for(int i = 0; i < result.length; i++) 
766      { 
767        result[i] = imports.get(i).toString(); 
768      } 
769      return this.getClassNames(result); 
770    } 
771   
772    /** 
773     * This returns all the class names/directories available from the imports 
774     * @param imports contains an array of string of imports like "javax.swing.*" or "java.awt.Frame" 
775     * @return returns an arraylist 
776     */ 
777    private List getClassNames(String[] imports) 
778    { 
779      List result = new Vector(); 
780      List map = this.getClassMap(); 
781      for(int i = 0; i < map.size(); i++) 
782      { 
783        result.add(map.get(i)); 
784   
785      } 
786      for(int i = 0; i < imports.length; i++) 
787      { 
788        String name = imports[i]; 
789        if(name.endsWith(".*")) //add whole list of classes 
790        { 
791          StringTokenizer st = new StringTokenizer(name.substring(0, 
792              name.length() - 2), ".", false); 
793          List tmp = classMap; 
794   
795          while(st.hasMoreTokens()) 
796          { 
797            Directory d = this.getDirectory(tmp, st.nextToken()); 
798            if(d != null) 
799            { 
800              tmp = d.getList(); 
801            } 
802            else 
803            { 
804              tmp = new Vector(); 
805              break; 
806            } 
807          } 
808   
809          for(int x = 0; x < tmp.size(); x++) 
810          { 
811            if(tmp.get(x)instanceof ClassName) 
812            { 
813              result.add(tmp.get(x)); 
814            } 
815          } 
816        } 
817        else 
818        { 
819          String class_name = ""; 
820          String dir_name = ""; 
821          for(int x = name.length() - 1; x >= 0; x--) 
822          { 
823            if(name.charAt(x) == '.') 
824            { 
825              class_name = name.substring(x + 1, name.length()); 
826              dir_name = name.substring(0, x); 
827              break; 
828            } 
829          } 
830   
831          //goes to directory 
832          StringTokenizer st = new StringTokenizer(dir_name, ".", false); 
833          List tmp = classMap; 
834   
835          while(st.hasMoreTokens()) 
836          { 
837            Directory d = this.getDirectory(tmp, st.nextToken()); 
838            if(d != null) 
839            { 
840              tmp = d.getList(); 
841            } 
842            else 
843            { 
844              tmp = new Vector(); 
845              break; 
846            } 
847          } 
848   
849          result.add(this.getObject(class_name, tmp)); 
850        } 
851      } 
852      this.sort(result); 
853      return result; 
854    } 
855   
856    /** 
857     * Using getClassMap() 
858     * @param name name of the package you wish to get 
859     * @return all the classes found in that package 
860     */ 
861    public final Directory getDirectory(String name) 
862    { 
863      StringTokenizer st = new StringTokenizer(name, ".", false); 
864      List tmp = classMap; 
865      Directory result = null; 
866   
867      while(st.hasMoreTokens()) 
868      { 
869        result = this.getDirectory(tmp, st.nextToken()); 
870        if(result != null) 
871        { 
872          tmp = result.getList(); 
873        } 
874      } 
875      return result; 
876    } 
877   
878    public static JavaPackages getDefaultPackage() 
879    { 
880      return new JavaPackages(new JLabel(), ""); 
881    } 
882  }