Source Code Cross Referenced for AltClassLoader.java in  » Code-Analyzer » soot » soot » util » cfgcmd » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Code Analyzer » soot » soot.util.cfgcmd 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Soot - a J*va Optimization Framework
002:         * Copyright (C) 2003 John Jorgensen
003:         *
004:         * This library is free software; you can redistribute it and/or
005:         * modify it under the terms of the GNU Lesser General Public
006:         * License as published by the Free Software Foundation; either
007:         * version 2.1 of the License, or (at your option) any later version.
008:         *
009:         * This library is distributed in the hope that it will be useful,
010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012:         * Lesser General Public License for more details.
013:         *
014:         * You should have received a copy of the GNU Lesser General Public
015:         * License along with this library; if not, write to the
016:         * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017:         * Boston, MA 02111-1307, USA.
018:         */
019:
020:        package soot.util.cfgcmd;
021:
022:        import java.io.File;
023:        import java.io.FileInputStream;
024:        import java.util.List;
025:        import java.util.LinkedList;
026:        import java.util.Map;
027:        import java.util.HashMap;
028:        import java.util.StringTokenizer;
029:        import soot.Singletons;
030:        import soot.G;
031:
032:        /**
033:         * <p>A {@link ClassLoader} that loads specified classes from a
034:         * different class path than that given by the value of
035:         * <code>java.class.path</code> in {@link System#getProperties()}.</p>
036:         *
037:         * <p>This class is part of Soot's test infrastructure. It allows
038:         * loading multiple implementations of a class with a given
039:         * name, and was written to compare different
040:         * implementations of Soot's CFG representations.</p>
041:         */
042:        public class AltClassLoader extends ClassLoader {
043:
044:            private final static boolean DEBUG = false;
045:
046:            private String[] locations; // Locations in the alternate
047:            // classpath.
048:            private final Map<String, Class> alreadyFound = new HashMap<String, Class>(); // Maps from already loaded
049:            // classnames to their
050:            // Class objects.
051:
052:            private final Map<String, String> nameToMangledName = new HashMap<String, String>();// Maps from the names
053:            // of classes to be
054:            // loaded from the alternate
055:            // classpath to mangled
056:            // names to use for them.
057:
058:            private final Map<String, String> mangledNameToName = new HashMap<String, String>();// Maps from the mangled names
059:
060:            // of classes back to their
061:            // original names.
062:
063:            /**
064:             * Constructs an <code>AltClassLoader</code> for inclusion in Soot's
065:             * global variable manager, {@link G}.
066:             *
067:             * @param g guarantees that the constructor may only be called from
068:             * {@link Singletons}.
069:             */
070:            public AltClassLoader(Singletons.Global g) {
071:            }
072:
073:            /**
074:             * Returns the single instance of <code>AltClassLoader</code>, which
075:             * loads classes from the classpath set by the most recent call to
076:             * its {@link #setAltClassPath}.
077:             *
078:             * @return Soot's <code>AltClassLoader</code>.
079:             */
080:            public static AltClassLoader v() {
081:                return G.v().soot_util_cfgcmd_AltClassLoader();
082:            }
083:
084:            /**
085:             * Sets the list of locations in the alternate classpath.
086:             *
087:             * @param classPath A list of directories and jar files to
088:             * search for class files, delimited by 
089:             * {@link File#pathSeparator}.
090:             */
091:            public void setAltClassPath(String altClassPath) {
092:                List<String> locationList = new LinkedList<String>();
093:                for (StringTokenizer tokens = new StringTokenizer(altClassPath,
094:                        File.pathSeparator, false); tokens.hasMoreTokens();) {
095:                    String location = tokens.nextToken();
096:                    locationList.add(location);
097:                }
098:                locations = new String[locationList.size()];
099:                locations = locationList.toArray(locations);
100:            }
101:
102:            /**
103:             * Specifies the set of class names that the <code>AltClassLoader</code>
104:             * should load from the alternate classpath instead of the 
105:             * regular classpath.
106:             *
107:             * @param classNames[] an array containing the names of classes to
108:             * be loaded from the AltClassLoader.
109:             */
110:            public void setAltClasses(String[] classNames) {
111:                nameToMangledName.clear();
112:                for (String origName : classNames) {
113:                    String mangledName = mangleName(origName);
114:                    nameToMangledName.put(origName, mangledName);
115:                    mangledNameToName.put(mangledName, origName);
116:                }
117:            }
118:
119:            /**
120:             * Mangles a classname so that it will not be found on the system
121:             * classpath by our parent class loader, even if there is a class
122:             * with the original name there.  We use a crude heuristic to do this that
123:             * happens to work with the names we have needed to mangle to date.
124:             * The heuristic requires that <code>origName</code> include at least
125:             * two dots (i.e., the class must be in a package, where
126:             * the package name has at least two components). More sophisticated
127:             * possibilities certainly exist, but they would require 
128:             * more thorough parsing of the class file.
129:             *
130:             * @param origName the name to be mangled.
131:             * @return the mangled name.
132:             * @throws IllegalArgumentException if <code>origName</code> is not
133:             * amenable to our crude mangling.
134:             */
135:            private static String mangleName(String origName)
136:                    throws IllegalArgumentException {
137:                final char dot = '.';
138:                final char dotReplacement = '_';
139:                StringBuffer mangledName = new StringBuffer(origName);
140:                int replacements = 0;
141:                int lastDot = origName.lastIndexOf(dot);
142:                for (int nextDot = lastDot; (nextDot = origName.lastIndexOf(
143:                        dot, nextDot - 1)) >= 0;) {
144:                    mangledName.setCharAt(nextDot, dotReplacement);
145:                    replacements++;
146:                }
147:                if (replacements <= 0) {
148:                    throw new IllegalArgumentException(
149:                            "AltClassLoader.mangleName()'s crude classname mangling cannot deal with "
150:                                    + origName);
151:                }
152:                return mangledName.toString();
153:            }
154:
155:            /**
156:             * <p>
157:             * Loads a class from either the regular classpath, or the alternate
158:             * classpath, depending on whether it looks like we have already
159:             * mangled its name.</p>
160:             *
161:             * <p> This method follows the steps provided by <a
162:             * href="http://www.javaworld.com/javaworld/jw-03-2000/jw-03-classload.html#resources">Ken
163:             * McCrary's ClasssLoader tutorial</a>.</p>
164:             *
165:             * @param maybeMangledName A string from which the desired class's
166:             * name can be determined.  It may have been mangled by {@link
167:             * AltClassLoader#loadClass(String) AltClassLoader.loadClass()} so
168:             * that the regular <code>ClassLoader</code> to which we are
169:             * delegating won't load the class from the regular classpath.
170:             * @return the loaded class.
171:             * @throws ClassNotFoundException if the class cannot be loaded.
172:             *
173:             */
174:            protected Class findClass(String maybeMangledName)
175:                    throws ClassNotFoundException {
176:                if (DEBUG) {
177:                    G.v().out.println("AltClassLoader.findClass("
178:                            + maybeMangledName + ')');
179:                }
180:
181:                Class result = alreadyFound.get(maybeMangledName);
182:                if (result != null) {
183:                    return result;
184:                }
185:
186:                String name = mangledNameToName.get(maybeMangledName);
187:                if (name == null) {
188:                    name = maybeMangledName;
189:                }
190:                String pathTail = "/" + name.replace('.', File.separatorChar)
191:                        + ".class";
192:
193:                for (String element : locations) {
194:                    String path = element + pathTail;
195:                    try {
196:                        FileInputStream stream = new FileInputStream(path);
197:                        byte[] classBytes = new byte[stream.available()];
198:                        stream.read(classBytes);
199:                        replaceAltClassNames(classBytes);
200:                        result = defineClass(maybeMangledName, classBytes, 0,
201:                                classBytes.length);
202:                        alreadyFound.put(maybeMangledName, result);
203:                        return result;
204:                    } catch (java.io.IOException e) {
205:                        // Try the next location.
206:                    } catch (ClassFormatError e) {
207:                        if (DEBUG) {
208:                            e.printStackTrace(G.v().out);
209:                        }
210:                        // Try the next location.
211:                    }
212:                }
213:                throw new ClassNotFoundException("Unable to find class" + name
214:                        + " in alternate classpath");
215:            }
216:
217:            /**
218:             * <p>Loads a class, from the alternate classpath if the class's
219:             * name has been included in the list of alternate classes with
220:             * {@link #setAltClasses(String[]) setAltClasses()}, from the
221:             * regular system classpath otherwise.  When a alternate class is
222:             * loaded, its references to other alternate classes are also
223:             * resolved to the alternate classpath.
224:             * 
225:             * @param name the name of the class to load.
226:             * @return the loaded class.
227:             * @throws ClassNotFoundException if the class cannot be loaded.
228:             */
229:            public Class loadClass(String name) throws ClassNotFoundException {
230:                if (DEBUG) {
231:                    G.v().out.println("AltClassLoader.loadClass(" + name + ")");
232:                }
233:
234:                String nameForParent = nameToMangledName.get(name);
235:                if (nameForParent == null) {
236:                    // This is not an alternate class
237:                    nameForParent = name;
238:                }
239:
240:                if (DEBUG) {
241:                    G.v().out
242:                            .println("AltClassLoader.loadClass asking parent for "
243:                                    + nameForParent);
244:                }
245:                return super .loadClass(nameForParent, false);
246:            }
247:
248:            /**
249:             * Replaces any occurrences in <code>classBytes</code> of
250:             * classnames to be loaded from the alternate class path with
251:             * the corresponding mangled names.  Of course we should really
252:             * parse the class pool properly, since the simple-minded, brute
253:             * force replacment done here could produce problems with some
254:             * combinations of classnames and class contents. But we've got away
255:             * with this so far!
256:             */
257:            private void replaceAltClassNames(byte[] classBytes) {
258:                for (Object element : nameToMangledName.entrySet()) {
259:                    Map.Entry entry = (Map.Entry) element;
260:                    String origName = (String) entry.getKey();
261:                    origName = origName.replace('.', '/');
262:                    String mangledName = (String) entry.getValue();
263:                    mangledName = mangledName.replace('.', '/');
264:                    findAndReplace(classBytes, stringToUtf8Pattern(origName),
265:                            stringToUtf8Pattern(mangledName));
266:                    findAndReplace(classBytes,
267:                            stringToTypeStringPattern(origName),
268:                            stringToTypeStringPattern(mangledName));
269:                }
270:            }
271:
272:            /**
273:             * Returns the bytes that correspond to a 
274:             * CONSTANT_Utf8 constant pool entry containing
275:             * the passed string.
276:             */
277:            private static byte[] stringToUtf8Pattern(String s) {
278:                byte[] origBytes = s.getBytes();
279:                int length = origBytes.length;
280:                final byte CONSTANT_Utf8 = 1;
281:                byte[] result = new byte[length + 3];
282:                result[0] = CONSTANT_Utf8;
283:                result[1] = (byte) (length & 0xff00);
284:                result[2] = (byte) (length & 0x00ff);
285:                for (int i = 0; i < length; i++) {
286:                    result[i + 3] = origBytes[i];
287:                }
288:                return result;
289:            }
290:
291:            /**
292:             * Returns the bytes that correspond to a type signature string
293:             * containing the passed string.
294:             */
295:            private static byte[] stringToTypeStringPattern(String s) {
296:                byte[] origBytes = s.getBytes();
297:                int length = origBytes.length;
298:                byte[] result = new byte[length + 2];
299:                result[0] = (byte) 'L';
300:                for (int i = 0; i < length; i++) {
301:                    result[i + 1] = origBytes[i];
302:                }
303:                result[length + 1] = (byte) ';';
304:                return result;
305:            }
306:
307:            /**
308:             * Replaces all occurrences of the <code>pattern</code> in <code>text</code>
309:             * with <code>replacement</code>. 
310:             * @throws IllegalArgumentException if the lengths of <code>text</code>
311:             * and <code>replacement</code> differ.
312:             */
313:            private static void findAndReplace(byte[] text, byte[] pattern,
314:                    byte[] replacement) throws IllegalArgumentException {
315:                int patternLength = pattern.length;
316:                if (patternLength != replacement.length) {
317:                    throw new IllegalArgumentException(
318:                            "findAndReplace(): The lengths of the pattern and replacement must match.");
319:                }
320:                int match = 0;
321:                while ((match = findMatch(text, pattern, match)) >= 0) {
322:                    replace(text, replacement, match);
323:                    match += patternLength;
324:                }
325:            }
326:
327:            /**
328:             * A naive string-searching algorithm for finding a pattern
329:             * in a byte array. 
330:             *
331:             * @param text the array to search in.
332:             * @param pattern the string of bytes to search for.
333:             * @param start the first position in text to search (0-based).
334:             * @return the index in text where the first occurrence of
335:             *         <code>pattern</code> in <code>text</code> after <code>start</code>
336:             *         begins.  Returns -1 if <code>pattern</code> does not occur
337:             *         in <code>text</code> after <code>start</code>.
338:             */
339:            private static int findMatch(byte[] text, byte[] pattern, int start) {
340:                int textLength = text.length;
341:                int patternLength = pattern.length;
342:                nextBase: for (int base = start; base < textLength; base++) {
343:                    for (int t = base, p = 0; p < patternLength; t++, p++) {
344:                        if (text[t] != pattern[p]) {
345:                            continue nextBase;
346:                        }
347:                    }
348:                    return base;
349:                }
350:                return -1;
351:            }
352:
353:            /**
354:             * Replace the <code>replacement.length</code> bytes in <code>text</code>
355:             * starting at <code>start</code> with the bytes in <code>replacement</code>.
356:             * @throws ArrayIndexOutOfBounds if there are not
357:             * <code>replacement.length</code> remaining after <code>text[start]</code>.
358:             */
359:            private static void replace(byte[] text, byte[] replacement,
360:                    int start) {
361:                for (int t = start, p = 0; p < replacement.length; t++, p++) {
362:                    text[t] = replacement[p];
363:                }
364:            }
365:
366:            /**
367:             * <p>A main() entry for basic unit testing.</p>
368:             *
369:             * <p>Usage: path class ...</p>
370:             */
371:            public static void main(String[] argv)
372:                    throws ClassNotFoundException {
373:                AltClassLoader.v().setAltClassPath(argv[0]);
374:                for (int i = 1; i < argv.length; i++) {
375:                    AltClassLoader.v().setAltClasses(new String[] { argv[i] });
376:                    G.v().out.println("main() loadClass(" + argv[i] + ")");
377:                    AltClassLoader.v().loadClass(argv[i]);
378:                }
379:            }
380:
381:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.