Hi,

In an earlier message I said that since java.net.URLClassLoader was based on
SecureClassLoader which depends on some 1.2 features not yet implemented in
Classpath it would not be I good idea to use it for loading Locales.
But that did not stop me from trying to implement it. (But I wise that I had
followed my own advise since it depends on a lot of tricky issues with
ClassLoaders, Security and Jar Manifests :)

Attached is a hopefully fairly complete and not to buggy implementation.
But it is not tested since there is no 1.2 support yet. (There are also some
notes in the comments about issues I was not completely sure of.)
I did implement java.lang.Package so I could at least almost compile it with
Classpath. And there is also a diff for JarURLConnection attached to change
the getIdentities() method to a getCertificates() method which URLClassLoader
also needs.

I will now start on implementing java.util.jar so I can at least compile
everything with Classpath. And if that is finished and Loren has not yet
surfaced then I want to implement java.util.zip.

Cheers,

Mark
/*************************************************************************
/* URLClassLoader.java -- Class loader that loads classes from one or more URLs
/*
/* Copyright (c) 1999 Free Software Foundation, Inc.
/* Written by Mark Wielaard ([EMAIL PROTECTED])
/*
/* This library is free software; you can redistribute it and/or modify
/* it under the terms of the GNU Library General Public License as published 
/* by the Free Software Foundation, either version 2 of the License, or
/* (at your option) any later verion.
/*
/* This library is distributed in the hope that it will be useful, but
/* WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/* GNU Library General Public License for more details.
/*
/* You should have received a copy of the GNU Library General Public License
/* along with this library; if not, write to the Free Software Foundation
/* Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
/*************************************************************************/

package java.net;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.FilePermission;
import java.security.CodeSource;
import java.security.SecureClassLoader;
import java.security.PermissionCollection;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.Vector;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

/**
 * A secure class loader that can load classes and resources from multiple
 * locations. Given an array of URLs this class loader will retrieve classes
 * and resources by fetching them from possible remote locations. Each URL is
 * searched in order in which it was added. If the file portion of the URL ends
 * with a / character then it is interpreted as a base directory, otherwise it
 * is interpreted as a jar file from which the classes/resources are resolved.
 * <p>
 * New instances can be created by two static newInstance() methods or by
 * three public contructors. Both give the option to supply an initial array
 * of URLs and (optionally) a parent classloader (that is different from the
 * standard system class loader).
 * Creating a <code>URLClassLoader</code> can always throw a
 * <code>SecurityException</code> if the checkes performed by the constructor of
 * <code>SecureClassLoader</code>, which are called when creating a new
 * instance, fail.
 * Note that only subclasses can add new URLs after the URLClassLoader had been
 * created. But it is always possible to get an array of all URLs that the class
 * loader uses to resolve classes and resources by way of the
 * <code>getURLs()</code> method.
 * <p>
 * XXX - TODO - FIXME This implementation is not finished or tested!<br>
 * Open issues:
 * <ul>
 * <li>Should the URLClassLoader actually add the locations found in the
 * manifest or is this the responsibility of some other loader/(sub)class?
 * (see <a href="http://java.sun.com/products/jdk/1.3/docs/guide/extensions/spec.html#bundled">Extension Machanism Architecture - Bundles Extensions</a>)
 * <li> How does <code>definePackage()</code> and sealing work precisely?
 * (Note that the method is currently not even implemented in
 * <code>java.lang.ClassLoader</code>.)
 * <li> Should the static <code>newInstance()</code> methods always succeed? Or
 * are they also restricted by the normal security checks?
 * <li> We might want to do some caching of URLs, Connections or JarFiles.
 * For now we just assume that the (Jar)URLConnection takes care of this.
 * <li> Is the way we create the "jar" URLs correct? What if it was already a
 * "jar" URL?
 * <li> XXX
 * </ul>
 *
 * @author Mark Wielaard ([EMAIL PROTECTED])
 */
public class URLClassLoader extends SecureClassLoader {

    // Variables

    /** Locations to load classes from */
    private Vector urls = new Vector();

