mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			225 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Copyright (C) 2001, 2003, 2004, 2005  Free Software Foundation
 | |
| 
 | |
|    This file is part of libgcj.
 | |
| 
 | |
| This software is copyrighted work licensed under the terms of the
 | |
| Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | |
| details.  */
 | |
| 
 | |
| package gnu.gcj.runtime;
 | |
| import java.lang.ref.WeakReference;
 | |
| import java.net.URL;
 | |
| import java.net.MalformedURLException;
 | |
| import java.util.HashMap;
 | |
| import java.security.*;
 | |
| import gnu.gcj.Core;
 | |
| import java.util.Set;
 | |
| import java.util.Iterator;
 | |
| import java.util.HashSet;
 | |
| import java.util.HashMap;
 | |
| import java.nio.channels.FileChannel;
 | |
| import java.io.*;
 | |
| 
 | |
| public class SharedLibHelper
 | |
| {
 | |
|   /** Load a shared library, and associate a ClassLoader with it.
 | |
|    * @param libname named of shared library (passed to dlopen)
 | |
|    * @param parent the parent ClassLoader
 | |
|    * @parem flags passed to dlopen
 | |
|    */
 | |
|   SharedLibHelper(String libname, ClassLoader parent, CodeSource source,
 | |
| 		  ProtectionDomain domain, int flags)
 | |
|   {
 | |
|     // FIXME: ask security manager first.
 | |
|     loader = parent;
 | |
|     baseName = libname;
 | |
|     if (domain == null)
 | |
|       domain = new ProtectionDomain(source,
 | |
| 				    Policy.getPolicy().getPermissions(source));
 | |
|     this.domain = domain;
 | |
|     this.flags = flags;
 | |
|   }
 | |
| 
 | |
|   public static SharedLibHelper findHelper (String libname)
 | |
|   {
 | |
|     synchronized (map)
 | |
|       {
 | |
| 	Set s = (Set)map.get(libname);
 | |
| 	if (s == null)
 | |
| 	  return null;
 | |
| 	for (Iterator i=s.iterator(); i.hasNext();)
 | |
| 	  {
 | |
| 	    WeakReference ref = (WeakReference)i.next();
 | |
| 	    if (ref != null)
 | |
| 	      return (SharedLibHelper) ref.get();
 | |
| 	  }
 | |
| 	return null;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   static void copyFile (File in, File out) throws IOException 
 | |
|   {
 | |
|     FileChannel source = new FileInputStream(in).getChannel();
 | |
|     FileChannel destination = new FileOutputStream(out).getChannel();
 | |
|     source.transferTo(0, source.size(), destination);
 | |
|     source.close();
 | |
|     destination.close();
 | |
|   }
 | |
| 
 | |
|   public static SharedLibHelper findHelper (ClassLoader loader, String libname,
 | |
| 					    CodeSource source,
 | |
| 					    boolean tryParents)
 | |
|   {
 | |
|     return findHelper (loader, libname, source, null, tryParents);
 | |
|   }
 | |
| 
 | |
|   public static SharedLibHelper findHelper (ClassLoader loader, String libname,
 | |
| 					    CodeSource source,
 | |
| 					    ProtectionDomain domain, 
 | |
| 					    boolean tryParents)
 | |
|   {
 | |
|     synchronized (map)
 | |
|       {
 | |
| 	SharedLibHelper result;
 | |
| 	Set s = (Set)map.get(libname);
 | |
| 	if (s == null)
 | |
| 	  {
 | |
| 	    s = new HashSet();
 | |
| 	    map.put(libname, s);
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    for (Iterator i=s.iterator(); i.hasNext();)
 | |
| 	      {
 | |
| 		WeakReference ref = (WeakReference)i.next();
 | |
| 		if (ref != null)
 | |
| 		  {
 | |
| 		    result = (SharedLibHelper) ref.get();
 | |
| 		    if (result != null)
 | |
| 		      {			
 | |
| 			// A match succeeds if the library is already
 | |
| 			// loaded by LOADER or any of its ancestors.
 | |
| 			ClassLoader l = loader;
 | |
| 			do
 | |
| 			  {
 | |
| 			    if (result.loader == l)
 | |
| 			      return result;
 | |
| 			    l = l.getParent();
 | |
| 			  }
 | |
| 			while (tryParents && l != null);
 | |
| 		      }
 | |
| 		  }
 | |
| 	      }
 | |
| 
 | |
| 	    // Oh dear.  We've already mapped this shared library, but
 | |
| 	    // with a different class loader.  We need to copy it.
 | |
| 	    try
 | |
| 	      {
 | |
| 		File copy 
 | |
| 		  = File.createTempFile(new File(libname).getName(), 
 | |
| 					".so", new File ("/tmp"));
 | |
| 		File src = new File(libname);
 | |
| 		copyFile (src, copy);
 | |
| 		copy.deleteOnExit();
 | |
| 		libname = copy.getPath();
 | |
| 	      }
 | |
| 	    catch (IOException e)
 | |
| 	      {
 | |
| 		return null;
 | |
| 	      }
 | |
| 	  }
 | |
| 	result = new SharedLibHelper(libname, loader, source, domain, 0);
 | |
| 	s.add(new WeakReference(result));
 | |
| 	return result;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   public native void finalize ();
 | |
| 
 | |
|   public Class findClass(String name)
 | |
|   {
 | |
|     ensureInit();
 | |
|     Class result = (Class) classMap.get(name);
 | |
|     if (result != null)
 | |
|       {
 | |
| 	// We never want to return a class without its supers linked.
 | |
| 	// It isn't clear from the spec, but this is what other
 | |
| 	// implementations do in practice.
 | |
| 	ensureSupersLinked(result);
 | |
|       }
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   public URL findResource (String name)
 | |
|   {
 | |
|     ensureInit();
 | |
|     if (! hasResource(name))
 | |
|       return null;
 | |
|     try
 | |
|       {
 | |
| 	return new URL("gcjlib", "", -1, baseName + "!/" + name);
 | |
|       }
 | |
|     catch (MalformedURLException _)
 | |
|       {
 | |
|       }
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   public native Core findCore (String name);
 | |
| 
 | |
|   void ensureInit()
 | |
|   {
 | |
|     synchronized (classMap)
 | |
|       {
 | |
| 	if (initialized)
 | |
| 	  return;
 | |
| 	init();
 | |
| 	initialized = true;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   native boolean hasResource(String name);
 | |
|   native void init();
 | |
|   native void ensureSupersLinked(Class k);
 | |
| 
 | |
|   public String toString ()
 | |
|   {
 | |
|     return "shared object " + baseName;
 | |
|   }
 | |
| 
 | |
|   /** Called during dlopen's processing of the init section. */
 | |
|   void registerClass(String name, Class cls)
 | |
|   {
 | |
|     classMap.put(name, cls);
 | |
|   }
 | |
| 
 | |
|   /** The handle returned by dlopen. */
 | |
|   gnu.gcj.RawData handler;
 | |
| 
 | |
|   /** Holds a _Jv_core_chain for the loader.  */
 | |
|   gnu.gcj.RawData core_chain;
 | |
| 
 | |
|   /** Map classnames to Classes. */
 | |
|   HashMap classMap = new HashMap(20);
 | |
| 
 | |
|   /** Class loader we're helping.  */
 | |
|   ClassLoader loader;
 | |
| 
 | |
|   /** Name of base file.  */
 | |
|   String baseName;
 | |
| 
 | |
|   /** Protection domain for loaded classes.  */
 | |
|   ProtectionDomain domain;
 | |
| 
 | |
|   /** Flags to pass to dlopen.  FIXME: platform dependent.
 | |
|       0 is always "sensible" (defined by us).  */
 | |
|   int flags;
 | |
| 
 | |
|   /** True if we've been initialized.  */
 | |
|   boolean initialized = false;
 | |
| 
 | |
|   /** Map shared library names to a helper object.  This uses weak
 | |
|       references in the values so we don't prevent collection.  */
 | |
|   static HashMap map = new HashMap ();
 | |
| }
 |