KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > binding > classes > ClassCache


1 /*
2 Copyright (c) 2003-2005, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.binding.classes;
30
31 import java.io.File JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.HashMap JavaDoc;
35
36 import org.apache.bcel.classfile.Utility;
37 import org.jibx.runtime.JiBXException;
38
39 /**
40  * Cache for class files being modified. Handles loading and saving of class
41  * files. Classes are loaded directly from the file system paths supplied on
42  * initialization in preference to the system class path.
43  *
44  * @author Dennis M. Sosnoski
45  * @version 1.0
46  */

47
48 public class ClassCache
49 {
50     /** Singleton instance of class (created when paths set) */
51     private static ClassCache s_instance;
52     
53     /** Paths to be searched for class files. */
54     private String JavaDoc[] m_paths;
55     
56     /** Root directories corresponding to paths. */
57     private File JavaDoc[] m_roots;
58     
59     /** Map from class names to actual class information. */
60     private HashMap JavaDoc m_classMap;
61     
62     /**
63      * Constructor. Discards jar file paths and normalizes all other paths
64      * (except the empty path) to end with the system path separator character.
65      *
66      * @param paths ordered set of paths to be searched for class files
67      */

68      
69     private ClassCache(String JavaDoc[] paths) {
70         ArrayList JavaDoc keepers = new ArrayList JavaDoc();
71         for (int i = 0; i < paths.length; i++) {
72             String JavaDoc path = paths[i];
73             int mark = path.lastIndexOf('.');
74             if (mark < 0 || !"jar".equalsIgnoreCase(path.substring(mark+1))) {
75                 keepers.add(paths[i]);
76             }
77         }
78         m_paths = new String JavaDoc[keepers.size()];
79         m_roots = new File JavaDoc[keepers.size()];
80         for (int i = 0; i < keepers.size(); i++) {
81             String JavaDoc path = (String JavaDoc)keepers.get(i);
82             int length = path.length();
83             if (length > 0) {
84                 if (path.charAt(length-1) != File.separatorChar) {
85                     path = path + File.separator;
86                 }
87             }
88             m_paths[i] = path;
89             m_roots[i] = new File JavaDoc(path);
90         }
91         m_classMap = new HashMap JavaDoc();
92     }
93     
94     /**
95      * Get class information. Looks up the class in cache, and if not already
96      * present tries to find it based on the class file search path list. If
97      * the class file is found it is loaded and this method calls itself
98      * recursively to load the whole hierarchy of superclasses.
99      *
100      * @param name fully-qualified name of class to be found
101      * @return class information, or <code>null</code> if class not found
102      * @throws JiBXException on any error accessing class file
103      */

104      
105     private ClassFile getClassFileImpl(String JavaDoc name) throws JiBXException {
106         
107         // first try for match on fully-qualified class name
108
Object JavaDoc match = m_classMap.get(name);
109         if (match != null) {
110             return (ClassFile)match;
111         } else if (ClassItem.isPrimitive(name) || name.endsWith("[]")) {
112             
113             // create synthetic class file for array type
114
ClassFile cf = new ClassFile(name, Utility.getSignature(name));
115             m_classMap.put(name, cf);
116             return cf;
117             
118         } else {
119             try {
120                 
121                 // got to load it, convert to file path format
122
ClassFile cf = null;
123                 String JavaDoc path = name.replace('.', File.separatorChar) + ".class";
124                 for (int i = 0; i < m_paths.length; i++) {
125                 
126                     // check for file found off search path
127
File JavaDoc file = new File JavaDoc(m_paths[i], path);
128                     if (file.exists()) {
129                     
130                         // load file information
131
cf = new ClassFile(name, m_roots[i], file);
132                         break;
133                         
134                     }
135                 }
136             
137                 // finally try loading (non-modifiable) class from classpath
138
if (cf == null) {
139                     cf = new ClassFile(name);
140                 }
141             
142                 // check for class found
143
if (cf != null) {
144                 
145                     // force loading of superclass as well (to root)
146
String JavaDoc sname = cf.getSuperName();
147                     if (!name.equals(sname) && sname != null) {
148                         ClassFile sf = getClassFileImpl(sname);
149                         if (sf == null) {
150                             throw new JiBXException("Superclass " + sname +
151                                 " of class " + name + " not found");
152                         }
153                         cf.setSuperFile(sf);
154                     }
155                     
156                     // add class information to cache
157
m_classMap.put(name, cf);
158                 
159                 }
160                 return cf;
161                 
162             } catch (IOException JavaDoc ex) {
163                 throw new JiBXException("Error loading class " + name);
164             }
165         }
166     }
167     
168     /**
169      * Get class information. Looks up the class in cache, and if not already
170      * present tries to find it based on the class file search path list. If
171      * the class file is found it is loaded along with all superclasses.
172      *
173      * @param name fully-qualified name of class to be found
174      * @return class information, or <code>null</code> if class not found
175      * @throws JiBXException on any error accessing class file
176      */

177      
178     public static ClassFile getClassFile(String JavaDoc name) throws JiBXException {
179         return s_instance.getClassFileImpl(name);
180     }
181     
182     /**
183      * Add created class information to cache.
184      *
185      * @param information for class to be added
186      */

187      
188     /*package*/ static void addClassFile(ClassFile cf) {
189         s_instance.m_classMap.put(cf.getName(), cf);
190     }
191     
192     /**
193      * Set class paths to be searched. Discards jar file paths and normalizes
194      * all other paths (except the empty path) to end with the system path
195      * separator character.
196      *
197      * @param paths ordered set of paths to be searched for class files
198      */

199      
200     public static void setPaths(String JavaDoc[] paths) {
201         s_instance = new ClassCache(paths);
202     }
203 }
Popular Tags