    /** Factory used to get the protocol handlers of the URLs */
    private URLStreamHandlerFactory factory = null;

    // Constructors

    /**
     * Creates a URLClassLoader that gets classes from the supplied URLs.
     * To determine if this classloader may be created the constructor of
     * the super class (<CODE>SecureClassLoader</CODE>) is called first, which
     * can throw a SecurityException. Then the supplied URLs are added
     * in the order given to the URLClassLoader which uses these URLs to
     * load classes and resources (after using the default parent ClassLoader).
     * @exception SecurityException if the SecurityManager disallows the
     * creation of a ClassLoader.
     * @param urls Locations that should be searched by this ClassLoader when
     * resolving Classes or Resources.
     * @see SecureClassLoader
     */
    public URLClassLoader(URL[] urls) throws SecurityException {
        super();
        addURLs(urls);
    }

    /**
     * Creates a URLClassLoader that gets classes from the supplied URLs.
     * To determine if this classloader may be created the constructor of
     * the super class (<CODE>SecureClassLoader</CODE>) is called first, which
     * can throw a SecurityException. Then the supplied URLs are added
     * in the order given to the URLClassLoader which uses these URLs to
     * load classes and resources (after using the supplied parent ClassLoader).
     * @exception SecurityException if the SecurityManager disallows the
     * creation of a ClassLoader.
     * @exception SecurityException 
     * @param urls Locations that should be searched by this ClassLoader when
     * resolving Classes or Resources.
     * @param parent The parent class loader used before trying this class
     * loader.
     * @see SecureClassLoader
     */
    public URLClassLoader(URL[] urls, ClassLoader parent) throws
                                                          SecurityException {
        super(parent);
        addURLs(urls);
    }

    /**
     * Creates a URLClassLoader that gets classes from the supplied URLs.
     * To determine if this classloader may be created the constructor of
     * the super class (<CODE>SecureClassLoader</CODE>) is called first, which
     * can throw a SecurityException. Then the supplied URLs are added
     * in the order given to the URLClassLoader which uses these URLs to
     * load classes and resources (after using the supplied parent ClassLoader).
     * It will use the supplied <CODE>URLStreamHandlerFactory</CODE> to get the
     * protocol handlers of the supplied URLs.
     * @exception SecurityException if the SecurityManager disallows the
     * creation of a ClassLoader.
     * @exception SecurityException 
     * @param urls Locations that should be searched by this ClassLoader when
     * resolving Classes or Resources.
     * @param parent The parent class loader used before trying this class
     * loader.
     * @param factory Used to get the protocol handler for the URLs.
     * @see SecureClassLoader
     */
    public URLClassLoader(URL[] urls,
                          ClassLoader parent,
                          URLStreamHandlerFactory factory) throws
                                                           SecurityException {
        super(parent);
        addURLs(urls);
        this.factory = factory;
    }

    // Methods

    /**
     * Adds a new location to the end of the internal URL store.
     * @param newUrl the location to add
     */
    protected void addURL(URL newUrl) {
        urls.add(newUrl);
    }

    /**
     * Adds an array of new locations to the end of the internal URL store.
     * @param newUrls the locations to add
     */
    private void addURLs(URL[] newUrls) {
        for (int i = 0; i < newUrls.length; i++) {
            addURL(newUrls[i]);
        }
    }

    /** 
     * Defines a Package based on the given name and the supplied manifest
     * information. The manifest indicates the tile, version and
     * vendor information of the specification and implementation and wheter the
     * package is sealed. If the Manifest indicates that the package is sealed
     * then the Package will be sealed with respect to the supplied URL.
     *
     * @exception IllegalArgumentException If this package name already exists
     * in this class loader
     * @param name The name of the package
     * @param manifest The manifest describing the specification,
     * implementation and sealing details of the package
     * @param url the code source url to seal the package
     * @return the defined Package
     */
    protected Package definePackage(String name, Manifest manifest, URL url) 
                                             throws IllegalArgumentException {
        Attributes attr = manifest.getMainAttributes();
        String specTitle =
            attr.getValue(Attributes.Name.SPECIFICATION_TITLE); 
        String specVersion =
            attr.getValue(Attributes.Name.SPECIFICATION_VERSION); 
        String specVendor =
            attr.getValue(Attributes.Name.SPECIFICATION_VENDOR); 
        String implTitle =
            attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE); 
        String implVersion =
            attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION); 
        String implVendor =
            attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);

        // Look if the Manifest indicates that this package is sealed
        // XXX - most likely not completely correct!
        // Shouldn't we also check the sealed attribute of the complete jar?
