| /******************************************************************************* |
| * Copyright (c) 2004, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.osgi.framework.adaptor.core; |
| |
| import java.io.*; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.security.*; |
| import java.security.cert.Certificate; |
| import java.util.*; |
| import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate; |
| import org.eclipse.osgi.framework.debug.Debug; |
| import org.eclipse.osgi.util.NLS; |
| import org.osgi.framework.BundleException; |
| import org.osgi.framework.FrameworkEvent; |
| |
| /** |
| * A concrete implementation of BundleClassLoader. This implementation |
| * consolidates all Bundle-ClassPath entries into a single ClassLoader. |
| * <p> |
| * Clients may extend this class. |
| * </p> |
| * @since 3.1 |
| */ |
| public class DefaultClassLoader extends AbstractClassLoader { |
| /** |
| * A PermissionCollection for AllPermissions; shared across all ProtectionDomains when security is disabled |
| */ |
| static final PermissionCollection ALLPERMISSIONS; |
| static { |
| AllPermission allPerm = new AllPermission(); |
| ALLPERMISSIONS = allPerm.newPermissionCollection(); |
| if (ALLPERMISSIONS != null) |
| ALLPERMISSIONS.add(allPerm); |
| } |
| /** |
| * The BundleData object for this BundleClassLoader |
| */ |
| protected AbstractBundleData hostdata; |
| |
| /** |
| * The ClasspathEntries for this BundleClassLoader. Each ClasspathEntry object |
| * represents on Bundle-ClassPath entry. |
| */ |
| protected ClasspathEntry[] classpathEntries; |
| |
| /** |
| * A list of fragment classpaths for this classloader |
| */ |
| protected Vector fragClasspaths; //TODO This should be an array or an arraylist if the synchronization is not required |
| |
| /** |
| * The buffer size to use when loading classes. This value is used |
| * only if we cannot determine the size of the class we are loading. |
| */ |
| protected int buffersize = 8 * 1024; //TODO Could not that be a constant? |
| |
| /** |
| * BundleClassLoader constructor. |
| * @param delegate The ClassLoaderDelegate for this ClassLoader. |
| * @param domain The ProtectionDomain for this ClassLoader. |
| * @param classpath An array of Bundle-ClassPath entries to |
| * use for loading classes and resources. This is specified by the |
| * Bundle-ClassPath manifest entry. |
| * @param parent The parent ClassLoader. |
| * @param bundledata The BundleData for this ClassLoader |
| */ |
| public DefaultClassLoader(ClassLoaderDelegate delegate, ProtectionDomain domain, String[] classpath, ClassLoader parent, AbstractBundleData bundledata) { |
| super(delegate, domain, classpath, parent); |
| this.hostdata = bundledata; |
| |
| try { |
| hostdata.open(); /* make sure the BundleData is open */ |
| } catch (IOException e) { |
| hostdata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, hostdata.getBundle(), e); |
| } |
| } |
| |
| /** |
| * @see org.eclipse.osgi.framework.adaptor.BundleClassLoader#initialize() |
| */ |
| public void initialize() { |
| classpathEntries = buildClasspath(hostclasspath, hostdata, hostdomain); |
| } |
| |
| /** |
| * @see org.eclipse.osgi.framework.adaptor.BundleClassLoader#attachFragment(BundleData, ProtectionDomain, String[]) |
| */ |
| public void attachFragment(org.eclipse.osgi.framework.adaptor.BundleData bundledata, ProtectionDomain domain, String[] classpath) { |
| AbstractBundleData abstractbundledata = (AbstractBundleData) bundledata; |
| try { |
| bundledata.open(); /* make sure the BundleData is open */ |
| } catch (IOException e) { |
| |
| abstractbundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, abstractbundledata.getBundle(), e); |
| } |
| ClasspathEntry[] fragEntries = buildClasspath(classpath, abstractbundledata, domain); |
| FragmentClasspath fragClasspath = new FragmentClasspath(fragEntries, abstractbundledata, domain); |
| insertFragment(fragClasspath); |
| } |
| |
| /** |
| * Inserts a fragment classpath to into the list of fragments for this host. |
| * Fragments are inserted into the list according to the fragment's |
| * Bundle ID. |
| * @param fragClasspath The FragmentClasspath to insert. |
| */ |
| protected synchronized void insertFragment(FragmentClasspath fragClasspath) { |
| if (fragClasspaths == null) { |
| // First fragment to attach. Simply create the list and add the fragment. |
| fragClasspaths = new Vector(10); |
| fragClasspaths.addElement(fragClasspath); |
| return; |
| } |
| |
| // Find a place in the fragment list to insert this fragment. |
| int size = fragClasspaths.size(); |
| long fragID = fragClasspath.bundledata.getBundleID(); |
| for (int i = 0; i < size; i++) { |
| long otherID = ((FragmentClasspath) fragClasspaths.elementAt(i)).bundledata.getBundleID(); |
| if (fragID < otherID) { |
| fragClasspaths.insertElementAt(fragClasspath, i); |
| return; |
| } |
| } |
| // This fragment has the highest ID; put it at the end of the list. |
| fragClasspaths.addElement(fragClasspath); |
| } |
| |
| /** |
| * Returns a string of the symbolic name and version |
| * @return a string of the symbolic name and version |
| */ |
| protected String getBundleSymbolicName() { |
| return hostdata.getSymbolicName() + "_" + hostdata.getVersion(); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Returns the host BundleData for this classloader |
| * @return the host BundleData for this classloader |
| */ |
| public AbstractBundleData getHostData() { |
| return hostdata; |
| } |
| |
| /** |
| * Returns a list of FragmentClasspath objects for the currently attached fragments |
| * @return a list of FragmentClasspath objects for the currently attached fragments |
| */ |
| public FragmentClasspath[] getFragClasspaths() { |
| if (fragClasspaths == null) |
| return null; |
| return (FragmentClasspath[]) fragClasspaths.toArray(new FragmentClasspath[fragClasspaths.size()]); |
| } |
| |
| /** |
| * Gets a ClasspathEntry object for the specified ClassPath entry. |
| * @param cp The ClassPath entry to get the ClasspathEntry for. |
| * @param bundledata The BundleData that the ClassPath entry is for. |
| * @param domain The ProtectionDomain for the ClassPath entry. |
| * @return The ClasspathEntry object for the ClassPath entry. |
| */ |
| protected ClasspathEntry getClasspath(String cp, AbstractBundleData bundledata, ProtectionDomain domain) { |
| BundleFile bundlefile = null; |
| File file; |
| // check for internal library jars |
| if ((file = bundledata.getBaseBundleFile().getFile(cp)) != null) |
| bundlefile = createBundleFile(file, bundledata); |
| // check for intenral library directories in a bundle jar file |
| if (bundlefile == null && bundledata.getBaseBundleFile().containsDir(cp)) |
| bundlefile = new BundleFile.NestedDirBundleFile(bundledata.getBaseBundleFile(), cp); |
| // if in dev mode, try using the cp as an absolute path |
| if (bundlefile == null && DevClassPathHelper.inDevelopmentMode()) |
| return getExternalClassPath(cp, bundledata, domain); |
| if (bundlefile != null) |
| return createClassPathEntry(bundlefile, domain); |
| return null; |
| } |
| |
| /** |
| * Gets a ClasspathEntry object for the specified classpath entry which is external to the |
| * bundledata. |
| * @param cp The ClassPath entry to get the ClasspathEntry for. |
| * @param bundledata The BundleData that the ClassPath entry is for. |
| * @param domain The ProtectionDomain for the ClassPath entry. |
| * @return The ClasspathEntry object for the ClassPath entry. |
| */ |
| protected ClasspathEntry getExternalClassPath(String cp, AbstractBundleData bundledata, ProtectionDomain domain) { |
| File file = new File(cp); |
| if (!file.isAbsolute()) |
| return null; |
| BundleFile bundlefile = createBundleFile(file, bundledata); |
| if (bundlefile != null) |
| return createClassPathEntry(bundlefile, domain); |
| return null; |
| } |
| |
| /** |
| * Creates a BundleFile object for a classpath entry |
| * @param file the file object used to create a BundleFile |
| * @param bundledata the bundle data |
| * @return a BundleFile object for a classpath entry |
| */ |
| protected BundleFile createBundleFile(File file, AbstractBundleData bundledata) { |
| if (file == null || !file.exists()) |
| return null; |
| try { |
| return hostdata.getAdaptor().createBundleFile(file, bundledata); |
| } catch (IOException e) { |
| bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundledata.getBundle(), e); |
| } |
| return null; |
| } |
| |
| /** |
| * @see ClassLoader#findClass(java.lang.String) |
| */ |
| protected synchronized Class findClass(String name) throws ClassNotFoundException { |
| // must call findLoadedClass here even if it was called earlier, |
| // the findLoadedClass and defineClass calls must be atomic |
| Class result = findLoadedClass(name); |
| if (result != null) |
| return result; |
| for (int i = 0; i < classpathEntries.length; i++) { |
| if (classpathEntries[i] != null) { |
| result = findClassImpl(name, classpathEntries[i]); |
| if (result != null) |
| return result; |
| } |
| } |
| // look in fragments. |
| if (fragClasspaths != null) { |
| int size = fragClasspaths.size(); |
| for (int i = 0; i < size; i++) { |
| FragmentClasspath fragCP = (FragmentClasspath) fragClasspaths.elementAt(i); |
| for (int j = 0; j < fragCP.classpathEntries.length; j++) { |
| result = findClassImpl(name, fragCP.classpathEntries[j]); |
| if (result != null) |
| return result; |
| } |
| } |
| } |
| throw new ClassNotFoundException(name); |
| } |
| |
| /** |
| * Finds a class in the BundleFile. If a class is found then the class |
| * is defined using the ProtectionDomain bundledomain. |
| * @param name The name of the class to find. |
| * @param classpathEntry The ClasspathEntry to find the class in. |
| * @return The loaded class object or null if the class is not found. |
| */ |
| protected Class findClassImpl(String name, ClasspathEntry classpathEntry) { |
| if (Debug.DEBUG && Debug.DEBUG_LOADER) { |
| Debug.println("BundleClassLoader[" + hostdata + "].findClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ |
| } |
| |
| String filename = name.replace('.', '/').concat(".class"); //$NON-NLS-1$ |
| |
| BundleEntry entry = classpathEntry.getBundleFile().getEntry(filename); |
| |
| if (entry == null) { |
| return null; |
| } |
| |
| InputStream in; |
| try { |
| in = entry.getInputStream(); |
| } catch (IOException e) { |
| return null; |
| } |
| |
| int length = (int) entry.getSize(); |
| byte[] classbytes; |
| int bytesread = 0; |
| int readcount; |
| |
| if (Debug.DEBUG && Debug.DEBUG_LOADER) { |
| Debug.println(" about to read " + length + " bytes from " + filename); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| try { |
| try { |
| if (length > 0) { |
| classbytes = new byte[length]; |
| |
| readloop: for (; bytesread < length; bytesread += readcount) { |
| readcount = in.read(classbytes, bytesread, length - bytesread); |
| |
| if (readcount <= 0) /* if we didn't read anything */{ |
| break readloop; /* leave the loop */ |
| } |
| } |
| } else /* BundleEntry does not know its own length! */{ |
| length = buffersize; |
| classbytes = new byte[length]; |
| |
| readloop: while (true) { |
| for (; bytesread < length; bytesread += readcount) { |
| readcount = in.read(classbytes, bytesread, length - bytesread); |
| |
| if (readcount <= 0) /* if we didn't read anything */{ |
| break readloop; /* leave the loop */ |
| } |
| } |
| |
| byte[] oldbytes = classbytes; |
| length += buffersize; |
| classbytes = new byte[length]; |
| System.arraycopy(oldbytes, 0, classbytes, 0, bytesread); |
| } |
| } |
| } catch (IOException e) { |
| if (Debug.DEBUG && Debug.DEBUG_LOADER) { |
| Debug.println(" IOException reading " + filename + " from " + hostdata); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| return null; |
| } |
| } finally { |
| try { |
| in.close(); |
| } catch (IOException ee) { |
| // nothing to do here |
| } |
| } |
| |
| if (Debug.DEBUG && Debug.DEBUG_LOADER) { |
| Debug.println(" read " + bytesread + " bytes from " + filename); //$NON-NLS-1$ //$NON-NLS-2$ |
| Debug.println(" defining class " + name); //$NON-NLS-1$ |
| } |
| |
| try { |
| return (defineClass(name, classbytes, 0, bytesread, classpathEntry)); |
| } catch (Error e) { |
| if (Debug.DEBUG && Debug.DEBUG_LOADER) { |
| Debug.println(" error defining class " + name); //$NON-NLS-1$ |
| } |
| |
| throw e; |
| } |
| } |
| |
| /** |
| * Defines a class for this classloader |
| * @param name the name of the class |
| * @param classbytes the class bytes |
| * @param off the offset in the class bytes array |
| * @param len the legth of the class bytes |
| * @param classpathEntry the classpath entry used for the class |
| * @return a loaded Class object |
| * @throws ClassFormatError if the class has a format error |
| */ |
| protected Class defineClass(String name, byte[] classbytes, int off, int len, ClasspathEntry classpathEntry) throws ClassFormatError { |
| if (name != null && name.startsWith("java.")) { //$NON-NLS-1$ |
| // To work around the security issue that prevents any |
| // other classloader except for the bootstrap classloader |
| // from loading packages that start with java. |
| name = null; |
| } |
| return defineClass(name, classbytes, off, len, classpathEntry.getProtectionDomain()); |
| } |
| |
| /** |
| * @see ClassLoader#findResource(java.lang.String) |
| */ |
| protected URL findResource(String name) { |
| URL result = null; |
| for (int i = 0; i < classpathEntries.length; i++) { |
| if (classpathEntries[i] != null) { |
| result = findResourceImpl(name, classpathEntries[i].getBundleFile()); |
| if (result != null) |
| return result; |
| } |
| } |
| // look in fragments |
| if (fragClasspaths != null) { |
| int size = fragClasspaths.size(); |
| for (int i = 0; i < size; i++) { |
| FragmentClasspath fragCP = (FragmentClasspath) fragClasspaths.elementAt(i); |
| for (int j = 0; j < fragCP.classpathEntries.length; j++) { |
| result = findResourceImpl(name, fragCP.classpathEntries[j].getBundleFile()); |
| if (result != null) |
| return result; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Looks in the specified BundleFile for the resource. |
| * @param name The name of the resource to find. |
| * @param bundlefile The BundleFile to look in. |
| * @return A URL to the resource or null if the resource does not exist. |
| */ |
| protected URL findResourceImpl(String name, BundleFile bundlefile) { |
| return findResourceImpl(name, bundlefile, 0); |
| } |
| |
| /** |
| * Looks in the specified BundleFile for the resource. |
| * @param name The name of the resource to find. |
| * @param bundlefile The BundleFile to look in. |
| * @param index the index of the resource. |
| * @return A URL to the resource or null if the resource does not exist. |
| */ |
| protected URL findResourceImpl(String name, BundleFile bundlefile, int index) { |
| return bundlefile.getResourceURL(name, hostdata.getBundleID(), index); |
| } |
| |
| /** |
| * @see org.eclipse.osgi.framework.adaptor.BundleClassLoader#findLocalResources(String) |
| */ |
| public Enumeration findLocalResources(String resource) { |
| Vector resources = new Vector(6); // use a Vector instead of ArrayList because we need an enumeration |
| for (int i = 0; i < classpathEntries.length; i++) { |
| if (classpathEntries[i] != null) { |
| URL url = findResourceImpl(resource, classpathEntries[i].getBundleFile(), resources.size()); |
| if (url != null) |
| resources.addElement(url); |
| } |
| } |
| // look in fragments |
| if (fragClasspaths != null) { |
| int size = fragClasspaths.size(); |
| for (int i = 0; i < size; i++) { |
| FragmentClasspath fragCP = (FragmentClasspath) fragClasspaths.elementAt(i); |
| for (int j = 0; j < fragCP.classpathEntries.length; j++) { |
| URL url = findResourceImpl(resource, fragCP.classpathEntries[j].getBundleFile(), resources.size()); |
| if (url != null) |
| resources.addElement(url); |
| } |
| } |
| } |
| if (resources.size() > 0) |
| return resources.elements(); |
| return null; |
| } |
| |
| /** |
| * @see AbstractClassLoader#findLocalObject(String) |
| */ |
| public Object findLocalObject(String object) { |
| BundleEntry result = null; |
| for (int i = 0; i < classpathEntries.length; i++) { |
| if (classpathEntries[i] != null) { |
| result = findObjectImpl(object, classpathEntries[i].getBundleFile()); |
| if (result != null) { |
| return result; |
| } |
| } |
| } |
| // look in fragments |
| if (fragClasspaths != null) { |
| int size = fragClasspaths.size(); |
| for (int i = 0; i < size; i++) { |
| FragmentClasspath fragCP = (FragmentClasspath) fragClasspaths.elementAt(i); |
| for (int j = 0; j < fragCP.classpathEntries.length; j++) { |
| result = findObjectImpl(object, fragCP.classpathEntries[j].getBundleFile()); |
| if (result != null) { |
| return result; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @see AbstractClassLoader#findLocalObjects(String) |
| */ |
| public Enumeration findLocalObjects(String object) { |
| Vector objects = new Vector(6); // use a Vector instead of ArrayList because we need an enumeration |
| for (int i = 0; i < classpathEntries.length; i++) { |
| if (classpathEntries[i] != null) { |
| Object result = findObjectImpl(object, classpathEntries[i].getBundleFile()); |
| if (result != null) |
| objects.addElement(result); |
| } |
| } |
| // look in fragments |
| if (fragClasspaths != null) { |
| int size = fragClasspaths.size(); |
| for (int i = 0; i < size; i++) { |
| FragmentClasspath fragCP = (FragmentClasspath) fragClasspaths.elementAt(i); |
| for (int j = 0; j < fragCP.classpathEntries.length; j++) { |
| Object result = findObjectImpl(object, fragCP.classpathEntries[j].getBundleFile()); |
| if (result != null) |
| objects.addElement(result); |
| } |
| } |
| } |
| if (objects.size() > 0) |
| return objects.elements(); |
| return null; |
| } |
| |
| /** |
| * Looks in the specified BundleFile for the entry. |
| * @param object The name of the entry to find. |
| * @param bundleFile The BundleFile to look in. |
| * @return a bundle entry for the specified entry or <code>null</code> if the |
| * entry does not exist |
| */ |
| protected BundleEntry findObjectImpl(String object, BundleFile bundleFile) { |
| return bundleFile.getEntry(object); |
| } |
| |
| /** |
| * @see org.eclipse.osgi.framework.adaptor.BundleClassLoader#close() |
| */ |
| public void close() { |
| super.close(); |
| if (classpathEntries != null) { |
| for (int i = 0; i < classpathEntries.length; i++) { |
| if (classpathEntries[i] != null) { |
| try { |
| classpathEntries[i].getBundleFile().close(); |
| } catch (IOException e) { |
| hostdata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, hostdata.getBundle(), e); |
| } |
| } |
| } |
| } |
| if (fragClasspaths != null) { |
| int size = fragClasspaths.size(); |
| for (int i = 0; i < size; i++) { |
| FragmentClasspath fragCP = (FragmentClasspath) fragClasspaths.elementAt(i); |
| fragCP.close(); |
| } |
| } |
| } |
| |
| /** |
| * Builds the classpath entry objects for this classloader |
| * @param classpath a list of classpath entries to build |
| * @param bundledata the bundle data |
| * @param domain the ProtectionDomain for the classpath entry objects |
| * @return |
| */ |
| protected ClasspathEntry[] buildClasspath(String[] classpath, AbstractBundleData bundledata, ProtectionDomain domain) { |
| ArrayList result = new ArrayList(classpath.length); |
| // if in dev mode add the dev entries |
| addDefaultDevEntries(result, bundledata, domain); |
| // add the regular classpath entries. |
| for (int i = 0; i < classpath.length; i++) |
| findClassPathEntry(result, classpath[i], bundledata, domain); |
| return (ClasspathEntry[]) result.toArray(new ClasspathEntry[result.size()]); |
| } |
| |
| /** |
| * Adds the default development classpath entries |
| * @param result a list of current classpath entries. This list is modified by this method to add |
| * a new classpath entry. |
| * @param bundledata the bundle data |
| * @param domain the ProtectionDomain for the classpath entry |
| */ |
| protected void addDefaultDevEntries(ArrayList result, AbstractBundleData bundledata, ProtectionDomain domain) { |
| String[] devClassPath = !DevClassPathHelper.inDevelopmentMode() ? null : DevClassPathHelper.getDevClassPath(bundledata.getSymbolicName()); |
| if (devClassPath == null) |
| return; // not in dev mode return |
| for (int i = 0; i < devClassPath.length; i++) |
| findClassPathEntry(result, devClassPath[i], bundledata, domain); |
| } |
| |
| /** |
| * Finds a classpath entry for this classloader |
| * @param result a list of current classpath entries. This list is modified by this method to add |
| * a new classpath entry. |
| * @param entry the path to the entry to find |
| * @param bundledata the bundle data |
| * @param domain the ProtectionDomain for the classpath entry |
| */ |
| protected void findClassPathEntry(ArrayList result, String entry, AbstractBundleData bundledata, ProtectionDomain domain) { |
| if (!addClassPathEntry(result, entry, bundledata, domain)) { |
| String[] devCP = !DevClassPathHelper.inDevelopmentMode() ? null : DevClassPathHelper.getDevClassPath(bundledata.getSymbolicName()); |
| if (devCP == null || devCP.length == 0) { |
| BundleException be = new BundleException(NLS.bind(AdaptorMsg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, entry, bundledata.getLocation())); |
| bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.INFO, bundledata.getBundle(), be); |
| } |
| } |
| } |
| |
| /** |
| * Adds a classpath entry to this classloader |
| * @param result a list of current classpath entries. This list is modified by this method to add |
| * a new classpath entry. |
| * @param entry the path to the entry to add |
| * @param bundledata the bundle data |
| * @param domain the ProtectionDomain for the classpath entry |
| * @return true if a classpath entry was added to the result; false if the classpath entry could |
| * not be found |
| */ |
| protected boolean addClassPathEntry(ArrayList result, String entry, AbstractBundleData bundledata, ProtectionDomain domain) { |
| if (entry.equals(".")) { //$NON-NLS-1$ |
| result.add(createClassPathEntry(bundledata.getBaseBundleFile(), domain)); |
| return true; |
| } |
| Object element = getClasspath(entry, bundledata, domain); |
| if (element != null) { |
| result.add(element); |
| return true; |
| } |
| // need to check in fragments for the classpath entry. |
| // only check for fragments if the bundledata is the hostdata. |
| if (fragClasspaths != null && hostdata == bundledata) { |
| int size = fragClasspaths.size(); |
| for (int i = 0; i < size; i++) { |
| FragmentClasspath fragCP = (FragmentClasspath) fragClasspaths.elementAt(i); |
| element = getClasspath(entry, fragCP.bundledata, fragCP.domain); |
| if (element != null) { |
| result.add(element); |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Creates a ClasspathEntry from a BundleFile and ProtectionDomain. |
| * @param bundlefile the BundleFile. |
| * @param domain the ProtectionDomain |
| * @return the ClasspathEntry |
| */ |
| protected ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain domain) { |
| return new ClasspathEntry(bundlefile, domain); |
| } |
| |
| /** |
| * A data structure to hold information about a fragment classpath. |
| */ |
| protected class FragmentClasspath { |
| /** The ClasspathEntries of the fragments Bundle-Classpath */ |
| protected ClasspathEntry[] classpathEntries; |
| /** The BundleData of the fragment */ |
| protected AbstractBundleData bundledata; |
| /** The ProtectionDomain of the fragment */ |
| protected ProtectionDomain domain; |
| |
| protected FragmentClasspath(ClasspathEntry[] classpathEntries, AbstractBundleData bundledata, ProtectionDomain domain) { |
| this.classpathEntries = classpathEntries; |
| this.bundledata = bundledata; |
| this.domain = domain; |
| } |
| |
| protected void close() { |
| for (int i = 0; i < classpathEntries.length; i++) { |
| try { |
| classpathEntries[i].getBundleFile().close(); |
| } catch (IOException e) { |
| bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundledata.getBundle(), e); |
| } |
| } |
| } |
| |
| public AbstractBundleData getBundleData() { |
| return bundledata; |
| } |
| } |
| |
| /** |
| * A data structure to hold information about a classpath entry. |
| */ |
| protected class ClasspathEntry { |
| protected BundleFile bundlefile; |
| protected ProtectionDomain domain; |
| |
| protected ClasspathEntry(BundleFile bundlefile, ProtectionDomain domain) { |
| this.bundlefile = bundlefile; |
| this.domain = createProtectionDomain(domain); |
| } |
| |
| public BundleFile getBundleFile() { |
| return bundlefile; |
| } |
| |
| public ProtectionDomain getProtectionDomain() { |
| return domain; |
| } |
| |
| /* |
| * Creates a ProtectionDomain using the permissions of the specified baseDomain |
| */ |
| protected ProtectionDomain createProtectionDomain(ProtectionDomain baseDomain) { |
| // create a protection domain which knows about the codesource for this classpath entry (bug 89904) |
| try { |
| // use the permissions supplied by the domain passed in from the framework |
| PermissionCollection permissions; |
| if (baseDomain != null) |
| permissions = baseDomain.getPermissions(); |
| else |
| // no domain specified. Better use a collection that has all permissions |
| // this is done just incase someone sets the security manager later |
| permissions = ALLPERMISSIONS; |
| return new ClasspathDomain(bundlefile.getBaseFile().toURL(), permissions); |
| } catch (MalformedURLException e) { |
| // Failed to create our own domain; just return the baseDomain |
| return baseDomain; |
| } |
| } |
| } |
| |
| /* |
| * Very simple protection domain that uses a URL to create a CodeSource for a ProtectionDomain |
| */ |
| protected class ClasspathDomain extends ProtectionDomain { |
| public ClasspathDomain(URL codeLocation, PermissionCollection permissions) { |
| super(new CodeSource(codeLocation, (Certificate[]) null), permissions); |
| } |
| } |
| } |