Source Code Cross Referenced for URLClassLoader.java in  » 6.0-JDK-Core » net » java » net » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
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
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » net » java.net 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.net;
027
028        import java.lang.reflect.Method;
029        import java.lang.reflect.Modifier;
030        import java.io.File;
031        import java.io.FilePermission;
032        import java.io.InputStream;
033        import java.io.IOException;
034        import java.net.URL;
035        import java.net.URLConnection;
036        import java.net.URLStreamHandlerFactory;
037        import java.util.Enumeration;
038        import java.util.NoSuchElementException;
039        import java.util.StringTokenizer;
040        import java.util.jar.Manifest;
041        import java.util.jar.Attributes;
042        import java.util.jar.Attributes.Name;
043        import java.security.CodeSigner;
044        import java.security.PrivilegedAction;
045        import java.security.PrivilegedExceptionAction;
046        import java.security.AccessController;
047        import java.security.AccessControlContext;
048        import java.security.SecureClassLoader;
049        import java.security.CodeSource;
050        import java.security.Permission;
051        import java.security.PermissionCollection;
052        import sun.misc.Resource;
053        import sun.misc.URLClassPath;
054        import sun.net.www.ParseUtil;
055        import sun.security.util.SecurityConstants;
056
057        /**
058         * This class loader is used to load classes and resources from a search
059         * path of URLs referring to both JAR files and directories. Any URL that
060         * ends with a '/' is assumed to refer to a directory. Otherwise, the URL
061         * is assumed to refer to a JAR file which will be opened as needed.
062         * <p>
063         * The AccessControlContext of the thread that created the instance of
064         * URLClassLoader will be used when subsequently loading classes and
065         * resources.
066         * <p>
067         * The classes that are loaded are by default granted permission only to
068         * access the URLs specified when the URLClassLoader was created.
069         *
070         * @author  David Connelly
071         * @version 1.97, 05/05/07
072         * @since   1.2
073         */
074        public class URLClassLoader extends SecureClassLoader {
075            /* The search path for classes and resources */
076            URLClassPath ucp;
077
078            /* The context to be used when loading classes and resources */
079            private AccessControlContext acc;
080
081            /**
082             * Constructs a new URLClassLoader for the given URLs. The URLs will be
083             * searched in the order specified for classes and resources after first
084             * searching in the specified parent class loader. Any URL that ends with
085             * a '/' is assumed to refer to a directory. Otherwise, the URL is assumed
086             * to refer to a JAR file which will be downloaded and opened as needed.
087             *
088             * <p>If there is a security manager, this method first
089             * calls the security manager's <code>checkCreateClassLoader</code> method
090             * to ensure creation of a class loader is allowed.
091             * 
092             * @param urls the URLs from which to load classes and resources
093             * @param parent the parent class loader for delegation
094             * @exception  SecurityException  if a security manager exists and its  
095             *             <code>checkCreateClassLoader</code> method doesn't allow 
096             *             creation of a class loader.
097             * @see SecurityManager#checkCreateClassLoader
098             */
099            public URLClassLoader(URL[] urls, ClassLoader parent) {
100                super (parent);
101                // this is to make the stack depth consistent with 1.1
102                SecurityManager security = System.getSecurityManager();
103                if (security != null) {
104                    security.checkCreateClassLoader();
105                }
106                ucp = new URLClassPath(urls);
107                acc = AccessController.getContext();
108            }
109
110            /**
111             * Constructs a new URLClassLoader for the specified URLs using the
112             * default delegation parent <code>ClassLoader</code>. The URLs will
113             * be searched in the order specified for classes and resources after
114             * first searching in the parent class loader. Any URL that ends with
115             * a '/' is assumed to refer to a directory. Otherwise, the URL is
116             * assumed to refer to a JAR file which will be downloaded and opened
117             * as needed.
118             *
119             * <p>If there is a security manager, this method first
120             * calls the security manager's <code>checkCreateClassLoader</code> method
121             * to ensure creation of a class loader is allowed.
122             * 
123             * @param urls the URLs from which to load classes and resources
124             *
125             * @exception  SecurityException  if a security manager exists and its  
126             *             <code>checkCreateClassLoader</code> method doesn't allow 
127             *             creation of a class loader.
128             * @see SecurityManager#checkCreateClassLoader
129             */
130            public URLClassLoader(URL[] urls) {
131                super ();
132                // this is to make the stack depth consistent with 1.1
133                SecurityManager security = System.getSecurityManager();
134                if (security != null) {
135                    security.checkCreateClassLoader();
136                }
137                ucp = new URLClassPath(urls);
138                acc = AccessController.getContext();
139            }
140
141            /**
142             * Constructs a new URLClassLoader for the specified URLs, parent
143             * class loader, and URLStreamHandlerFactory. The parent argument
144             * will be used as the parent class loader for delegation. The
145             * factory argument will be used as the stream handler factory to
146             * obtain protocol handlers when creating new jar URLs.
147             *
148             * <p>If there is a security manager, this method first
149             * calls the security manager's <code>checkCreateClassLoader</code> method
150             * to ensure creation of a class loader is allowed.
151             *
152             * @param urls the URLs from which to load classes and resources
153             * @param parent the parent class loader for delegation
154             * @param factory the URLStreamHandlerFactory to use when creating URLs
155             *
156             * @exception  SecurityException  if a security manager exists and its  
157             *             <code>checkCreateClassLoader</code> method doesn't allow 
158             *             creation of a class loader.
159             * @see SecurityManager#checkCreateClassLoader
160             */
161            public URLClassLoader(URL[] urls, ClassLoader parent,
162                    URLStreamHandlerFactory factory) {
163                super (parent);
164                // this is to make the stack depth consistent with 1.1
165                SecurityManager security = System.getSecurityManager();
166                if (security != null) {
167                    security.checkCreateClassLoader();
168                }
169                ucp = new URLClassPath(urls, factory);
170                acc = AccessController.getContext();
171            }
172
173            /**
174             * Appends the specified URL to the list of URLs to search for
175             * classes and resources.
176             * <p>
177             * If the URL specified is <code>null</code> or is already in the 
178             * list of URLs, then invoking this method has no effect.
179             *
180             * @param url the URL to be added to the search path of URLs
181             */
182            protected void addURL(URL url) {
183                ucp.addURL(url);
184            }
185
186            /**
187             * Returns the search path of URLs for loading classes and resources.
188             * This includes the original list of URLs specified to the constructor,
189             * along with any URLs subsequently appended by the addURL() method.
190             * @return the search path of URLs for loading classes and resources.
191             */
192            public URL[] getURLs() {
193                return ucp.getURLs();
194            }
195
196            /**
197             * Finds and loads the class with the specified name from the URL search
198             * path. Any URLs referring to JAR files are loaded and opened as needed
199             * until the class is found.
200             *
201             * @param name the name of the class
202             * @return the resulting class
203             * @exception ClassNotFoundException if the class could not be found
204             */
205            protected Class<?> findClass(final String name)
206                    throws ClassNotFoundException {
207                try {
208                    return (Class) AccessController.doPrivileged(
209                            new PrivilegedExceptionAction() {
210                                public Object run()
211                                        throws ClassNotFoundException {
212                                    String path = name.replace('.', '/')
213                                            .concat(".class");
214                                    Resource res = ucp.getResource(path, false);
215                                    if (res != null) {
216                                        try {
217                                            return defineClass(name, res);
218                                        } catch (IOException e) {
219                                            throw new ClassNotFoundException(
220                                                    name, e);
221                                        }
222                                    } else {
223                                        throw new ClassNotFoundException(name);
224                                    }
225                                }
226                            }, acc);
227                } catch (java.security.PrivilegedActionException pae) {
228                    throw (ClassNotFoundException) pae.getException();
229                }
230            }
231
232            /*
233             * Defines a Class using the class bytes obtained from the specified
234             * Resource. The resulting Class must be resolved before it can be
235             * used.
236             */
237            private Class defineClass(String name, Resource res)
238                    throws IOException {
239                int i = name.lastIndexOf('.');
240                URL url = res.getCodeSourceURL();
241                if (i != -1) {
242                    String pkgname = name.substring(0, i);
243                    // Check if package already loaded.
244                    Package pkg = getPackage(pkgname);
245                    Manifest man = res.getManifest();
246                    if (pkg != null) {
247                        // Package found, so check package sealing.
248                        if (pkg.isSealed()) {
249                            // Verify that code source URL is the same.
250                            if (!pkg.isSealed(url)) {
251                                throw new SecurityException(
252                                        "sealing violation: package " + pkgname
253                                                + " is sealed");
254                            }
255
256                        } else {
257                            // Make sure we are not attempting to seal the package
258                            // at this code source URL.
259                            if ((man != null) && isSealed(pkgname, man)) {
260                                throw new SecurityException(
261                                        "sealing violation: can't seal package "
262                                                + pkgname + ": already loaded");
263                            }
264                        }
265                    } else {
266                        if (man != null) {
267                            definePackage(pkgname, man, url);
268                        } else {
269                            definePackage(pkgname, null, null, null, null,
270                                    null, null, null);
271                        }
272                    }
273                }
274                // Now read the class bytes and define the class
275                java.nio.ByteBuffer bb = res.getByteBuffer();
276                if (bb != null) {
277                    // Use (direct) ByteBuffer:
278                    CodeSigner[] signers = res.getCodeSigners();
279                    CodeSource cs = new CodeSource(url, signers);
280                    return defineClass(name, bb, cs);
281                } else {
282                    byte[] b = res.getBytes();
283                    // must read certificates AFTER reading bytes.
284                    CodeSigner[] signers = res.getCodeSigners();
285                    CodeSource cs = new CodeSource(url, signers);
286                    return defineClass(name, b, 0, b.length, cs);
287                }
288            }
289
290            /**
291             * Defines a new package by name in this ClassLoader. The attributes
292             * contained in the specified Manifest will be used to obtain package
293             * version and sealing information. For sealed packages, the additional
294             * URL specifies the code source URL from which the package was loaded.
295             *
296             * @param name  the package name
297             * @param man   the Manifest containing package version and sealing
298             *              information
299             * @param url   the code source url for the package, or null if none
300             * @exception   IllegalArgumentException if the package name duplicates
301             *              an existing package either in this class loader or one
302             *              of its ancestors
303             * @return the newly defined Package object
304             */
305            protected Package definePackage(String name, Manifest man, URL url)
306                    throws IllegalArgumentException {
307                String path = name.replace('.', '/').concat("/");
308                String specTitle = null, specVersion = null, specVendor = null;
309                String implTitle = null, implVersion = null, implVendor = null;
310                String sealed = null;
311                URL sealBase = null;
312
313                Attributes attr = man.getAttributes(path);
314                if (attr != null) {
315                    specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
316                    specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
317                    specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
318                    implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
319                    implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
320                    implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
321                    sealed = attr.getValue(Name.SEALED);
322                }
323                attr = man.getMainAttributes();
324                if (attr != null) {
325                    if (specTitle == null) {
326                        specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
327                    }
328                    if (specVersion == null) {
329                        specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
330                    }
331                    if (specVendor == null) {
332                        specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
333                    }
334                    if (implTitle == null) {
335                        implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
336                    }
337                    if (implVersion == null) {
338                        implVersion = attr
339                                .getValue(Name.IMPLEMENTATION_VERSION);
340                    }
341                    if (implVendor == null) {
342                        implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
343                    }
344                    if (sealed == null) {
345                        sealed = attr.getValue(Name.SEALED);
346                    }
347                }
348                if ("true".equalsIgnoreCase(sealed)) {
349                    sealBase = url;
350                }
351                return definePackage(name, specTitle, specVersion, specVendor,
352                        implTitle, implVersion, implVendor, sealBase);
353            }
354
355            /*
356             * Returns true if the specified package name is sealed according to the
357             * given manifest.
358             */
359            private boolean isSealed(String name, Manifest man) {
360                String path = name.replace('.', '/').concat("/");
361                Attributes attr = man.getAttributes(path);
362                String sealed = null;
363                if (attr != null) {
364                    sealed = attr.getValue(Name.SEALED);
365                }
366                if (sealed == null) {
367                    if ((attr = man.getMainAttributes()) != null) {
368                        sealed = attr.getValue(Name.SEALED);
369                    }
370                }
371                return "true".equalsIgnoreCase(sealed);
372            }
373
374            /**
375             * Finds the resource with the specified name on the URL search path.
376             *
377             * @param name the name of the resource
378             * @return a <code>URL</code> for the resource, or <code>null</code> 
379             * if the resource could not be found.
380             */
381            public URL findResource(final String name) {
382                /*
383                 * The same restriction to finding classes applies to resources
384                 */
385                URL url = (URL) AccessController.doPrivileged(
386                        new PrivilegedAction() {
387                            public Object run() {
388                                return ucp.findResource(name, true);
389                            }
390                        }, acc);
391
392                return url != null ? ucp.checkURL(url) : null;
393            }
394
395            /**
396             * Returns an Enumeration of URLs representing all of the resources
397             * on the URL search path having the specified name.
398             *
399             * @param name the resource name
400             * @exception IOException if an I/O exception occurs
401             * @return an <code>Enumeration</code> of <code>URL</code>s
402             */
403            public Enumeration<URL> findResources(final String name)
404                    throws IOException {
405                final Enumeration e = ucp.findResources(name, true);
406
407                return new Enumeration<URL>() {
408                    private URL url = null;
409
410                    private boolean next() {
411                        if (url != null) {
412                            return true;
413                        }
414                        do {
415                            URL u = (URL) AccessController.doPrivileged(
416                                    new PrivilegedAction() {
417                                        public Object run() {
418                                            if (!e.hasMoreElements())
419                                                return null;
420                                            return e.nextElement();
421                                        }
422                                    }, acc);
423                            if (u == null)
424                                break;
425                            url = ucp.checkURL(u);
426                        } while (url == null);
427                        return url != null;
428                    }
429
430                    public URL nextElement() {
431                        if (!next()) {
432                            throw new NoSuchElementException();
433                        }
434                        URL u = url;
435                        url = null;
436                        return u;
437                    }
438
439                    public boolean hasMoreElements() {
440                        return next();
441                    }
442                };
443            }
444
445            /**
446             * Returns the permissions for the given codesource object.
447             * The implementation of this method first calls super.getPermissions
448             * and then adds permissions based on the URL of the codesource.
449             * <p>
450             * If the protocol of this URL is "jar", then the permission granted 
451             * is based on the permission that is required by the URL of the Jar 
452             * file.
453             * <p>
454             * If the protocol is "file" and there is an authority component, then
455             * permission to connect to and accept connections from that authority 
456             * may be granted. If the protocol is "file"
457             * and the path specifies a file, then permission to read that
458             * file is granted. If protocol is "file" and the path is
459             * a directory, permission is granted to read all files
460             * and (recursively) all files and subdirectories contained in
461             * that directory.
462             * <p>
463             * If the protocol is not "file", then permission
464             * to connect to and accept connections from the URL's host is granted.
465             * @param codesource the codesource
466             * @return the permissions granted to the codesource
467             */
468            protected PermissionCollection getPermissions(CodeSource codesource) {
469                PermissionCollection perms = super .getPermissions(codesource);
470
471                URL url = codesource.getLocation();
472
473                Permission p;
474                URLConnection urlConnection;
475
476                try {
477                    urlConnection = url.openConnection();
478                    p = urlConnection.getPermission();
479                } catch (java.io.IOException ioe) {
480                    p = null;
481                    urlConnection = null;
482                }
483
484                if (p instanceof  FilePermission) {
485                    // if the permission has a separator char on the end,
486                    // it means the codebase is a directory, and we need
487                    // to add an additional permission to read recursively
488                    String path = p.getName();
489                    if (path.endsWith(File.separator)) {
490                        path += "-";
491                        p = new FilePermission(path,
492                                SecurityConstants.FILE_READ_ACTION);
493                    }
494                } else if ((p == null) && (url.getProtocol().equals("file"))) {
495                    String path = url.getFile()
496                            .replace('/', File.separatorChar);
497                    path = ParseUtil.decode(path);
498                    if (path.endsWith(File.separator))
499                        path += "-";
500                    p = new FilePermission(path,
501                            SecurityConstants.FILE_READ_ACTION);
502                } else {
503                    /**
504                     * Not loading from a 'file:' URL so we want to give the class
505                     * permission to connect to and accept from the remote host
506                     * after we've made sure the host is the correct one and is valid.
507                     */
508                    URL locUrl = url;
509                    if (urlConnection instanceof  JarURLConnection) {
510                        locUrl = ((JarURLConnection) urlConnection)
511                                .getJarFileURL();
512                    }
513                    String host = locUrl.getHost();
514                    if (host != null && (host.length() > 0))
515                        p = new SocketPermission(host,
516                                SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
517                }
518
519                // make sure the person that created this class loader
520                // would have this permission
521
522                if (p != null) {
523                    final SecurityManager sm = System.getSecurityManager();
524                    if (sm != null) {
525                        final Permission fp = p;
526                        AccessController.doPrivileged(new PrivilegedAction() {
527                            public Object run() throws SecurityException {
528                                sm.checkPermission(fp);
529                                return null;
530                            }
531                        }, acc);
532                    }
533                    perms.add(p);
534                }
535                return perms;
536            }
537
538            /**
539             * Creates a new instance of URLClassLoader for the specified
540             * URLs and parent class loader. If a security manager is
541             * installed, the <code>loadClass</code> method of the URLClassLoader
542             * returned by this method will invoke the
543             * <code>SecurityManager.checkPackageAccess</code> method before
544             * loading the class.
545             *
546             * @param urls the URLs to search for classes and resources
547             * @param parent the parent class loader for delegation
548             * @return the resulting class loader
549             */
550            public static URLClassLoader newInstance(final URL[] urls,
551                    final ClassLoader parent) {
552                // Save the caller's context
553                AccessControlContext acc = AccessController.getContext();
554                // Need a privileged block to create the class loader
555                URLClassLoader ucl = (URLClassLoader) AccessController
556                        .doPrivileged(new PrivilegedAction() {
557                            public Object run() {
558                                return new FactoryURLClassLoader(urls, parent);
559                            }
560                        });
561                // Now set the context on the loader using the one we saved,
562                // not the one inside the privileged block...
563                ucl.acc = acc;
564                return ucl;
565            }
566
567            /**
568             * Creates a new instance of URLClassLoader for the specified
569             * URLs and default parent class loader. If a security manager is
570             * installed, the <code>loadClass</code> method of the URLClassLoader
571             * returned by this method will invoke the
572             * <code>SecurityManager.checkPackageAccess</code> before
573             * loading the class.
574             *
575             * @param urls the URLs to search for classes and resources
576             * @return the resulting class loader
577             */
578            public static URLClassLoader newInstance(final URL[] urls) {
579                // Save the caller's context
580                AccessControlContext acc = AccessController.getContext();
581                // Need a privileged block to create the class loader
582                URLClassLoader ucl = (URLClassLoader) AccessController
583                        .doPrivileged(new PrivilegedAction() {
584                            public Object run() {
585                                return new FactoryURLClassLoader(urls);
586                            }
587                        });
588
589                // Now set the context on the loader using the one we saved,
590                // not the one inside the privileged block...
591                ucl.acc = acc;
592                return ucl;
593            }
594
595            static {
596                sun.misc.SharedSecrets
597                        .setJavaNetAccess(new sun.misc.JavaNetAccess() {
598                            public URLClassPath getURLClassPath(URLClassLoader u) {
599                                return u.ucp;
600                            }
601                        });
602            }
603        }
604
605        final class FactoryURLClassLoader extends URLClassLoader {
606
607            FactoryURLClassLoader(URL[] urls, ClassLoader parent) {
608                super (urls, parent);
609            }
610
611            FactoryURLClassLoader(URL[] urls) {
612                super (urls);
613            }
614
615            public final synchronized Class loadClass(String name,
616                    boolean resolve) throws ClassNotFoundException {
617                // First check if we have permission to access the package. This
618                // should go away once we've added support for exported packages.
619                SecurityManager sm = System.getSecurityManager();
620                if (sm != null) {
621                    int i = name.lastIndexOf('.');
622                    if (i != -1) {
623                        sm.checkPackageAccess(name.substring(0, i));
624                    }
625                }
626                return super.loadClass(name, resolve);
627            }
628        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.