// http://java.sun.com/products/jdk/1.3/docs/guide/extensions/spec.html#bundled
        // But how do we get that jar manifest here?
        String sealed = attr.getValue(Attributes.Name.SEALED);
        if ("false".equals(sealed)) {
            // make sure that the URL is null so the package is not sealed
            url = null;
        }

        // XXX - Since ClassLoader.definePackage is not implemented return null
        return null;

        // XXX - Replace it with this return when ClassLoader.definePackage()
        // is actually implemented.
        // return definePackage(name, specTitle, specVersion, specVendor,
        //                      implTitle, implVersion, implVendor, url);
    }

    /**
     * Finds (the first) class by name from one of the locations. The locations
     * are searched in the order they were added to the URLClassLoader.
     * @param className the classname to find
     * @exception ClassNotFoundException when the class could not be found or
     * loaded
     * @return a Class object representing the found class
     */
    protected Class findClass(String className) throws ClassNotFoundException {
        // Just try to find the resource by the (almost) same name
        String resourceName = className.replace('.', '/') + ".class";
        URL url = findResource(resourceName);
        if (url == null) {
            throw new ClassNotFoundException(className);
        }

        // Try to read the class data, create the CodeSource and construct the
        // class (and watch out for those nasty IOExceptions)
        try {
            byte [] classData;
            URLConnection conn = url.openConnection();
            InputStream in = conn.getInputStream();
            int length = conn.getContentLength();
            if (length != -1) {
                // We know the length of the data, just read it all in at once
                classData = new byte[length];
                in.read(classData);
            } else {
                // We don't know the data length so we have to read it in chunks
                ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
                byte b[] = new byte[1024];
                int l = 0;
                while (l != -1) {
                    l = in.read(b);
                    if (l != -1) {
                        out.write(b, 0, l);
                    }
                }
                classData = out.toByteArray();
            }

            // Now construct the CodeSource (if loaded from a jar file)
            CodeSource source = null;
            if (url.getProtocol().equals("jar")) {
                Certificate[] certificates =
                                   ((JarURLConnection)conn).getCertificates();
                source = new CodeSource(url, certificates);
            }

            // And finally construct the class!
            return defineClass(className, classData,
                               0, classData.length,
                               source);
        } catch (IOException ioe) {
            throw new ClassNotFoundException(className + ": " + ioe);
        }
    }

    /**
     * Finds the first occurrence of a resource that can be found. The locations
     * are searched in the order they were added to the URLClassLoader.
     * @param resourceName the resource name to look for
     * @return the URL if found, null otherwise
     */
    public URL findResource(String resourceName) {
        Enumeration e = urls.elements();
        while (e.hasMoreElements()) {
            URL url = findResource(resourceName, (URL)e.nextElement());
            if (url != null) {
                // Found the resource
                return url;
            }
        }
        // Resource not found
        return null;
    }

    /**
     * Find a resource relative to a base URL. If the base URL ends with a /
     * character then the base URL is interpreted as a directory and the
     * resource name is appended to it, otherwise the base URL is interpreted
     * as a jar file and a "jar" URL is constructed from the base URL and the
     * supplied resource name. This method tries to open a connection to the
     * resulting URL to make sure the resource is actually there.
     * <p>
     * XXX - We might want to do some caching of URLs, Connections or JarFiles.
     * For now we just assume that the (Jar)URLConnection takes care of this.
     * XXX - Should we also disconnect/close the URLConnection again? And how
     * would we do that? For now just assume the connection will actually be
     * used.
     * @param resourceName the resource name to look for
     * @param url the base URL
     * @return the URL if found, null otherwise
     * @see JarURLConnection
     */
    private URL findResource(String resourceName, URL url) {
        URL resourceURL;
        // Get the file portion of the base URL
        String file = url.getFile();

        // Construct the resourceURL
        if (file.endsWith("/")) {
            // Interpret it as a directory and just append the resource name
            try {
                resourceURL = new URL(url, resourceName,
                                    createURLStreamHandler(url.getProtocol()));
            } catch (MalformedURLException e) {
                return null;
            }
        } else {
            // Interpret it as a jar file and construct a "jar" URL
            String external = url.toExternalForm();
            try {
                // XXX - Is this correct? Why is there no URL constructor that
                // takes just a string and a URLStreamHandler?
                resourceURL = new URL(new URL("jar:" + external + "!/"),
                                      resourceName,
                                      createURLStreamHandler("jar"));
            } catch (MalformedURLException e) {
                return null;
            }
        }

        // Check if the resource is actually at that location
        try {
            resourceURL.openConnection();
        } catch (IOException ioe) {
            return null;
        }

        return resourceURL;
    }

    /**
     * If the URLStreamHandlerFactory has been set this return the appropriate
     * URLStreamHandler for the given protocol.
     * @param protocol the protocol for which we need a URLStreamHandler
     * @return the appropriate URLStreamHandler or null
     */
    private URLStreamHandler createURLStreamHandler(String protocol) {
        if (factory != null) {
            return factory.createURLStreamHandler(protocol);
        } else {
            return null;
        }
    }

    /**
     * Finds all the resources with a particular name from all the locations.
     * @exception IOException when an error occurs accessing one of the
     * locations
     * @param resourceName the name of the resource to lookup
     * @return a (possible empty) enumeration of URLs where the resource can be
     * found
     */
    public Enumeration findResources(String resourceName) throws IOException {
        Vector resources = new Vector();
        Enumeration e = urls.elements();
        while (e.hasMoreElements()) {
            URL url = findResource(resourceName, (URL)e.nextElement());
            if (url != null) {
                // Found another resource
                resources.add(url);
            }
        }
        return resources.elements();
    }

    /**
     * Returns the permissions needed to access a particular code source.
     * These permissions includes those returned by
     * <CODE>SecureClassLoader.getPermissions</CODE> and the actual permissions
     * to access the objects referenced by the URL of the code source.
     * The extra permissions added depend on the protocol and file portion of
     * the URL in the code source. If the URL has the "file" protocol ends with
     * a / character then it must be a directory and a file Permission to read
     * everthing in that directory and all subdirectories is added. If the URL
     * had the "file" protocol and doesn't end with a / character then it must
     * be a normal file and a file permission to read that file is added. If the
     * URL has any other protocol then a socket permission to connect and accept
     * connections from the host portion of the URL is added.
     * @param source The codesource that needs the permissions to be accessed
     * @return the collection of permissions needed to access the code resource
     * @see SecureClassLoader.getPermissions()
     */
    protected PermissionCollection getPermissions(CodeSource source) {
        // XXX - This implementation does exactly as the Javadoc describes.
        // But maybe we should/could use URLConnection.getPermissions()?

        // First get the permissions that would normally be granted
        PermissionCollection permissions = super.getPermissions(source);
        
        // Now add the any extra permissions depending on the URL location
        URL url = source.getLocation();
        String protocol = url.getProtocol();
        if (protocol.equals("file")) {
            String file = url.getFile();
            // If the file end in / it must be an directory
            if (file.endsWith("/")) {
                // Grant permission to read everything in that directory and
                // all subdirectories
                permissions.add(new FilePermission(file + "-", "read"));
            } else { // It is a 'normal' file
                // Grant permission to access that file
                permissions.add(new FilePermission(file, "read"));
            }
        } else {
            // Grant permission to connect to and accept connections from host
            String host = url.getHost();
            permissions.add(new SocketPermission(host, "connect,accept"));
        }

        return permissions;
    }
    
    /**
     * Returns all the locations that this class loader currently uses the
     * resolve classes and resource. This includes both the initially supplied
     * URLs as any URLs added later by the loader.
     * @return All the currently used URLs
     */
    public URL[] getURLs() {
        return (URL[]) urls.toArray();
    }

    /**
     * Creates a new instance of a URLClassLoader that gets classes from the
     * supplied URLs. This class loader will have as parent the standard
     * system class loader.
     * @param urls the initial URLs used to resolve classes and resources
     */
    public static URLClassLoader newInstance(URL urls[]) throws
                                                         SecurityException {
        return new URLClassLoader(urls);
    }

    /**
     * Creates a new instance of a URLClassLoader that gets classes from the
     * supplied URLs and with the supplied loader as parent class loader.
     * @param urls the initial URLs used to resolve classes and resources
     * @param parent the parent class loader
     */
    public static URLClassLoader newInstance(URL urls[],
                                             ClassLoader parent) throws
                                                         SecurityException {
        return new URLClassLoader(urls, parent);
    }
}
/*
 * java.lang.Package: part of the Java Class Libraries project.
 * Copyright (C) 1999 Free Software Foundation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */

