Source Code Cross Referenced for AntClassLoader.java in  » Build » ANT » org » apache » tools » ant » 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 » Build » ANT » org.apache.tools.ant 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         *
0017:         */
0018:
0019:        package org.apache.tools.ant;
0020:
0021:        import java.io.ByteArrayOutputStream;
0022:        import java.io.File;
0023:        import java.io.FileInputStream;
0024:        import java.io.IOException;
0025:        import java.io.InputStream;
0026:        import java.io.InputStreamReader;
0027:        import java.io.Reader;
0028:        import java.lang.reflect.Constructor;
0029:        import java.net.MalformedURLException;
0030:        import java.net.URL;
0031:        import java.util.Collections;
0032:        import java.util.Enumeration;
0033:        import java.util.HashMap;
0034:        import java.util.Hashtable;
0035:        import java.util.Map;
0036:        import java.util.StringTokenizer;
0037:        import java.util.Vector;
0038:        import java.util.jar.Attributes;
0039:        import java.util.jar.Attributes.Name;
0040:        import java.util.jar.JarFile;
0041:        import java.util.jar.Manifest;
0042:        import java.util.zip.ZipEntry;
0043:        import java.util.zip.ZipFile;
0044:        import org.apache.tools.ant.types.Path;
0045:        import org.apache.tools.ant.util.CollectionUtils;
0046:        import org.apache.tools.ant.util.FileUtils;
0047:        import org.apache.tools.ant.util.JavaEnvUtils;
0048:        import org.apache.tools.ant.util.LoaderUtils;
0049:        import org.apache.tools.ant.launch.Locator;
0050:
0051:        /**
0052:         * Used to load classes within ant with a different classpath from
0053:         * that used to start ant. Note that it is possible to force a class
0054:         * into this loader even when that class is on the system classpath by
0055:         * using the forceLoadClass method. Any subsequent classes loaded by that
0056:         * class will then use this loader rather than the system class loader.
0057:         *
0058:         * <p>
0059:         * Note that this classloader has a feature to allow loading
0060:         * in reverse order and for "isolation".
0061:         * Due to the fact that a number of
0062:         * methods in java.lang.ClassLoader are final (at least
0063:         * in java 1.4 getResources) this means that the
0064:         * class has to fake the given parent.
0065:         * </p>
0066:         *
0067:         */
0068:        public class AntClassLoader extends ClassLoader implements 
0069:                SubBuildListener {
0070:
0071:            private static final FileUtils FILE_UTILS = FileUtils
0072:                    .getFileUtils();
0073:
0074:            /**
0075:             * An enumeration of all resources of a given name found within the
0076:             * classpath of this class loader. This enumeration is used by the
0077:             * ClassLoader.findResources method, which is in
0078:             * turn used by the ClassLoader.getResources method.
0079:             *
0080:             * @see AntClassLoader#findResources(String)
0081:             * @see java.lang.ClassLoader#getResources(String)
0082:             */
0083:            private class ResourceEnumeration implements  Enumeration {
0084:                /**
0085:                 * The name of the resource being searched for.
0086:                 */
0087:                private String resourceName;
0088:
0089:                /**
0090:                 * The index of the next classpath element to search.
0091:                 */
0092:                private int pathElementsIndex;
0093:
0094:                /**
0095:                 * The URL of the next resource to return in the enumeration. If this
0096:                 * field is <code>null</code> then the enumeration has been completed,
0097:                 * i.e., there are no more elements to return.
0098:                 */
0099:                private URL nextResource;
0100:
0101:                /**
0102:                 * Constructs a new enumeration of resources of the given name found
0103:                 * within this class loader's classpath.
0104:                 *
0105:                 * @param name the name of the resource to search for.
0106:                 */
0107:                ResourceEnumeration(String name) {
0108:                    this .resourceName = name;
0109:                    this .pathElementsIndex = 0;
0110:                    findNextResource();
0111:                }
0112:
0113:                /**
0114:                 * Indicates whether there are more elements in the enumeration to
0115:                 * return.
0116:                 *
0117:                 * @return <code>true</code> if there are more elements in the
0118:                 *         enumeration; <code>false</code> otherwise.
0119:                 */
0120:                public boolean hasMoreElements() {
0121:                    return (this .nextResource != null);
0122:                }
0123:
0124:                /**
0125:                 * Returns the next resource in the enumeration.
0126:                 *
0127:                 * @return the next resource in the enumeration
0128:                 */
0129:                public Object nextElement() {
0130:                    URL ret = this .nextResource;
0131:                    findNextResource();
0132:                    return ret;
0133:                }
0134:
0135:                /**
0136:                 * Locates the next resource of the correct name in the classpath and
0137:                 * sets <code>nextResource</code> to the URL of that resource. If no
0138:                 * more resources can be found, <code>nextResource</code> is set to
0139:                 * <code>null</code>.
0140:                 */
0141:                private void findNextResource() {
0142:                    URL url = null;
0143:                    while ((pathElementsIndex < pathComponents.size())
0144:                            && (url == null)) {
0145:                        try {
0146:                            File pathComponent = (File) pathComponents
0147:                                    .elementAt(pathElementsIndex);
0148:                            url = getResourceURL(pathComponent,
0149:                                    this .resourceName);
0150:                            pathElementsIndex++;
0151:                        } catch (BuildException e) {
0152:                            // ignore path elements which are not valid relative to the
0153:                            // project
0154:                        }
0155:                    }
0156:                    this .nextResource = url;
0157:                }
0158:            }
0159:
0160:            /**
0161:             * The size of buffers to be used in this classloader.
0162:             */
0163:            private static final int BUFFER_SIZE = 8192;
0164:            /**
0165:             * Number of array elements in a test array of strings
0166:             */
0167:            private static final int NUMBER_OF_STRINGS = 256;
0168:
0169:            /**
0170:             * The components of the classpath that the classloader searches
0171:             * for classes.
0172:             */
0173:            private Vector pathComponents = new Vector();
0174:
0175:            /**
0176:             * The project to which this class loader belongs.
0177:             */
0178:            private Project project;
0179:
0180:            /**
0181:             * Indicates whether the parent class loader should be
0182:             * consulted before trying to load with this class loader.
0183:             */
0184:            private boolean parentFirst = true;
0185:
0186:            /**
0187:             * These are the package roots that are to be loaded by the parent class
0188:             * loader regardless of whether the parent class loader is being searched
0189:             * first or not.
0190:             */
0191:            private Vector systemPackages = new Vector();
0192:
0193:            /**
0194:             * These are the package roots that are to be loaded by this class loader
0195:             * regardless of whether the parent class loader is being searched first
0196:             * or not.
0197:             */
0198:            private Vector loaderPackages = new Vector();
0199:
0200:            /**
0201:             * Whether or not this classloader will ignore the base
0202:             * classloader if it can't find a class.
0203:             *
0204:             * @see #setIsolated(boolean)
0205:             */
0206:            private boolean ignoreBase = false;
0207:
0208:            /**
0209:             * The parent class loader, if one is given or can be determined.
0210:             */
0211:            private ClassLoader parent = null;
0212:
0213:            /**
0214:             * A hashtable of zip files opened by the classloader (File to ZipFile).
0215:             */
0216:            private Hashtable zipFiles = new Hashtable();
0217:
0218:            /** Static map of jar file/time to manifiest class-path entries */
0219:            private static Map/*<String,String>*/pathMap = Collections
0220:                    .synchronizedMap(new HashMap());
0221:
0222:            /**
0223:             * The context loader saved when setting the thread's current
0224:             * context loader.
0225:             */
0226:            private ClassLoader savedContextLoader = null;
0227:            /**
0228:             * Whether or not the context loader is currently saved.
0229:             */
0230:            private boolean isContextLoaderSaved = false;
0231:
0232:            /**
0233:             * Create an Ant ClassLoader for a given project, with
0234:             * a parent classloader and an initial classpath.
0235:             * @since Ant 1.7.
0236:             * @param parent the parent for this classloader.
0237:             * @param project The project to which this classloader is to
0238:             *                belong.
0239:             * @param classpath The classpath to use to load classes.
0240:             */
0241:            public AntClassLoader(ClassLoader parent, Project project,
0242:                    Path classpath) {
0243:                setParent(parent);
0244:                setClassPath(classpath);
0245:                setProject(project);
0246:            }
0247:
0248:            /**
0249:             * Create an Ant Class Loader
0250:             */
0251:            public AntClassLoader() {
0252:                setParent(null);
0253:            }
0254:
0255:            /**
0256:             * Creates a classloader for the given project using the classpath given.
0257:             *
0258:             * @param project The project to which this classloader is to belong.
0259:             *                Must not be <code>null</code>.
0260:             * @param classpath The classpath to use to load the classes.  This
0261:             *                is combined with the system classpath in a manner
0262:             *                determined by the value of ${build.sysclasspath}.
0263:             *                May be <code>null</code>, in which case no path
0264:             *                elements are set up to start with.
0265:             */
0266:            public AntClassLoader(Project project, Path classpath) {
0267:                setParent(null);
0268:                setProject(project);
0269:                setClassPath(classpath);
0270:            }
0271:
0272:            /**
0273:             * Creates a classloader for the given project using the classpath given.
0274:             *
0275:             * @param parent The parent classloader to which unsatisfied loading
0276:             *               attempts are delegated. May be <code>null</code>,
0277:             *               in which case the classloader which loaded this
0278:             *               class is used as the parent.
0279:             * @param project The project to which this classloader is to belong.
0280:             *                Must not be <code>null</code>.
0281:             * @param classpath the classpath to use to load the classes.
0282:             *                  May be <code>null</code>, in which case no path
0283:             *                  elements are set up to start with.
0284:             * @param parentFirst If <code>true</code>, indicates that the parent
0285:             *                    classloader should be consulted  before trying to
0286:             *                    load the a class through this loader.
0287:             */
0288:            public AntClassLoader(ClassLoader parent, Project project,
0289:                    Path classpath, boolean parentFirst) {
0290:                this (project, classpath);
0291:                if (parent != null) {
0292:                    setParent(parent);
0293:                }
0294:                setParentFirst(parentFirst);
0295:                addJavaLibraries();
0296:            }
0297:
0298:            /**
0299:             * Creates a classloader for the given project using the classpath given.
0300:             *
0301:             * @param project The project to which this classloader is to belong.
0302:             *                Must not be <code>null</code>.
0303:             * @param classpath The classpath to use to load the classes. May be
0304:             *                  <code>null</code>, in which case no path
0305:             *                  elements are set up to start with.
0306:             * @param parentFirst If <code>true</code>, indicates that the parent
0307:             *                    classloader should be consulted before trying to
0308:             *                    load the a class through this loader.
0309:             */
0310:            public AntClassLoader(Project project, Path classpath,
0311:                    boolean parentFirst) {
0312:                this (null, project, classpath, parentFirst);
0313:            }
0314:
0315:            /**
0316:             * Creates an empty class loader. The classloader should be configured
0317:             * with path elements to specify where the loader is to look for
0318:             * classes.
0319:             *
0320:             * @param parent The parent classloader to which unsatisfied loading
0321:             *               attempts are delegated. May be <code>null</code>,
0322:             *               in which case the classloader which loaded this
0323:             *               class is used as the parent.
0324:             * @param parentFirst If <code>true</code>, indicates that the parent
0325:             *                    classloader should be consulted before trying to
0326:             *                    load the a class through this loader.
0327:             */
0328:            public AntClassLoader(ClassLoader parent, boolean parentFirst) {
0329:                setParent(parent);
0330:                project = null;
0331:                this .parentFirst = parentFirst;
0332:            }
0333:
0334:            /**
0335:             * Set the project associated with this class loader
0336:             *
0337:             * @param project the project instance
0338:             */
0339:            public void setProject(Project project) {
0340:                this .project = project;
0341:                if (project != null) {
0342:                    project.addBuildListener(this );
0343:                }
0344:            }
0345:
0346:            /**
0347:             * Set the classpath to search for classes to load. This should not be
0348:             * changed once the classloader starts to server classes
0349:             *
0350:             * @param classpath the search classpath consisting of directories and
0351:             *        jar/zip files.
0352:             */
0353:            public void setClassPath(Path classpath) {
0354:                pathComponents.removeAllElements();
0355:                if (classpath != null) {
0356:                    Path actualClasspath = classpath
0357:                            .concatSystemClasspath("ignore");
0358:                    String[] pathElements = actualClasspath.list();
0359:                    for (int i = 0; i < pathElements.length; ++i) {
0360:                        try {
0361:                            addPathElement(pathElements[i]);
0362:                        } catch (BuildException e) {
0363:                            // ignore path elements which are invalid
0364:                            // relative to the project
0365:                        }
0366:                    }
0367:                }
0368:            }
0369:
0370:            /**
0371:             * Set the parent for this class loader. This is the class loader to which
0372:             * this class loader will delegate to load classes
0373:             *
0374:             * @param parent the parent class loader.
0375:             */
0376:            public void setParent(ClassLoader parent) {
0377:                if (parent == null) {
0378:                    this .parent = AntClassLoader.class.getClassLoader();
0379:                } else {
0380:                    this .parent = parent;
0381:                }
0382:            }
0383:
0384:            /**
0385:             * Control whether class lookup is delegated to the parent loader first
0386:             * or after this loader. Use with extreme caution. Setting this to
0387:             * false violates the class loader hierarchy and can lead to Linkage errors
0388:             *
0389:             * @param parentFirst if true, delegate initial class search to the parent
0390:             *                    classloader.
0391:             */
0392:            public void setParentFirst(boolean parentFirst) {
0393:                this .parentFirst = parentFirst;
0394:            }
0395:
0396:            /**
0397:             * Logs a message through the project object if one has been provided.
0398:             *
0399:             * @param message The message to log.
0400:             *                Should not be <code>null</code>.
0401:             *
0402:             * @param priority The logging priority of the message.
0403:             */
0404:            protected void log(String message, int priority) {
0405:                if (project != null) {
0406:                    project.log(message, priority);
0407:                }
0408:                //         else {
0409:                //             System.out.println(message);
0410:                //         }
0411:            }
0412:
0413:            /**
0414:             * Sets the current thread's context loader to this classloader, storing
0415:             * the current loader value for later resetting.
0416:             */
0417:            public void setThreadContextLoader() {
0418:                if (isContextLoaderSaved) {
0419:                    throw new BuildException(
0420:                            "Context loader has not been reset");
0421:                }
0422:                if (LoaderUtils.isContextLoaderAvailable()) {
0423:                    savedContextLoader = LoaderUtils.getContextClassLoader();
0424:                    ClassLoader loader = this ;
0425:                    if (project != null
0426:                            && "only".equals(project
0427:                                    .getProperty("build.sysclasspath"))) {
0428:                        loader = this .getClass().getClassLoader();
0429:                    }
0430:                    LoaderUtils.setContextClassLoader(loader);
0431:                    isContextLoaderSaved = true;
0432:                }
0433:            }
0434:
0435:            /**
0436:             * Resets the current thread's context loader to its original value.
0437:             */
0438:            public void resetThreadContextLoader() {
0439:                if (LoaderUtils.isContextLoaderAvailable()
0440:                        && isContextLoaderSaved) {
0441:                    LoaderUtils.setContextClassLoader(savedContextLoader);
0442:                    savedContextLoader = null;
0443:                    isContextLoaderSaved = false;
0444:                }
0445:            }
0446:
0447:            /**
0448:             * Adds an element to the classpath to be searched.
0449:             *
0450:             * @param pathElement The path element to add. Must not be
0451:             *                    <code>null</code>.
0452:             *
0453:             * @exception BuildException if the given path element cannot be resolved
0454:             *                           against the project.
0455:             */
0456:            public void addPathElement(String pathElement)
0457:                    throws BuildException {
0458:                File pathComponent = project != null ? project
0459:                        .resolveFile(pathElement) : new File(pathElement);
0460:                try {
0461:                    addPathFile(pathComponent);
0462:                } catch (IOException e) {
0463:                    throw new BuildException(e);
0464:                }
0465:            }
0466:
0467:            /**
0468:             * Add a file to the path.
0469:             * Reads the manifest, if available, and adds any additional class path jars
0470:             * specified in the manifest.
0471:             *
0472:             * @param pathComponent the file which is to be added to the path for
0473:             *                      this class loader
0474:             *
0475:             * @throws IOException if data needed from the file cannot be read.
0476:             */
0477:            protected void addPathFile(File pathComponent) throws IOException {
0478:                pathComponents.addElement(pathComponent);
0479:                if (pathComponent.isDirectory()) {
0480:                    return;
0481:                }
0482:
0483:                String absPathPlusTimeAndLength = pathComponent
0484:                        .getAbsolutePath()
0485:                        + pathComponent.lastModified()
0486:                        + "-"
0487:                        + pathComponent.length();
0488:                String classpath = (String) pathMap
0489:                        .get(absPathPlusTimeAndLength);
0490:                if (classpath == null) {
0491:                    ZipFile jarFile = null;
0492:                    InputStream manifestStream = null;
0493:                    try {
0494:                        jarFile = new ZipFile(pathComponent);
0495:                        manifestStream = jarFile.getInputStream(new ZipEntry(
0496:                                "META-INF/MANIFEST.MF"));
0497:
0498:                        if (manifestStream == null) {
0499:                            return;
0500:                        }
0501:                        Reader manifestReader = new InputStreamReader(
0502:                                manifestStream, "UTF-8");
0503:                        org.apache.tools.ant.taskdefs.Manifest manifest = new org.apache.tools.ant.taskdefs.Manifest(
0504:                                manifestReader);
0505:                        classpath = manifest.getMainSection()
0506:                                .getAttributeValue("Class-Path");
0507:
0508:                    } catch (org.apache.tools.ant.taskdefs.ManifestException e) {
0509:                        // ignore
0510:                    } finally {
0511:                        if (manifestStream != null) {
0512:                            manifestStream.close();
0513:                        }
0514:                        if (jarFile != null) {
0515:                            jarFile.close();
0516:                        }
0517:                    }
0518:                    if (classpath == null) {
0519:                        classpath = "";
0520:                    }
0521:                    pathMap.put(absPathPlusTimeAndLength, classpath);
0522:                }
0523:
0524:                if (!"".equals(classpath)) {
0525:                    URL baseURL = FILE_UTILS.getFileURL(pathComponent);
0526:                    StringTokenizer st = new StringTokenizer(classpath);
0527:                    while (st.hasMoreTokens()) {
0528:                        String classpathElement = st.nextToken();
0529:                        URL libraryURL = new URL(baseURL, classpathElement);
0530:                        if (!libraryURL.getProtocol().equals("file")) {
0531:                            log(
0532:                                    "Skipping jar library "
0533:                                            + classpathElement
0534:                                            + " since only relative URLs are supported by this"
0535:                                            + " loader", Project.MSG_VERBOSE);
0536:                            continue;
0537:                        }
0538:                        String decodedPath = Locator.decodeUri(libraryURL
0539:                                .getFile());
0540:                        File libraryFile = new File(decodedPath);
0541:                        if (libraryFile.exists() && !isInPath(libraryFile)) {
0542:                            addPathFile(libraryFile);
0543:                        }
0544:                    }
0545:                }
0546:            }
0547:
0548:            /**
0549:             * Returns the classpath this classloader will consult.
0550:             *
0551:             * @return the classpath used for this classloader, with elements
0552:             *         separated by the path separator for the system.
0553:             */
0554:            public String getClasspath() {
0555:                StringBuffer sb = new StringBuffer();
0556:                boolean firstPass = true;
0557:                Enumeration componentEnum = pathComponents.elements();
0558:                while (componentEnum.hasMoreElements()) {
0559:                    if (!firstPass) {
0560:                        sb.append(System.getProperty("path.separator"));
0561:                    } else {
0562:                        firstPass = false;
0563:                    }
0564:                    sb.append(((File) componentEnum.nextElement())
0565:                            .getAbsolutePath());
0566:                }
0567:                return sb.toString();
0568:            }
0569:
0570:            /**
0571:             * Sets whether this classloader should run in isolated mode. In
0572:             * isolated mode, classes not found on the given classpath will
0573:             * not be referred to the parent class loader but will cause a
0574:             * ClassNotFoundException.
0575:             *
0576:             * @param isolated Whether or not this classloader should run in
0577:             *                 isolated mode.
0578:             */
0579:            public synchronized void setIsolated(boolean isolated) {
0580:                ignoreBase = isolated;
0581:            }
0582:
0583:            /**
0584:             * Forces initialization of a class in a JDK 1.1 compatible, albeit hacky
0585:             * way.
0586:             *
0587:             * @param theClass The class to initialize.
0588:             *                 Must not be <code>null</code>.
0589:             *
0590:             * @deprecated since 1.6.x.
0591:             *             Use Class.forName with initialize=true instead.
0592:             */
0593:            public static void initializeClass(Class theClass) {
0594:                // ***HACK*** We ask the VM to create an instance
0595:                // by voluntarily providing illegal arguments to force
0596:                // the VM to run the class' static initializer, while
0597:                // at the same time not running a valid constructor.
0598:
0599:                final Constructor[] cons = theClass.getDeclaredConstructors();
0600:                //At least one constructor is guaranteed to be there, but check anyway.
0601:                if (cons != null) {
0602:                    if (cons.length > 0 && cons[0] != null) {
0603:                        final String[] strs = new String[NUMBER_OF_STRINGS];
0604:                        try {
0605:                            cons[0].newInstance((Object[]) strs);
0606:                            // Expecting an exception to be thrown by this call:
0607:                            // IllegalArgumentException: wrong number of Arguments
0608:                        } catch (Exception e) {
0609:                            // Ignore - we are interested only in the side
0610:                            // effect - that of getting the static initializers
0611:                            // invoked.  As we do not want to call a valid
0612:                            // constructor to get this side effect, an
0613:                            // attempt is made to call a hopefully
0614:                            // invalid constructor - come on, nobody
0615:                            // would have a constructor that takes in
0616:                            // 256 String arguments ;-)
0617:                            // (In fact, they can't - according to JVM spec
0618:                            // section 4.10, the number of method parameters is limited
0619:                            // to 255 by the definition of a method descriptor.
0620:                            // Constructors count as methods here.)
0621:                        }
0622:                    }
0623:                }
0624:            }
0625:
0626:            /**
0627:             * Adds a package root to the list of packages which must be loaded on the
0628:             * parent loader.
0629:             *
0630:             * All subpackages are also included.
0631:             *
0632:             * @param packageRoot The root of all packages to be included.
0633:             *                    Should not be <code>null</code>.
0634:             */
0635:            public void addSystemPackageRoot(String packageRoot) {
0636:                systemPackages.addElement(packageRoot
0637:                        + (packageRoot.endsWith(".") ? "" : "."));
0638:            }
0639:
0640:            /**
0641:             * Adds a package root to the list of packages which must be loaded using
0642:             * this loader.
0643:             *
0644:             * All subpackages are also included.
0645:             *
0646:             * @param packageRoot The root of all packages to be included.
0647:             *                    Should not be <code>null</code>.
0648:             */
0649:            public void addLoaderPackageRoot(String packageRoot) {
0650:                loaderPackages.addElement(packageRoot
0651:                        + (packageRoot.endsWith(".") ? "" : "."));
0652:            }
0653:
0654:            /**
0655:             * Loads a class through this class loader even if that class is available
0656:             * on the parent classpath.
0657:             *
0658:             * This ensures that any classes which are loaded by the returned class
0659:             * will use this classloader.
0660:             *
0661:             * @param classname The name of the class to be loaded.
0662:             *                  Must not be <code>null</code>.
0663:             *
0664:             * @return the required Class object
0665:             *
0666:             * @exception ClassNotFoundException if the requested class does not exist
0667:             *                                   on this loader's classpath.
0668:             */
0669:            public Class forceLoadClass(String classname)
0670:                    throws ClassNotFoundException {
0671:                log("force loading " + classname, Project.MSG_DEBUG);
0672:
0673:                Class theClass = findLoadedClass(classname);
0674:
0675:                if (theClass == null) {
0676:                    theClass = findClass(classname);
0677:                }
0678:
0679:                return theClass;
0680:            }
0681:
0682:            /**
0683:             * Loads a class through this class loader but defer to the parent class
0684:             * loader.
0685:             *
0686:             * This ensures that instances of the returned class will be compatible
0687:             * with instances which have already been loaded on the parent
0688:             * loader.
0689:             *
0690:             * @param classname The name of the class to be loaded.
0691:             *                  Must not be <code>null</code>.
0692:             *
0693:             * @return the required Class object
0694:             *
0695:             * @exception ClassNotFoundException if the requested class does not exist
0696:             * on this loader's classpath.
0697:             */
0698:            public Class forceLoadSystemClass(String classname)
0699:                    throws ClassNotFoundException {
0700:                log("force system loading " + classname, Project.MSG_DEBUG);
0701:
0702:                Class theClass = findLoadedClass(classname);
0703:
0704:                if (theClass == null) {
0705:                    theClass = findBaseClass(classname);
0706:                }
0707:
0708:                return theClass;
0709:            }
0710:
0711:            /**
0712:             * Returns a stream to read the requested resource name.
0713:             *
0714:             * @param name The name of the resource for which a stream is required.
0715:             *             Must not be <code>null</code>.
0716:             *
0717:             * @return a stream to the required resource or <code>null</code> if the
0718:             *         resource cannot be found on the loader's classpath.
0719:             */
0720:            public InputStream getResourceAsStream(String name) {
0721:
0722:                InputStream resourceStream = null;
0723:                if (isParentFirst(name)) {
0724:                    resourceStream = loadBaseResource(name);
0725:                    if (resourceStream != null) {
0726:                        log("ResourceStream for " + name
0727:                                + " loaded from parent loader",
0728:                                Project.MSG_DEBUG);
0729:
0730:                    } else {
0731:                        resourceStream = loadResource(name);
0732:                        if (resourceStream != null) {
0733:                            log("ResourceStream for " + name
0734:                                    + " loaded from ant loader",
0735:                                    Project.MSG_DEBUG);
0736:                        }
0737:                    }
0738:                } else {
0739:                    resourceStream = loadResource(name);
0740:                    if (resourceStream != null) {
0741:                        log("ResourceStream for " + name
0742:                                + " loaded from ant loader", Project.MSG_DEBUG);
0743:
0744:                    } else {
0745:                        resourceStream = loadBaseResource(name);
0746:                        if (resourceStream != null) {
0747:                            log("ResourceStream for " + name
0748:                                    + " loaded from parent loader",
0749:                                    Project.MSG_DEBUG);
0750:                        }
0751:                    }
0752:                }
0753:
0754:                if (resourceStream == null) {
0755:                    log("Couldn't load ResourceStream for " + name,
0756:                            Project.MSG_DEBUG);
0757:                }
0758:
0759:                return resourceStream;
0760:            }
0761:
0762:            /**
0763:             * Returns a stream to read the requested resource name from this loader.
0764:             *
0765:             * @param name The name of the resource for which a stream is required.
0766:             *             Must not be <code>null</code>.
0767:             *
0768:             * @return a stream to the required resource or <code>null</code> if
0769:             *         the resource cannot be found on the loader's classpath.
0770:             */
0771:            private InputStream loadResource(String name) {
0772:                // we need to search the components of the path to see if we can
0773:                // find the class we want.
0774:                InputStream stream = null;
0775:
0776:                Enumeration e = pathComponents.elements();
0777:                while (e.hasMoreElements() && stream == null) {
0778:                    File pathComponent = (File) e.nextElement();
0779:                    stream = getResourceStream(pathComponent, name);
0780:                }
0781:                return stream;
0782:            }
0783:
0784:            /**
0785:             * Finds a system resource (which should be loaded from the parent
0786:             * classloader).
0787:             *
0788:             * @param name The name of the system resource to load.
0789:             *             Must not be <code>null</code>.
0790:             *
0791:             * @return a stream to the named resource, or <code>null</code> if
0792:             *         the resource cannot be found.
0793:             */
0794:            private InputStream loadBaseResource(String name) {
0795:                if (parent == null) {
0796:                    return getSystemResourceAsStream(name);
0797:                } else {
0798:                    return parent.getResourceAsStream(name);
0799:                }
0800:            }
0801:
0802:            /**
0803:             * Returns an inputstream to a given resource in the given file which may
0804:             * either be a directory or a zip file.
0805:             *
0806:             * @param file the file (directory or jar) in which to search for the
0807:             *             resource. Must not be <code>null</code>.
0808:             * @param resourceName The name of the resource for which a stream is
0809:             *                     required. Must not be <code>null</code>.
0810:             *
0811:             * @return a stream to the required resource or <code>null</code> if
0812:             *         the resource cannot be found in the given file.
0813:             */
0814:            private InputStream getResourceStream(File file, String resourceName) {
0815:                try {
0816:                    if (!file.exists()) {
0817:                        return null;
0818:                    }
0819:
0820:                    if (file.isDirectory()) {
0821:                        File resource = new File(file, resourceName);
0822:
0823:                        if (resource.exists()) {
0824:                            return new FileInputStream(resource);
0825:                        }
0826:                    } else {
0827:                        // is the zip file in the cache
0828:                        ZipFile zipFile = (ZipFile) zipFiles.get(file);
0829:                        if (zipFile == null) {
0830:                            zipFile = new ZipFile(file);
0831:                            zipFiles.put(file, zipFile);
0832:                        }
0833:                        ZipEntry entry = zipFile.getEntry(resourceName);
0834:                        if (entry != null) {
0835:                            return zipFile.getInputStream(entry);
0836:                        }
0837:                    }
0838:                } catch (Exception e) {
0839:                    log("Ignoring Exception " + e.getClass().getName() + ": "
0840:                            + e.getMessage() + " reading resource "
0841:                            + resourceName + " from " + file,
0842:                            Project.MSG_VERBOSE);
0843:                }
0844:
0845:                return null;
0846:            }
0847:
0848:            /**
0849:             * Tests whether or not the parent classloader should be checked for
0850:             * a resource before this one. If the resource matches both the
0851:             * "use parent classloader first" and the "use this classloader first"
0852:             * lists, the latter takes priority.
0853:             *
0854:             * @param resourceName The name of the resource to check.
0855:             *                     Must not be <code>null</code>.
0856:             *
0857:             * @return whether or not the parent classloader should be checked for a
0858:             *         resource before this one is.
0859:             */
0860:            private boolean isParentFirst(String resourceName) {
0861:                // default to the global setting and then see
0862:                // if this class belongs to a package which has been
0863:                // designated to use a specific loader first
0864:                // (this one or the parent one)
0865:
0866:                // XXX - shouldn't this always return false in isolated mode?
0867:
0868:                boolean useParentFirst = parentFirst;
0869:
0870:                for (Enumeration e = systemPackages.elements(); e
0871:                        .hasMoreElements();) {
0872:                    String packageName = (String) e.nextElement();
0873:                    if (resourceName.startsWith(packageName)) {
0874:                        useParentFirst = true;
0875:                        break;
0876:                    }
0877:                }
0878:
0879:                for (Enumeration e = loaderPackages.elements(); e
0880:                        .hasMoreElements();) {
0881:                    String packageName = (String) e.nextElement();
0882:                    if (resourceName.startsWith(packageName)) {
0883:                        useParentFirst = false;
0884:                        break;
0885:                    }
0886:                }
0887:
0888:                return useParentFirst;
0889:            }
0890:
0891:            /**
0892:             * Used for isolated resource seaching.
0893:             * @return the root classloader of AntClassLoader.
0894:             */
0895:            private ClassLoader getRootLoader() {
0896:                ClassLoader ret = getClass().getClassLoader();
0897:                while (ret != null && ret.getParent() != null) {
0898:                    ret = ret.getParent();
0899:                }
0900:                return ret;
0901:            }
0902:
0903:            /**
0904:             * Finds the resource with the given name. A resource is
0905:             * some data (images, audio, text, etc) that can be accessed by class
0906:             * code in a way that is independent of the location of the code.
0907:             *
0908:             * @param name The name of the resource for which a stream is required.
0909:             *             Must not be <code>null</code>.
0910:             *
0911:             * @return a URL for reading the resource, or <code>null</code> if the
0912:             *         resource could not be found or the caller doesn't have
0913:             *         adequate privileges to get the resource.
0914:             */
0915:            public URL getResource(String name) {
0916:                // we need to search the components of the path to see if
0917:                // we can find the class we want.
0918:                URL url = null;
0919:                if (isParentFirst(name)) {
0920:                    url = (parent == null) ? super .getResource(name) : parent
0921:                            .getResource(name);
0922:                }
0923:
0924:                if (url != null) {
0925:                    log("Resource " + name + " loaded from parent loader",
0926:                            Project.MSG_DEBUG);
0927:
0928:                } else {
0929:                    // try and load from this loader if the parent either didn't find
0930:                    // it or wasn't consulted.
0931:                    Enumeration e = pathComponents.elements();
0932:                    while (e.hasMoreElements() && url == null) {
0933:                        File pathComponent = (File) e.nextElement();
0934:                        url = getResourceURL(pathComponent, name);
0935:                        if (url != null) {
0936:                            log("Resource " + name + " loaded from ant loader",
0937:                                    Project.MSG_DEBUG);
0938:                        }
0939:                    }
0940:                }
0941:
0942:                if (url == null && !isParentFirst(name)) {
0943:                    // this loader was first but it didn't find it - try the parent
0944:                    if (ignoreBase) {
0945:                        url = (getRootLoader() == null) ? null
0946:                                : getRootLoader().getResource(name);
0947:                    } else {
0948:                        url = (parent == null) ? super .getResource(name)
0949:                                : parent.getResource(name);
0950:                    }
0951:                    if (url != null) {
0952:                        log("Resource " + name + " loaded from parent loader",
0953:                                Project.MSG_DEBUG);
0954:                    }
0955:                }
0956:
0957:                if (url == null) {
0958:                    log("Couldn't load Resource " + name, Project.MSG_DEBUG);
0959:                }
0960:
0961:                return url;
0962:            }
0963:
0964:            /**
0965:             * Returns an enumeration of URLs representing all the resources with the
0966:             * given name by searching the class loader's classpath.
0967:             *
0968:             * @param name The resource name to search for.
0969:             *             Must not be <code>null</code>.
0970:             * @return an enumeration of URLs for the resources
0971:             * @exception IOException if I/O errors occurs (can't happen)
0972:             */
0973:            protected Enumeration/*<URL>*/findResources(String name)
0974:                    throws IOException {
0975:                Enumeration/*<URL>*/mine = new ResourceEnumeration(name);
0976:                Enumeration/*<URL>*/base;
0977:                if (parent != null && parent != getParent()) {
0978:                    // Delegate to the parent:
0979:                    base = parent.getResources(name);
0980:                    // Note: could cause overlaps in case ClassLoader.this.parent has matches.
0981:                } else {
0982:                    // ClassLoader.this.parent is already delegated to from
0983:                    // ClassLoader.getResources, no need:
0984:                    base = new CollectionUtils.EmptyEnumeration();
0985:                }
0986:                if (isParentFirst(name)) {
0987:                    // Normal case.
0988:                    return CollectionUtils.append(base, mine);
0989:                } else if (ignoreBase) {
0990:                    return getRootLoader() == null ? mine : CollectionUtils
0991:                            .append(mine, getRootLoader().getResources(name));
0992:                } else {
0993:                    // Inverted.
0994:                    return CollectionUtils.append(mine, base);
0995:                }
0996:            }
0997:
0998:            /**
0999:             * Returns the URL of a given resource in the given file which may
1000:             * either be a directory or a zip file.
1001:             *
1002:             * @param file The file (directory or jar) in which to search for
1003:             *             the resource. Must not be <code>null</code>.
1004:             * @param resourceName The name of the resource for which a stream
1005:             *                     is required. Must not be <code>null</code>.
1006:             *
1007:             * @return a stream to the required resource or <code>null</code> if the
1008:             *         resource cannot be found in the given file object.
1009:             */
1010:            protected URL getResourceURL(File file, String resourceName) {
1011:                try {
1012:                    if (!file.exists()) {
1013:                        return null;
1014:                    }
1015:
1016:                    if (file.isDirectory()) {
1017:                        File resource = new File(file, resourceName);
1018:
1019:                        if (resource.exists()) {
1020:                            try {
1021:                                return FILE_UTILS.getFileURL(resource);
1022:                            } catch (MalformedURLException ex) {
1023:                                return null;
1024:                            }
1025:                        }
1026:                    } else {
1027:                        ZipFile zipFile = (ZipFile) zipFiles.get(file);
1028:                        if (zipFile == null) {
1029:                            zipFile = new ZipFile(file);
1030:                            zipFiles.put(file, zipFile);
1031:                        }
1032:
1033:                        ZipEntry entry = zipFile.getEntry(resourceName);
1034:                        if (entry != null) {
1035:                            try {
1036:                                return new URL("jar:"
1037:                                        + FILE_UTILS.getFileURL(file) + "!/"
1038:                                        + entry);
1039:                            } catch (MalformedURLException ex) {
1040:                                return null;
1041:                            }
1042:                        }
1043:                    }
1044:                } catch (Exception e) {
1045:                    e.printStackTrace();
1046:                }
1047:
1048:                return null;
1049:            }
1050:
1051:            /**
1052:             * Loads a class with this class loader.
1053:             *
1054:             * This class attempts to load the class in an order determined by whether
1055:             * or not the class matches the system/loader package lists, with the
1056:             * loader package list taking priority. If the classloader is in isolated
1057:             * mode, failure to load the class in this loader will result in a
1058:             * ClassNotFoundException.
1059:             *
1060:             * @param classname The name of the class to be loaded.
1061:             *                  Must not be <code>null</code>.
1062:             * @param resolve <code>true</code> if all classes upon which this class
1063:             *                depends are to be loaded.
1064:             *
1065:             * @return the required Class object
1066:             *
1067:             * @exception ClassNotFoundException if the requested class does not exist
1068:             * on the system classpath (when not in isolated mode) or this loader's
1069:             * classpath.
1070:             */
1071:            protected synchronized Class loadClass(String classname,
1072:                    boolean resolve) throws ClassNotFoundException {
1073:                // 'sync' is needed - otherwise 2 threads can load the same class
1074:                // twice, resulting in LinkageError: duplicated class definition.
1075:                // findLoadedClass avoids that, but without sync it won't work.
1076:
1077:                Class theClass = findLoadedClass(classname);
1078:                if (theClass != null) {
1079:                    return theClass;
1080:                }
1081:
1082:                if (isParentFirst(classname)) {
1083:                    try {
1084:                        theClass = findBaseClass(classname);
1085:                        log("Class " + classname
1086:                                + " loaded from parent loader "
1087:                                + "(parentFirst)", Project.MSG_DEBUG);
1088:                    } catch (ClassNotFoundException cnfe) {
1089:                        theClass = findClass(classname);
1090:                        log("Class " + classname + " loaded from ant loader "
1091:                                + "(parentFirst)", Project.MSG_DEBUG);
1092:                    }
1093:                } else {
1094:                    try {
1095:                        theClass = findClass(classname);
1096:                        log("Class " + classname + " loaded from ant loader",
1097:                                Project.MSG_DEBUG);
1098:                    } catch (ClassNotFoundException cnfe) {
1099:                        if (ignoreBase) {
1100:                            throw cnfe;
1101:                        }
1102:                        theClass = findBaseClass(classname);
1103:                        log(
1104:                                "Class " + classname
1105:                                        + " loaded from parent loader",
1106:                                Project.MSG_DEBUG);
1107:                    }
1108:                }
1109:
1110:                if (resolve) {
1111:                    resolveClass(theClass);
1112:                }
1113:
1114:                return theClass;
1115:            }
1116:
1117:            /**
1118:             * Converts the class dot notation to a filesystem equivalent for
1119:             * searching purposes.
1120:             *
1121:             * @param classname The class name in dot format (eg java.lang.Integer).
1122:             *                  Must not be <code>null</code>.
1123:             *
1124:             * @return the classname in filesystem format (eg java/lang/Integer.class)
1125:             */
1126:            private String getClassFilename(String classname) {
1127:                return classname.replace('.', '/') + ".class";
1128:            }
1129:
1130:            /**
1131:             * Define a class given its bytes
1132:             *
1133:             * @param container the container from which the class data has been read
1134:             *                  may be a directory or a jar/zip file.
1135:             *
1136:             * @param classData the bytecode data for the class
1137:             * @param classname the name of the class
1138:             *
1139:             * @return the Class instance created from the given data
1140:             *
1141:             * @throws IOException if the class data cannot be read.
1142:             */
1143:            protected Class defineClassFromData(File container,
1144:                    byte[] classData, String classname) throws IOException {
1145:                definePackage(container, classname);
1146:                // XXX should instead make a new ProtectionDomain with a CodeSource
1147:                // corresponding to container.toURI().toURL() and the same
1148:                // PermissionCollection as Project.class.protectionDomain had
1149:                return defineClass(classname, classData, 0, classData.length,
1150:                        Project.class.getProtectionDomain());
1151:            }
1152:
1153:            /**
1154:             * Define the package information associated with a class.
1155:             *
1156:             * @param container the file containing the class definition.
1157:             * @param className the class name of for which the package information
1158:             *        is to be determined.
1159:             *
1160:             * @exception IOException if the package information cannot be read from the
1161:             *            container.
1162:             */
1163:            protected void definePackage(File container, String className)
1164:                    throws IOException {
1165:                int classIndex = className.lastIndexOf('.');
1166:                if (classIndex == -1) {
1167:                    return;
1168:                }
1169:
1170:                String packageName = className.substring(0, classIndex);
1171:                if (getPackage(packageName) != null) {
1172:                    // already defined
1173:                    return;
1174:                }
1175:
1176:                // define the package now
1177:                Manifest manifest = getJarManifest(container);
1178:
1179:                if (manifest == null) {
1180:                    definePackage(packageName, null, null, null, null, null,
1181:                            null, null);
1182:                } else {
1183:                    definePackage(container, packageName, manifest);
1184:                }
1185:            }
1186:
1187:            /**
1188:             * Get the manifest from the given jar, if it is indeed a jar and it has a
1189:             * manifest
1190:             *
1191:             * @param container the File from which a manifest is required.
1192:             *
1193:             * @return the jar's manifest or null is the container is not a jar or it
1194:             *         has no manifest.
1195:             *
1196:             * @exception IOException if the manifest cannot be read.
1197:             */
1198:            private Manifest getJarManifest(File container) throws IOException {
1199:                if (container.isDirectory()) {
1200:                    return null;
1201:                }
1202:                JarFile jarFile = null;
1203:                try {
1204:                    jarFile = new JarFile(container);
1205:                    return jarFile.getManifest();
1206:                } finally {
1207:                    if (jarFile != null) {
1208:                        jarFile.close();
1209:                    }
1210:                }
1211:            }
1212:
1213:            /**
1214:             * Define the package information when the class comes from a
1215:             * jar with a manifest
1216:             *
1217:             * @param container the jar file containing the manifest
1218:             * @param packageName the name of the package being defined.
1219:             * @param manifest the jar's manifest
1220:             */
1221:            protected void definePackage(File container, String packageName,
1222:                    Manifest manifest) {
1223:                String sectionName = packageName.replace('.', '/') + "/";
1224:
1225:                String specificationTitle = null;
1226:                String specificationVendor = null;
1227:                String specificationVersion = null;
1228:                String implementationTitle = null;
1229:                String implementationVendor = null;
1230:                String implementationVersion = null;
1231:                String sealedString = null;
1232:                URL sealBase = null;
1233:
1234:                Attributes sectionAttributes = manifest
1235:                        .getAttributes(sectionName);
1236:                if (sectionAttributes != null) {
1237:                    specificationTitle = sectionAttributes
1238:                            .getValue(Name.SPECIFICATION_TITLE);
1239:                    specificationVendor = sectionAttributes
1240:                            .getValue(Name.SPECIFICATION_VENDOR);
1241:                    specificationVersion = sectionAttributes
1242:                            .getValue(Name.SPECIFICATION_VERSION);
1243:                    implementationTitle = sectionAttributes
1244:                            .getValue(Name.IMPLEMENTATION_TITLE);
1245:                    implementationVendor = sectionAttributes
1246:                            .getValue(Name.IMPLEMENTATION_VENDOR);
1247:                    implementationVersion = sectionAttributes
1248:                            .getValue(Name.IMPLEMENTATION_VERSION);
1249:                    sealedString = sectionAttributes.getValue(Name.SEALED);
1250:                }
1251:
1252:                Attributes mainAttributes = manifest.getMainAttributes();
1253:                if (mainAttributes != null) {
1254:                    if (specificationTitle == null) {
1255:                        specificationTitle = mainAttributes
1256:                                .getValue(Name.SPECIFICATION_TITLE);
1257:                    }
1258:                    if (specificationVendor == null) {
1259:                        specificationVendor = mainAttributes
1260:                                .getValue(Name.SPECIFICATION_VENDOR);
1261:                    }
1262:                    if (specificationVersion == null) {
1263:                        specificationVersion = mainAttributes
1264:                                .getValue(Name.SPECIFICATION_VERSION);
1265:                    }
1266:                    if (implementationTitle == null) {
1267:                        implementationTitle = mainAttributes
1268:                                .getValue(Name.IMPLEMENTATION_TITLE);
1269:                    }
1270:                    if (implementationVendor == null) {
1271:                        implementationVendor = mainAttributes
1272:                                .getValue(Name.IMPLEMENTATION_VENDOR);
1273:                    }
1274:                    if (implementationVersion == null) {
1275:                        implementationVersion = mainAttributes
1276:                                .getValue(Name.IMPLEMENTATION_VERSION);
1277:                    }
1278:                    if (sealedString == null) {
1279:                        sealedString = mainAttributes.getValue(Name.SEALED);
1280:                    }
1281:                }
1282:
1283:                if (sealedString != null
1284:                        && sealedString.equalsIgnoreCase("true")) {
1285:                    try {
1286:                        sealBase = new URL(FileUtils.getFileUtils().toURI(
1287:                                container.getAbsolutePath()));
1288:                    } catch (MalformedURLException e) {
1289:                        // ignore
1290:                    }
1291:                }
1292:
1293:                definePackage(packageName, specificationTitle,
1294:                        specificationVersion, specificationVendor,
1295:                        implementationTitle, implementationVersion,
1296:                        implementationVendor, sealBase);
1297:            }
1298:
1299:            /**
1300:             * Reads a class definition from a stream.
1301:             *
1302:             * @param stream The stream from which the class is to be read.
1303:             *               Must not be <code>null</code>.
1304:             * @param classname The name of the class in the stream.
1305:             *                  Must not be <code>null</code>.
1306:             * @param container the file or directory containing the class.
1307:             *
1308:             * @return the Class object read from the stream.
1309:             *
1310:             * @exception IOException if there is a problem reading the class from the
1311:             * stream.
1312:             * @exception SecurityException if there is a security problem while
1313:             * reading the class from the stream.
1314:             */
1315:            private Class getClassFromStream(InputStream stream,
1316:                    String classname, File container) throws IOException,
1317:                    SecurityException {
1318:                ByteArrayOutputStream baos = new ByteArrayOutputStream();
1319:                int bytesRead = -1;
1320:                byte[] buffer = new byte[BUFFER_SIZE];
1321:
1322:                while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) {
1323:                    baos.write(buffer, 0, bytesRead);
1324:                }
1325:
1326:                byte[] classData = baos.toByteArray();
1327:                return defineClassFromData(container, classData, classname);
1328:            }
1329:
1330:            /**
1331:             * Searches for and load a class on the classpath of this class loader.
1332:             *
1333:             * @param name The name of the class to be loaded. Must not be
1334:             *             <code>null</code>.
1335:             *
1336:             * @return the required Class object
1337:             *
1338:             * @exception ClassNotFoundException if the requested class does not exist
1339:             *                                   on this loader's classpath.
1340:             */
1341:            public Class findClass(String name) throws ClassNotFoundException {
1342:                log("Finding class " + name, Project.MSG_DEBUG);
1343:
1344:                return findClassInComponents(name);
1345:            }
1346:
1347:            /**
1348:             * Indicate if the given file is in this loader's path
1349:             *
1350:             * @param component the file which is to be checked
1351:             *
1352:             * @return true if the file is in the class path
1353:             */
1354:            protected boolean isInPath(File component) {
1355:                for (Enumeration e = pathComponents.elements(); e
1356:                        .hasMoreElements();) {
1357:                    File pathComponent = (File) e.nextElement();
1358:                    if (pathComponent.equals(component)) {
1359:                        return true;
1360:                    }
1361:                }
1362:                return false;
1363:            }
1364:
1365:            /**
1366:             * Finds a class on the given classpath.
1367:             *
1368:             * @param name The name of the class to be loaded. Must not be
1369:             *             <code>null</code>.
1370:             *
1371:             * @return the required Class object
1372:             *
1373:             * @exception ClassNotFoundException if the requested class does not exist
1374:             * on this loader's classpath.
1375:             */
1376:            private Class findClassInComponents(String name)
1377:                    throws ClassNotFoundException {
1378:                // we need to search the components of the path to see if
1379:                // we can find the class we want.
1380:                InputStream stream = null;
1381:                String classFilename = getClassFilename(name);
1382:                try {
1383:                    Enumeration e = pathComponents.elements();
1384:                    while (e.hasMoreElements()) {
1385:                        File pathComponent = (File) e.nextElement();
1386:                        try {
1387:                            stream = getResourceStream(pathComponent,
1388:                                    classFilename);
1389:                            if (stream != null) {
1390:                                log("Loaded from " + pathComponent + " "
1391:                                        + classFilename, Project.MSG_DEBUG);
1392:                                return getClassFromStream(stream, name,
1393:                                        pathComponent);
1394:                            }
1395:                        } catch (SecurityException se) {
1396:                            throw se;
1397:                        } catch (IOException ioe) {
1398:                            // ioe.printStackTrace();
1399:                            log("Exception reading component " + pathComponent
1400:                                    + " (reason: " + ioe.getMessage() + ")",
1401:                                    Project.MSG_VERBOSE);
1402:                        }
1403:                    }
1404:
1405:                    throw new ClassNotFoundException(name);
1406:                } finally {
1407:                    try {
1408:                        if (stream != null) {
1409:                            stream.close();
1410:                        }
1411:                    } catch (IOException e) {
1412:                        //ignore
1413:                    }
1414:                }
1415:            }
1416:
1417:            /**
1418:             * Finds a system class (which should be loaded from the same classloader
1419:             * as the Ant core).
1420:             *
1421:             * For JDK 1.1 compatibility, this uses the findSystemClass method if
1422:             * no parent classloader has been specified.
1423:             *
1424:             * @param name The name of the class to be loaded.
1425:             *             Must not be <code>null</code>.
1426:             *
1427:             * @return the required Class object
1428:             *
1429:             * @exception ClassNotFoundException if the requested class does not exist
1430:             * on this loader's classpath.
1431:             */
1432:            private Class findBaseClass(String name)
1433:                    throws ClassNotFoundException {
1434:                if (parent == null) {
1435:                    return findSystemClass(name);
1436:                } else {
1437:                    return parent.loadClass(name);
1438:                }
1439:            }
1440:
1441:            /**
1442:             * Cleans up any resources held by this classloader. Any open archive
1443:             * files are closed.
1444:             */
1445:            public synchronized void cleanup() {
1446:                for (Enumeration e = zipFiles.elements(); e.hasMoreElements();) {
1447:                    ZipFile zipFile = (ZipFile) e.nextElement();
1448:                    try {
1449:                        zipFile.close();
1450:                    } catch (IOException ioe) {
1451:                        // ignore
1452:                    }
1453:                }
1454:                zipFiles = new Hashtable();
1455:                if (project != null) {
1456:                    project.removeBuildListener(this );
1457:                }
1458:                project = null;
1459:            }
1460:
1461:            /**
1462:             * Empty implementation to satisfy the BuildListener interface.
1463:             *
1464:             * @param event the buildStarted event
1465:             */
1466:            public void buildStarted(BuildEvent event) {
1467:                // Not significant for the class loader.
1468:            }
1469:
1470:            /**
1471:             * Cleans up any resources held by this classloader at the end
1472:             * of a build.
1473:             *
1474:             * @param event the buildFinished event
1475:             */
1476:            public void buildFinished(BuildEvent event) {
1477:                cleanup();
1478:            }
1479:
1480:            /**
1481:             * Cleans up any resources held by this classloader at the end of
1482:             * a subbuild if it has been created for the subbuild's project
1483:             * instance.
1484:             *
1485:             * @param event the buildFinished event
1486:             *
1487:             * @since Ant 1.6.2
1488:             */
1489:            public void subBuildFinished(BuildEvent event) {
1490:                if (event.getProject() == project) {
1491:                    cleanup();
1492:                }
1493:            }
1494:
1495:            /**
1496:             * Empty implementation to satisfy the BuildListener interface.
1497:             *
1498:             * @param event the buildStarted event
1499:             *
1500:             * @since Ant 1.6.2
1501:             */
1502:            public void subBuildStarted(BuildEvent event) {
1503:                // Not significant for the class loader.
1504:            }
1505:
1506:            /**
1507:             * Empty implementation to satisfy the BuildListener interface.
1508:             *
1509:             * @param event the targetStarted event
1510:             */
1511:            public void targetStarted(BuildEvent event) {
1512:                // Not significant for the class loader.
1513:            }
1514:
1515:            /**
1516:             * Empty implementation to satisfy the BuildListener interface.
1517:             *
1518:             * @param event the targetFinished event
1519:             */
1520:            public void targetFinished(BuildEvent event) {
1521:                // Not significant for the class loader.
1522:            }
1523:
1524:            /**
1525:             * Empty implementation to satisfy the BuildListener interface.
1526:             *
1527:             * @param event the taskStarted event
1528:             */
1529:            public void taskStarted(BuildEvent event) {
1530:                // Not significant for the class loader.
1531:            }
1532:
1533:            /**
1534:             * Empty implementation to satisfy the BuildListener interface.
1535:             *
1536:             * @param event the taskFinished event
1537:             */
1538:            public void taskFinished(BuildEvent event) {
1539:                // Not significant for the class loader.
1540:            }
1541:
1542:            /**
1543:             * Empty implementation to satisfy the BuildListener interface.
1544:             *
1545:             * @param event the messageLogged event
1546:             */
1547:            public void messageLogged(BuildEvent event) {
1548:                // Not significant for the class loader.
1549:            }
1550:
1551:            /**
1552:             * add any libraries that come with different java versions
1553:             * here
1554:             */
1555:            public void addJavaLibraries() {
1556:                Vector packages = JavaEnvUtils.getJrePackages();
1557:                Enumeration e = packages.elements();
1558:                while (e.hasMoreElements()) {
1559:                    String packageName = (String) e.nextElement();
1560:                    addSystemPackageRoot(packageName);
1561:                }
1562:            }
1563:
1564:            /**
1565:             * Returns a <code>String</code> representing this loader.
1566:             * @return the path that this classloader has.
1567:             */
1568:            public String toString() {
1569:                return "AntClassLoader[" + getClasspath() + "]";
1570:            }
1571:
1572:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.