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 ();
 | 
						|
}
 |