package java.lang;

import java.net.URL;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

/**
 * Everything you ever wanted to know about a package. This class makes it
 * possible to attach specification and implementation information to a
 * package as explained in the
 * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersionSpecification">Package Versioning Specification</a>
 * section of the
 * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html">Product Versioning Specification</a>.
 * It also allows packages to be sealed with respect to the originating URL.
 * <p>
 * The most usefull method is the <code>isCompatibleWith()</code> method that
 * compares a desired version of a specification with the version of the
 * specification as implemented by a package. A package is considered compatible
 * with another version if the version of the specification is equal or higer
 * then the requested version. Version numbers are represented as strings of
 * positive numbers seperated by dots (e.g. "1.2.0"). The first number is called
 * the major number, the second the minor, the third the micro, etc. A version
 * is considered higher then another version if it has a bigger major number
 * then the another version or when the major numbers of the versions are equal
 * if it has a bigger minor number then the other version, etc. (If a version
 * has no minor, micro, etc numbers then they are considered the be 0.)
 * 
 * @since JDK1.2
 * @author Mark Wielaard
 * @version 1.0, 19 Dec 1999
 */
public class Package {

    // Variables

    /** The name of the Package
     */
    final private String name;

    /** The name if the implementation
     */
    final private String implTitle;
    /** The vendor that wrote this implementation
     */
    final private String implVendor;
    /** The version of this implementation
     */
    final private String implVersion;

    /** The name of the specification
     */
    final private String specTitle;
    /** The name of the specification designer
     */
    final private String specVendor;
    /** The version of this specification
     */
    final private String specVersion;

    /** If sealed the origin of the package classes
     */
    final private URL sealed;

    // Constructors

    /** 
     * A package local constructor for the Package class.
     * XXX - There are no public constructors defined for Package so I just
     * invented a package local constructor that can be used by classes in
     * java.lang.
     * 
     * @param name The name of the Package
     * @param implTitle The name of the implementation
     * @param implVendor The vendor that wrote this implementation
     * @param implVersion The version of this implementation
     * @param specTitle The name of the specification
     * @param specVendor The name of the specification designer
     * @param specVersion The version of this specification
     * @param sealed If sealed the origin of the package classes
     */
    Package(String name,
            String implTitle, String implVendor, String implVersion,
            String specTitle, String specVendor, String specVersion,
            URL sealed) {

        this.name = name;

        this.implTitle = implTitle;
        this.implVendor = implVendor;
        this.implVersion = implVersion;

        this.specTitle = specTitle;
        this.specVendor = specVendor;
        this.specVersion = specVersion;

        this.sealed = sealed;
    }

    // Methods

    /** 
     * Returns the Package name.
     */
    public String getName() {
        return name;
    }

    /** 
     * Returns the name of the implementation or null if unknown.
     */
    public String getImplementationTitle() {
        return implTitle;
    }

    /** 
     * Returns the vendor that wrote this implementation or null if unknown.
     */
    public String getImplementationVendor() {
        return implVendor;
    }

    /** 
     * Returns the version of this implementation or null if unknown.
     */
    public String getImplementationVersion() {
        return implVersion;
    }

    /** 
     * Returns the name of the specification or null if unknown.
     */
    public String getSpecificationTitle() {
        return specTitle;
    }

    /** 
     * Returns the name of the specification designer.
     */
    public String getSpecificationVendor() {
        return specVendor;
    }

    /** 
     * Returns the version of the specification or null if unknown.
     */
    public String getSpecificationVersion() {
        return specVersion;
    }

    /** 
     * Returns true if this Package is sealed.
     */
    public boolean isSealed() {
        return (sealed != null);
    }

    /** 
     * Returns true if this Package is sealed and the origin of the classes is
     * the given URL.
     * 
     * @param url 
     */
    public boolean isSealed(URL url) {
        return url.equals(sealed);
    }

    /**
     * Checks if the version of the specification is higher or at least as high
     * as the desired version.
     * XXX - It may throw unexpected (NullPointer) exceptions when the supplied
     * version or the specification version are null.
     * @param version the (minimal) desired version of the specification
     * @exception NumberFormatException when either version or the specification
     * version is not a correctly formatted version number
     */
    public boolean isCompatibleWith(String version) throws
                                                    NumberFormatException {
        StringTokenizer versionTokens = new StringTokenizer(version, ".");
        StringTokenizer specTokens = new StringTokenizer(specVersion, ".");
        try {
            while (versionTokens.hasMoreElements()) {
                int vers = Integer.parseInt(versionTokens.nextToken());
                int spec = Integer.parseInt(specTokens.nextToken());
                if (spec < vers) {
                    return false;
                } else if (spec > vers) {
                    return true;
                }
                // They must be equal, next Token please!
            }
        } catch (NoSuchElementException e) {
            // this must have been thrown by spec.netToken() so return false
            return false;
        }

        // They must have been exactly the same version.
        // Or the specVersion has more subversions. That is also good.
        return true;
    }

    /**
     * Returns the named package if it is known by the callers class loader.
     * It may return null if the package is unknown or when there is no
     * information on that particular package available.
     * XXX - Since ClassLoader.getPackage() is not yet implemented it just
     * returns null.
     * @param name the name of the desired package
     */
    public static Package getPackage(String name) {
        return null;
    }

    /**
     * Returns all the packages that are known to the callers class loader.
     * XXX - Since ClassLoader.getPackages() is not yet implemented it just
     * returns null.
     */
    public static Package[] getPackages() {
        return null;
    }

    /** 
     * Returns the hashCode of the name of this package.
     */
    public int hashCode() {
        return name.hashCode();
    }

    /** 
     * Returns a string representation of this package name, specification,
     * implementation and class origin if sealed.
     */
    public String toString() {
        return "package: " + name +
               " spec: " + specTitle +
               " version: " + specVersion +
               " vendor: " + specVendor +
               " implementation: " + implTitle +
               " version: " + implVersion +
               " vendor: " + implVendor +
               " sealed: " + sealed;
    }
}
--- JarURLConnection.java       1998/07/24 01:59:40     1.2
+++ JarURLConnection.java       1999/12/19 22:19:51
@@ -22,7 +22,7 @@
 package java.net;
 
 import java.io.IOException;
-import java.security.Identity;
+import java.security.cert.Certificate;
 import java.util.jar.*;
 
 /**
@@ -222,17 +222,17 @@
 /*************************************************************************/
 
 /**
-  * Returns an array of Identity objects for the jar file entry specified
+  * Returns an array of Certificate objects for the jar file entry specified
   * by this URL or null if there are none
   *
-  * @return An Identity array
+  * @return A Certificate array
   *
   * @exception IOException If an error occurs
   */
-public Identity[]
-getIdentities() throws IOException
+public Certificate[]
+getCertificates() throws IOException
 {
-  return(getJarEntry().getIdentities());
+  return(getJarEntry().getCertificates());
 }
 
 } // class JarURLConnection

Reply via email to