2002-12-18 19:00:25 +03:00
/ *
2006-01-02 11:15:43 +03:00
Copyright ( C ) 2002 , 2003 , 2004 , 2005 , 2006 Jeroen Frijters
2002-12-18 19:00:25 +03:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
Jeroen Frijters
jeroen @frijters . net
* /
using System ;
using System.Reflection ;
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
using System.Reflection.Emit ;
#endif
2002-12-18 19:00:25 +03:00
using System.IO ;
using System.Collections ;
using System.Diagnostics ;
2004-09-09 15:17:55 +04:00
using IKVM.Attributes ;
using IKVM.Runtime ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
namespace IKVM.Internal
2002-12-18 19:00:25 +03:00
{
2006-07-06 17:53:51 +04:00
abstract class TypeWrapperFactory
{
#if ! COMPACT_FRAMEWORK
internal abstract ModuleBuilder ModuleBuilder { get ; }
#endif
internal abstract TypeWrapper DefineClassImpl ( Hashtable types , ClassFile f , object protectionDomain ) ;
}
class ClassLoaderWrapper
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
private static readonly object wrapperLock = new object ( ) ;
2005-09-06 12:06:04 +04:00
private static readonly Hashtable typeToTypeWrapper = Hashtable . Synchronized ( new Hashtable ( ) ) ;
2005-06-01 13:49:30 +04:00
private static ClassLoaderWrapper bootstrapClassLoader ;
2006-05-15 13:08:01 +04:00
#if WHIDBEY & & ! STATIC_COMPILER
private static readonly Hashtable reflectionOnlyClassLoaders = new Hashtable ( ) ;
2006-04-10 13:09:09 +04:00
#endif
2006-07-26 14:33:52 +04:00
private static ArrayList genericClassLoaders ;
2006-06-28 12:07:29 +04:00
private readonly object javaClassLoader ;
2006-02-22 17:44:07 +03:00
protected Hashtable types = new Hashtable ( ) ;
2005-06-01 13:49:30 +04:00
private ArrayList nativeLibraries ;
2006-07-06 17:53:51 +04:00
private TypeWrapperFactory factory ;
2005-06-01 13:49:30 +04:00
private static Hashtable remappedTypes = new Hashtable ( ) ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader
internal static void SetBootstrapClassLoader ( ClassLoaderWrapper bootstrapClassLoader )
{
Debug . Assert ( ClassLoaderWrapper . bootstrapClassLoader = = null ) ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
ClassLoaderWrapper . bootstrapClassLoader = bootstrapClassLoader ;
}
2004-03-08 18:18:47 +03:00
2005-06-01 13:49:30 +04:00
static ClassLoaderWrapper ( )
{
typeToTypeWrapper [ PrimitiveTypeWrapper . BOOLEAN . TypeAsTBD ] = PrimitiveTypeWrapper . BOOLEAN ;
typeToTypeWrapper [ PrimitiveTypeWrapper . BYTE . TypeAsTBD ] = PrimitiveTypeWrapper . BYTE ;
typeToTypeWrapper [ PrimitiveTypeWrapper . CHAR . TypeAsTBD ] = PrimitiveTypeWrapper . CHAR ;
typeToTypeWrapper [ PrimitiveTypeWrapper . DOUBLE . TypeAsTBD ] = PrimitiveTypeWrapper . DOUBLE ;
typeToTypeWrapper [ PrimitiveTypeWrapper . FLOAT . TypeAsTBD ] = PrimitiveTypeWrapper . FLOAT ;
typeToTypeWrapper [ PrimitiveTypeWrapper . INT . TypeAsTBD ] = PrimitiveTypeWrapper . INT ;
typeToTypeWrapper [ PrimitiveTypeWrapper . LONG . TypeAsTBD ] = PrimitiveTypeWrapper . LONG ;
typeToTypeWrapper [ PrimitiveTypeWrapper . SHORT . TypeAsTBD ] = PrimitiveTypeWrapper . SHORT ;
typeToTypeWrapper [ PrimitiveTypeWrapper . VOID . TypeAsTBD ] = PrimitiveTypeWrapper . VOID ;
LoadRemappedTypes ( ) ;
}
2004-12-21 17:59:29 +03:00
2005-06-01 13:49:30 +04:00
internal static void LoadRemappedTypes ( )
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
// if we're compiling the core, coreAssembly will be null
Assembly coreAssembly = JVM . CoreAssembly ;
if ( coreAssembly ! = null )
2004-03-08 18:18:47 +03:00
{
2005-12-19 18:12:49 +03:00
Tracer . Info ( Tracer . Runtime , "Core assembly: {0}" , coreAssembly . Location ) ;
2005-12-07 12:06:32 +03:00
RemappedClassAttribute [ ] remapped = AttributeHelper . GetRemappedClasses ( coreAssembly ) ;
2005-06-01 13:49:30 +04:00
if ( remapped . Length > 0 )
{
foreach ( RemappedClassAttribute r in remapped )
{
Tracer . Info ( Tracer . Runtime , "Remapping type {0} to {1}" , r . RemappedType , r . Name ) ;
remappedTypes . Add ( r . RemappedType , r . Name ) ;
}
}
else
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
JVM . CriticalFailure ( "Failed to find core classes in core library" , null ) ;
2004-03-08 18:18:47 +03:00
}
}
2002-12-18 19:00:25 +03:00
}
2004-03-08 18:18:47 +03:00
2006-06-26 13:04:03 +04:00
internal static int GetLoadedClassCount ( )
{
return typeToTypeWrapper . Count ;
}
2005-06-01 13:49:30 +04:00
internal static bool IsCoreAssemblyType ( Type type )
{
2005-12-07 12:06:32 +03:00
return type . Assembly = = JVM . CoreAssembly ;
2005-06-01 13:49:30 +04:00
}
2004-10-04 23:30:53 +04:00
2005-06-01 13:49:30 +04:00
internal ClassLoaderWrapper ( object javaClassLoader )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
this . javaClassLoader = javaClassLoader ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal static bool IsRemappedType ( Type type )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return remappedTypes . ContainsKey ( type ) ;
2004-08-17 13:05:21 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal void SetRemappedType ( Type type , TypeWrapper tw )
{
Debug . Assert ( ! types . ContainsKey ( tw . Name ) ) ;
types . Add ( tw . Name , tw ) ;
Debug . Assert ( ! typeToTypeWrapper . ContainsKey ( type ) ) ;
typeToTypeWrapper . Add ( type , tw ) ;
remappedTypes . Add ( type , type ) ;
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// HACK return the TypeWrapper if it is already loaded
2005-07-25 18:34:22 +04:00
// (this exists solely for DynamicTypeWrapper.SetupGhosts and VMClassLoader.findLoadedClass)
2005-06-01 13:49:30 +04:00
internal TypeWrapper GetLoadedClass ( string name )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( types . SyncRoot )
{
return ( TypeWrapper ) types [ name ] ;
}
2004-08-17 13:05:21 +04:00
}
2003-12-20 01:19:18 +03:00
2006-07-26 13:03:44 +04:00
internal TypeWrapper RegisterInitiatingLoader ( TypeWrapper tw )
2005-07-27 19:57:55 +04:00
{
2006-07-11 15:34:44 +04:00
Debug . Assert ( tw ! = null ) ;
Debug . Assert ( ! tw . IsUnloadable ) ;
Debug . Assert ( ! tw . IsPrimitive ) ;
2005-07-27 19:57:55 +04:00
lock ( types . SyncRoot )
{
object existing = types [ tw . Name ] ;
if ( existing ! = tw )
{
if ( existing ! = null )
{
2006-07-10 18:40:31 +04:00
// another thread beat us to it, discard the new TypeWrapper and
// return the previous one
return ( TypeWrapper ) existing ;
2005-07-27 19:57:55 +04:00
}
// NOTE if types.ContainsKey(tw.Name) is true (i.e. the value is null),
// we currently have a DefineClass in progress on another thread and we've
// beaten that thread to the punch by loading the class from a parent class
// loader instead. This is ok as DefineClass will throw a LinkageError when
// it is done.
types [ tw . Name ] = tw ;
}
}
return tw ;
}
2006-07-06 17:53:51 +04:00
internal TypeWrapper DefineClass ( ClassFile f , object protectionDomain )
{
string dotnetAssembly = f . IKVMAssemblyAttribute ;
if ( dotnetAssembly ! = null )
{
// The sole purpose of the stub class is to let us load the assembly that the class lives in,
// once we've done that, all types in it become visible.
Assembly asm ;
try
{
#if WHIDBEY & & STATIC_COMPILER
asm = Assembly . ReflectionOnlyLoad ( dotnetAssembly ) ;
#else
asm = Assembly . Load ( dotnetAssembly ) ;
#endif
}
catch ( Exception x )
{
throw new NoClassDefFoundError ( f . Name + " (" + x . Message + ")" ) ;
}
TypeWrapper tw = ClassLoaderWrapper . GetAssemblyClassLoader ( asm ) . LoadClassByDottedNameFast ( f . Name ) ;
if ( tw = = null )
{
throw new NoClassDefFoundError ( f . Name + " (type not found in " + asm . FullName + ")" ) ;
}
if ( tw . Assembly ! = asm )
{
throw new NoClassDefFoundError ( f . Name + " (assembly mismatch)" ) ;
}
return RegisterInitiatingLoader ( tw ) ;
}
2006-07-11 15:34:44 +04:00
lock ( this )
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
if ( factory = = null )
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
factory = CreateTypeWrapperFactory ( ) ;
2006-07-06 17:53:51 +04:00
}
}
2006-07-11 15:34:44 +04:00
lock ( factory )
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
lock ( types . SyncRoot )
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
if ( types . ContainsKey ( f . Name ) )
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
throw new LinkageError ( "duplicate class definition: " + f . Name ) ;
2006-07-06 17:53:51 +04:00
}
2006-07-11 15:34:44 +04:00
// mark the type as "loading in progress", so that we can detect circular dependencies.
types . Add ( f . Name , null ) ;
2006-07-06 17:53:51 +04:00
}
2006-07-11 15:34:44 +04:00
try
{
return factory . DefineClassImpl ( types , f , protectionDomain ) ;
}
catch
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
lock ( types . SyncRoot )
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
if ( types [ f . Name ] = = null )
{
// if loading the class fails, we remove the indicator that we're busy loading the class,
// because otherwise we get a ClassCircularityError if we try to load the class again.
types . Remove ( f . Name ) ;
}
2006-07-06 17:53:51 +04:00
}
2006-07-11 15:34:44 +04:00
throw ;
2006-07-06 17:53:51 +04:00
}
}
}
2006-03-11 21:35:29 +03:00
2006-07-06 17:53:51 +04:00
protected virtual TypeWrapperFactory CreateTypeWrapperFactory ( )
2003-06-10 17:28:47 +04:00
{
2006-07-06 17:53:51 +04:00
#if COMPACT_FRAMEWORK
throw new NoClassDefFoundError ( "Class loading is not supported on the Compact Framework" ) ;
#else
return new DynamicClassLoader ( this ) ;
#endif
}
#if ! COMPACT_FRAMEWORK
internal virtual ModuleBuilder ModuleBuilder
{
get
2006-03-11 21:35:29 +03:00
{
2006-07-06 17:53:51 +04:00
lock ( this )
2006-03-11 21:35:29 +03:00
{
2006-07-06 17:53:51 +04:00
if ( factory = = null )
{
factory = CreateTypeWrapperFactory ( ) ;
}
2006-03-11 21:35:29 +03:00
}
2006-07-06 17:53:51 +04:00
return factory . ModuleBuilder ;
2006-03-11 21:35:29 +03:00
}
2006-02-22 17:44:07 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2003-06-10 17:28:47 +04:00
2005-06-01 13:49:30 +04:00
internal TypeWrapper LoadClassByDottedName ( string name )
2003-03-17 17:02:46 +03:00
{
2006-07-11 15:34:44 +04:00
TypeWrapper type = LoadClassByDottedNameFastImpl ( name , true ) ;
2005-06-01 13:49:30 +04:00
if ( type ! = null )
{
2006-07-11 15:34:44 +04:00
return RegisterInitiatingLoader ( type ) ;
2005-06-01 13:49:30 +04:00
}
throw new ClassNotFoundException ( name ) ;
2003-03-17 17:02:46 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper LoadClassByDottedNameFast ( string name )
2005-08-25 11:46:57 +04:00
{
2006-07-11 15:34:44 +04:00
TypeWrapper type = LoadClassByDottedNameFastImpl ( name , false ) ;
if ( type ! = null )
{
return RegisterInitiatingLoader ( type ) ;
}
return null ;
2005-08-25 11:46:57 +04:00
}
2006-07-10 18:40:31 +04:00
private TypeWrapper LoadClassByDottedNameFastImpl ( string name , bool throwClassNotFoundException )
2003-02-15 12:20:26 +03:00
{
2005-06-01 13:49:30 +04:00
// .NET 1.1 has a limit of 1024 characters for type names
2006-05-15 13:08:01 +04:00
if ( name . Length > = 1024 | | name . Length = = 0 )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return null ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
Profiler . Enter ( "LoadClassByDottedName" ) ;
try
2002-12-18 19:00:25 +03:00
{
2006-07-11 15:34:44 +04:00
bool defineInProgress ;
2005-06-01 13:49:30 +04:00
TypeWrapper type ;
lock ( types . SyncRoot )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
type = ( TypeWrapper ) types [ name ] ;
2006-07-11 15:34:44 +04:00
defineInProgress = ( type = = null & & types . ContainsKey ( name ) ) ;
2004-12-03 10:57:15 +03:00
}
2005-06-01 13:49:30 +04:00
if ( type ! = null )
2004-12-03 10:57:15 +03:00
{
2005-06-01 13:49:30 +04:00
return type ;
2004-12-03 10:57:15 +03:00
}
2006-07-11 15:34:44 +04:00
if ( defineInProgress & & factory ! = null )
2004-12-03 10:57:15 +03:00
{
2006-07-11 15:34:44 +04:00
// DefineClass synchronizes on factory, so if we can obtain that
// lock it either means that the DefineClass has finished or
// that we're on the same thread. To distinguish between
// the two, we check the types hashtable again and if it still
// contains the null entry we're on the same thread and should throw
// the ClassCircularityError.
lock ( factory )
2003-08-26 15:24:17 +04:00
{
2006-07-11 15:34:44 +04:00
lock ( types . SyncRoot )
2006-07-10 13:37:06 +04:00
{
2006-07-11 15:34:44 +04:00
if ( types [ name ] = = null & & types . ContainsKey ( name ) )
{
// NOTE this can also happen if we (incorrectly) trigger a load of this class during
// the loading of the base class, so we print a trace message here.
Tracer . Error ( Tracer . ClassLoading , "**** ClassCircularityError: {0} ****" , name ) ;
throw new ClassCircularityError ( name ) ;
}
2006-07-10 13:37:06 +04:00
}
2003-08-26 15:24:17 +04:00
}
2006-07-11 15:34:44 +04:00
}
if ( name . Length > 1 & & name [ 0 ] = = '[' )
{
return LoadArrayClass ( name ) ;
2005-06-01 13:49:30 +04:00
}
2006-07-26 11:57:18 +04:00
if ( name . EndsWith ( "_$$$$_" ) & & name . IndexOf ( "_$$$_" ) > 0 )
{
TypeWrapper tw = LoadGenericClass ( name ) ;
if ( tw ! = null )
{
return tw ;
}
}
2006-07-26 13:03:44 +04:00
// for manufactured types, we load the declaring outer type (the real one) and
// let that generated the manufactured nested classes
TypeWrapper outer = null ;
if ( name . EndsWith ( DotNetTypeWrapper . DelegateInterfaceSuffix ) )
{
outer = LoadClassByDottedNameFastImpl ( name . Substring ( 0 , name . Length - DotNetTypeWrapper . DelegateInterfaceSuffix . Length ) , false ) ;
}
else if ( name . EndsWith ( DotNetTypeWrapper . AttributeAnnotationSuffix ) )
{
outer = LoadClassByDottedNameFastImpl ( name . Substring ( 0 , name . Length - DotNetTypeWrapper . AttributeAnnotationSuffix . Length ) , false ) ;
}
if ( outer ! = null )
{
foreach ( TypeWrapper tw in outer . InnerClasses )
{
if ( tw . Name = = name )
{
return tw ;
}
}
}
2006-07-10 18:40:31 +04:00
return LoadClassImpl ( name , throwClassNotFoundException ) ;
2006-07-10 13:37:06 +04:00
}
finally
{
Profiler . Leave ( "LoadClassByDottedName" ) ;
}
}
2006-07-11 15:34:44 +04:00
private TypeWrapper LoadArrayClass ( string name )
{
int dims = 1 ;
while ( name [ dims ] = = '[' )
{
dims + + ;
if ( dims = = name . Length )
{
// malformed class name
return null ;
}
}
if ( name [ dims ] = = 'L' )
{
if ( ! name . EndsWith ( ";" ) | | name . Length < = dims + 2 | | name [ dims + 1 ] = = '[' )
{
// malformed class name
return null ;
}
string elemClass = name . Substring ( dims + 1 , name . Length - dims - 2 ) ;
// NOTE it's important that we're registered as the initiating loader
// for the element type here
TypeWrapper type = LoadClassByDottedNameFast ( elemClass ) ;
if ( type ! = null )
{
type = type . GetClassLoader ( ) . CreateArrayType ( name , type , dims ) ;
}
return type ;
}
if ( name . Length ! = dims + 1 )
{
// malformed class name
return null ;
}
switch ( name [ dims ] )
{
case 'B' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . BYTE , dims ) ;
case 'C' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . CHAR , dims ) ;
case 'D' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . DOUBLE , dims ) ;
case 'F' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . FLOAT , dims ) ;
case 'I' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . INT , dims ) ;
case 'J' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . LONG , dims ) ;
case 'S' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . SHORT , dims ) ;
case 'Z' :
return GetBootstrapClassLoader ( ) . CreateArrayType ( name , PrimitiveTypeWrapper . BOOLEAN , dims ) ;
default :
return null ;
}
}
2006-07-21 14:18:13 +04:00
private TypeWrapper LoadGenericClass ( string name )
{
// generic class name grammar:
/ /
2006-07-26 11:57:18 +04:00
// mangled(open_generic_type_name) "_$$$_" M(parameter_class_name) ( "_$$_" M(parameter_class_name) )* "_$$$$_"
/ /
// mangled() is the normal name mangling algorithm
// M() is a replacement of "__" with "$$005F$$005F" followed by a replace of "." with "__"
/ /
2006-07-21 14:18:13 +04:00
int pos = name . IndexOf ( "_$$$_" ) ;
if ( pos < = 0 )
{
return null ;
}
Type type = GetBootstrapClassLoader ( ) . GetType ( DotNetTypeWrapper . DemangleTypeName ( name . Substring ( 0 , pos ) ) ) ;
2006-07-26 11:57:18 +04:00
if ( type = = null | | ! Whidbey . IsGenericTypeDefinition ( type ) )
2006-07-21 14:18:13 +04:00
{
return null ;
}
ArrayList typeParamNames = new ArrayList ( ) ;
pos + = 5 ;
int start = pos ;
int nest = 0 ;
for ( ; ; )
{
pos = name . IndexOf ( "_$$" , pos ) ;
if ( pos = = - 1 )
{
return null ;
}
if ( name . IndexOf ( "_$$_" , pos , 4 ) = = pos )
{
if ( nest = = 0 )
{
typeParamNames . Add ( name . Substring ( start , pos - start ) ) ;
start = pos + 4 ;
}
pos + = 4 ;
}
else if ( name . IndexOf ( "_$$$_" , pos , 5 ) = = pos )
{
nest + + ;
pos + = 5 ;
}
else if ( name . IndexOf ( "_$$$$_" , pos , 6 ) = = pos )
{
if ( nest = = 0 )
{
if ( pos + 6 ! = name . Length )
{
return null ;
}
typeParamNames . Add ( name . Substring ( start , pos - start ) ) ;
break ;
}
nest - - ;
pos + = 6 ;
}
else
{
pos + = 3 ;
}
}
Type [ ] typeArguments = new Type [ typeParamNames . Count ] ;
for ( int i = 0 ; i < typeArguments . Length ; i + + )
{
2006-07-26 11:57:18 +04:00
string s = ( string ) typeParamNames [ i ] ;
s = s . Replace ( "__" , "." ) ;
s = s . Replace ( "$$005F$$005F" , "__" ) ;
int dims = 0 ;
while ( s . Length > dims & & s [ dims ] = = 'A' )
{
dims + + ;
}
if ( s . Length = = dims )
{
return null ;
}
TypeWrapper tw = null ;
switch ( s [ dims ] )
{
case 'L' :
tw = LoadClassByDottedNameFast ( s . Substring ( dims + 1 ) ) ;
break ;
case 'Z' :
tw = PrimitiveTypeWrapper . BOOLEAN ;
break ;
case 'B' :
tw = PrimitiveTypeWrapper . BYTE ;
break ;
case 'S' :
tw = PrimitiveTypeWrapper . SHORT ;
break ;
case 'C' :
tw = PrimitiveTypeWrapper . CHAR ;
break ;
case 'I' :
tw = PrimitiveTypeWrapper . INT ;
break ;
case 'F' :
tw = PrimitiveTypeWrapper . FLOAT ;
break ;
case 'J' :
tw = PrimitiveTypeWrapper . LONG ;
break ;
case 'D' :
tw = PrimitiveTypeWrapper . DOUBLE ;
break ;
}
2006-07-21 14:18:13 +04:00
if ( tw = = null )
{
return null ;
}
2006-07-26 11:57:18 +04:00
if ( dims > 0 )
{
tw = tw . MakeArrayType ( dims ) ;
}
2006-07-21 14:18:13 +04:00
typeArguments [ i ] = tw . TypeAsSignatureType ;
}
// TODO consider catching the ArgumentException that MakeGenericType can throw
2006-07-26 11:57:18 +04:00
return GetWrapperFromType ( Whidbey . MakeGenericType ( type , typeArguments ) ) ;
2006-07-21 14:18:13 +04:00
}
2006-07-10 13:37:06 +04:00
protected virtual TypeWrapper LoadClassImpl ( string name , bool throwClassNotFoundException )
{
#if ! STATIC_COMPILER
// NOTE just like Java does (I think), we take the classloader lock before calling the loadClass method
lock ( javaClassLoader )
{
Profiler . Enter ( "ClassLoader.loadClass" ) ;
TypeWrapper type ;
try
{
type = ( TypeWrapper ) JVM . Library . loadClass ( javaClassLoader , name ) ;
}
catch ( Exception x )
2005-06-01 13:49:30 +04:00
{
2006-07-10 13:37:06 +04:00
if ( ! throwClassNotFoundException
& & LoadClassCritical ( "java.lang.ClassNotFoundException" ) . TypeAsBaseType . IsInstanceOfType ( x ) )
2005-06-01 13:49:30 +04:00
{
return null ;
2003-08-21 14:06:34 +04:00
}
2006-07-10 13:37:06 +04:00
throw new ClassLoadingException ( IKVM . Runtime . Util . MapException ( x ) ) ;
2002-12-29 19:27:00 +03:00
}
2006-07-10 13:37:06 +04:00
finally
2006-03-11 21:35:29 +03:00
{
2006-07-10 13:37:06 +04:00
Profiler . Leave ( "ClassLoader.loadClass" ) ;
2002-12-29 19:27:00 +03:00
}
2006-07-10 18:40:31 +04:00
return type ;
2006-07-10 13:37:06 +04:00
}
2006-04-10 13:09:09 +04:00
#else
2006-07-10 13:37:06 +04:00
return null ;
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
}
2006-07-10 13:37:06 +04:00
internal TypeWrapper GetWrapperFromBootstrapType ( Type type )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
//Tracer.Info(Tracer.Runtime, "GetWrapperFromBootstrapType: {0}", type.FullName);
Debug . Assert ( ! type . IsArray , "!type.IsArray" , type . FullName ) ;
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! ( type . Assembly is AssemblyBuilder ) , "!(type.Assembly is AssemblyBuilder)" , type . FullName ) ;
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
// only the bootstrap classloader can own compiled types
Debug . Assert ( this = = GetBootstrapClassLoader ( ) , "this == GetBootstrapClassLoader()" , type . FullName ) ;
2005-12-07 12:06:32 +03:00
bool javaType = AttributeHelper . IsJavaModule ( type . Module ) ;
2005-06-01 13:49:30 +04:00
string name ;
2005-01-03 11:26:21 +03:00
if ( javaType )
{
2005-06-01 13:49:30 +04:00
name = CompiledTypeWrapper . GetName ( type ) ;
2005-01-03 11:26:21 +03:00
}
else
{
2005-06-01 13:49:30 +04:00
name = DotNetTypeWrapper . GetName ( type ) ;
2006-07-26 11:57:18 +04:00
if ( name = = null )
{
return null ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper wrapper ;
2004-08-17 13:05:21 +04:00
lock ( types . SyncRoot )
2003-08-13 19:00:41 +04:00
{
2005-06-01 13:49:30 +04:00
wrapper = ( TypeWrapper ) types [ name ] ;
}
2005-08-02 12:44:55 +04:00
if ( wrapper ! = null )
{
2006-07-11 11:29:32 +04:00
if ( wrapper . TypeAsTBD ! = type & & ( ! wrapper . IsRemapped | | wrapper . TypeAsBaseType ! = type ) )
2005-08-02 12:44:55 +04:00
{
2006-05-15 13:08:01 +04:00
string msg = String . Format ( "\nTypename \"{0}\" is imported from multiple assemblies:\n{1}\n{2}\n" , type . FullName , wrapper . TypeAsTBD . Assembly . FullName , type . Assembly . FullName ) ;
2005-08-02 12:44:55 +04:00
JVM . CriticalFailure ( msg , null ) ;
}
2006-07-11 11:29:32 +04:00
return wrapper ;
2005-08-02 12:44:55 +04:00
}
else
2005-06-01 13:49:30 +04:00
{
if ( javaType )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// since this type was compiled from Java source, we have to look for our
// attributes
2006-07-11 11:29:32 +04:00
return RegisterInitiatingLoader ( CompiledTypeWrapper . newInstance ( name , type ) ) ;
2004-08-17 13:05:21 +04:00
}
2005-01-03 11:26:21 +03:00
else
{
2006-05-15 13:08:01 +04:00
if ( ! DotNetTypeWrapper . IsAllowedOutside ( type ) )
{
return null ;
}
2005-06-01 13:49:30 +04:00
// since this type was not compiled from Java source, we don't need to
// look for our attributes, but we do need to filter unrepresentable
// stuff (and transform some other stuff)
2006-07-11 11:29:32 +04:00
return RegisterInitiatingLoader ( new DotNetTypeWrapper ( type ) ) ;
2005-01-03 11:26:21 +03:00
}
2003-08-13 19:00:41 +04:00
}
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// NOTE this method can actually return null if the resulting array type name would be too long
// for .NET to handle.
private TypeWrapper CreateArrayType ( string name , TypeWrapper elementTypeWrapper , int dims )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( new String ( '[' , dims ) + elementTypeWrapper . SigName = = name ) ;
Debug . Assert ( ! elementTypeWrapper . IsUnloadable & & ! elementTypeWrapper . IsVerifierType & & ! elementTypeWrapper . IsArray ) ;
Debug . Assert ( dims > = 1 ) ;
Type elementType = elementTypeWrapper . TypeAsArrayType ;
2006-07-11 11:29:32 +04:00
// .NET 1.1 has a limit of 1024 characters for type names
if ( elementType . FullName . Length > = 1024 - dims * 2 )
{
return null ;
}
Type array = ArrayTypeWrapper . MakeArrayType ( elementType , dims ) ;
Modifiers modifiers = Modifiers . Final | Modifiers . Abstract ;
Modifiers reflectiveModifiers = modifiers ;
modifiers | = elementTypeWrapper . Modifiers & Modifiers . Public ;
reflectiveModifiers | = elementTypeWrapper . ReflectiveModifiers & Modifiers . AccessMask ;
return RegisterInitiatingLoader ( new ArrayTypeWrapper ( array , modifiers , reflectiveModifiers , name , this ) ) ;
2005-06-01 13:49:30 +04:00
}
internal object GetJavaClassLoader ( )
2003-12-20 01:19:18 +03:00
{
2006-06-28 12:07:29 +04:00
return javaClassLoader ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper ExpressionTypeWrapper ( string type )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! type . StartsWith ( "Lret;" ) ) ;
Debug . Assert ( type ! = "Lnull" ) ;
int index = 0 ;
return SigDecoderWrapper ( ref index , type ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this exposes potentially unfinished types
internal Type [ ] ArgTypeListFromSig ( string sig )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( sig [ 1 ] = = ')' )
{
2005-12-07 12:06:32 +03:00
#if COMPACT_FRAMEWORK
return new Type [ 0 ] ;
#else
2005-06-01 13:49:30 +04:00
return Type . EmptyTypes ;
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
}
TypeWrapper [ ] wrappers = ArgTypeWrapperListFromSig ( sig ) ;
Type [ ] types = new Type [ wrappers . Length ] ;
for ( int i = 0 ; i < wrappers . Length ; i + + )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
types [ i ] = wrappers [ i ] . TypeAsSignatureType ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return types ;
}
// NOTE: this will ignore anything following the sig marker (so that it can be used to decode method signatures)
private TypeWrapper SigDecoderWrapper ( ref int index , string sig )
{
switch ( sig [ index + + ] )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
case 'B' :
return PrimitiveTypeWrapper . BYTE ;
case 'C' :
return PrimitiveTypeWrapper . CHAR ;
case 'D' :
return PrimitiveTypeWrapper . DOUBLE ;
case 'F' :
return PrimitiveTypeWrapper . FLOAT ;
case 'I' :
return PrimitiveTypeWrapper . INT ;
case 'J' :
return PrimitiveTypeWrapper . LONG ;
case 'L' :
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
int pos = index ;
index = sig . IndexOf ( ';' , index ) + 1 ;
return LoadClassByDottedName ( sig . Substring ( pos , index - pos - 1 ) ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
case 'S' :
return PrimitiveTypeWrapper . SHORT ;
case 'Z' :
return PrimitiveTypeWrapper . BOOLEAN ;
case 'V' :
return PrimitiveTypeWrapper . VOID ;
case '[' :
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO this can be optimized
string array = "[" ;
while ( sig [ index ] = = '[' )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
index + + ;
array + = "[" ;
}
switch ( sig [ index ] )
{
case 'L' :
{
int pos = index ;
index = sig . IndexOf ( ';' , index ) + 1 ;
return LoadClassByDottedName ( array + sig . Substring ( pos , index - pos ) ) ;
}
case 'B' :
case 'C' :
case 'D' :
case 'F' :
case 'I' :
case 'J' :
case 'S' :
case 'Z' :
return LoadClassByDottedName ( array + sig [ index + + ] ) ;
default :
throw new InvalidOperationException ( sig . Substring ( index ) ) ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
default :
throw new InvalidOperationException ( sig . Substring ( index ) ) ;
2002-12-18 19:00:25 +03:00
}
}
2004-03-16 20:10:09 +03:00
2005-06-01 13:49:30 +04:00
internal TypeWrapper FieldTypeWrapperFromSig ( string sig )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
int index = 0 ;
return SigDecoderWrapper ( ref index , sig ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper RetTypeWrapperFromSig ( string sig )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
int index = sig . IndexOf ( ')' ) + 1 ;
return SigDecoderWrapper ( ref index , sig ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper [ ] ArgTypeWrapperListFromSig ( string sig )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( sig [ 1 ] = = ')' )
{
return TypeWrapper . EmptyArray ;
}
ArrayList list = new ArrayList ( ) ;
for ( int i = 1 ; sig [ i ] ! = ')' ; )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
list . Add ( SigDecoderWrapper ( ref i , sig ) ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] types = new TypeWrapper [ list . Count ] ;
list . CopyTo ( types ) ;
return types ;
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
2005-06-01 13:49:30 +04:00
internal static ClassLoaderWrapper GetBootstrapClassLoader ( )
2004-10-04 23:30:53 +04:00
{
2006-03-23 14:57:41 +03:00
lock ( wrapperLock )
2005-06-01 13:49:30 +04:00
{
if ( bootstrapClassLoader = = null )
{
2006-02-22 17:44:07 +03:00
bootstrapClassLoader = new BootstrapClassLoader ( ) ;
2005-06-01 13:49:30 +04:00
}
return bootstrapClassLoader ;
}
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static ClassLoaderWrapper GetClassLoaderWrapper ( object javaClassLoader )
2002-12-18 19:00:25 +03:00
{
2006-06-28 12:07:29 +04:00
if ( javaClassLoader = = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return GetBootstrapClassLoader ( ) ;
}
2005-09-06 12:06:04 +04:00
lock ( wrapperLock )
2005-06-01 13:49:30 +04:00
{
2005-09-06 12:06:04 +04:00
ClassLoaderWrapper wrapper = ( ClassLoaderWrapper ) JVM . Library . getWrapperFromClassLoader ( javaClassLoader ) ;
2005-06-01 13:49:30 +04:00
if ( wrapper = = null )
{
2006-07-06 17:53:51 +04:00
wrapper = new ClassLoaderWrapper ( javaClassLoader ) ;
2005-09-06 12:06:04 +04:00
JVM . Library . setWrapperForClassLoader ( javaClassLoader , wrapper ) ;
2005-06-01 13:49:30 +04:00
}
return wrapper ;
2004-08-17 13:05:21 +04:00
}
2002-12-18 19:00:25 +03:00
}
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
2006-07-11 11:29:32 +04:00
internal static TypeWrapper GetWrapperFromType ( Type type )
2002-12-18 19:00:25 +03:00
{
2006-07-11 11:29:32 +04:00
//Tracer.Info(Tracer.Runtime, "GetWrapperFromType: {0}", type.AssemblyQualifiedName);
2005-06-01 13:49:30 +04:00
TypeWrapper . AssertFinished ( type ) ;
2006-01-23 13:18:44 +03:00
Debug . Assert ( ! Whidbey . ContainsGenericParameters ( type ) ) ;
2006-07-11 11:29:32 +04:00
Debug . Assert ( ! type . IsPointer ) ;
Debug . Assert ( ! type . IsByRef ) ;
2005-06-01 13:49:30 +04:00
TypeWrapper wrapper = ( TypeWrapper ) typeToTypeWrapper [ type ] ;
2006-07-11 11:29:32 +04:00
if ( wrapper ! = null )
2003-02-15 21:52:32 +03:00
{
2006-07-11 11:29:32 +04:00
return wrapper ;
2003-02-15 21:52:32 +03:00
}
2006-07-11 11:29:32 +04:00
string remapped = ( string ) remappedTypes [ type ] ;
if ( remapped ! = null )
2003-02-17 13:13:16 +03:00
{
2006-07-11 11:29:32 +04:00
wrapper = LoadClassCritical ( remapped ) ;
}
else if ( type . IsArray )
{
// it might be an array of a dynamically compiled Java type
int rank = 1 ;
Type elem = type . GetElementType ( ) ;
while ( elem . IsArray )
2003-02-17 13:13:16 +03:00
{
2006-07-11 11:29:32 +04:00
rank + + ;
elem = elem . GetElementType ( ) ;
2003-02-17 13:13:16 +03:00
}
2006-07-11 11:29:32 +04:00
wrapper = GetWrapperFromType ( elem ) . MakeArrayType ( rank ) ;
}
else
{
2005-06-01 13:49:30 +04:00
// if the wrapper doesn't already exist, that must mean that the type
// is a .NET type (or a pre-compiled Java class), which means that it
2006-05-15 13:08:01 +04:00
// was "loaded" by an assembly classloader
2006-07-11 11:29:32 +04:00
wrapper = GetAssemblyClassLoader ( type . Assembly ) . GetWrapperFromBootstrapType ( type ) ;
2003-02-17 13:13:16 +03:00
}
2006-07-11 11:29:32 +04:00
typeToTypeWrapper [ type ] = wrapper ;
2005-06-01 13:49:30 +04:00
return wrapper ;
2002-12-18 19:00:25 +03:00
}
2006-07-21 14:18:13 +04:00
internal virtual Type GetType ( string name )
{
return null ;
}
2006-07-26 14:33:52 +04:00
internal static ClassLoaderWrapper GetGenericClassLoader ( TypeWrapper wrapper )
{
Type type = wrapper . TypeAsTBD ;
Debug . Assert ( Whidbey . IsGenericType ( type ) ) ;
Debug . Assert ( ! Whidbey . ContainsGenericParameters ( type ) ) ;
ArrayList list = new ArrayList ( ) ;
list . Add ( GetAssemblyClassLoader ( type . Assembly ) ) ;
foreach ( Type arg in Whidbey . GetGenericArguments ( type ) )
{
ClassLoaderWrapper loader = GetWrapperFromType ( arg ) . GetClassLoader ( ) ;
if ( ! list . Contains ( loader ) )
{
list . Add ( loader ) ;
}
}
ClassLoaderWrapper [ ] key = ( ClassLoaderWrapper [ ] ) list . ToArray ( typeof ( ClassLoaderWrapper ) ) ;
ClassLoaderWrapper matchingLoader = null ;
lock ( wrapperLock )
{
if ( genericClassLoaders = = null )
{
genericClassLoaders = new ArrayList ( ) ;
}
foreach ( GenericClassLoader loader in genericClassLoaders )
{
if ( loader . Matches ( key ) )
{
matchingLoader = loader ;
break ;
}
}
if ( matchingLoader = = null )
{
matchingLoader = new GenericClassLoader ( key ) ;
genericClassLoaders . Add ( matchingLoader ) ;
}
}
matchingLoader . RegisterInitiatingLoader ( wrapper ) ;
return matchingLoader ;
}
2006-05-15 13:08:01 +04:00
// this method only supports .NET or pre-compiled Java assemblies
internal static ClassLoaderWrapper GetAssemblyClassLoader ( Assembly assembly )
{
// TODO this assertion fires when compiling the core library (at least on Whidbey)
// I need to find out why...
2006-07-06 17:53:51 +04:00
#if ! COMPACT_FRAMEWORK
2006-05-15 13:08:01 +04:00
Debug . Assert ( ! ( assembly is AssemblyBuilder ) ) ;
2006-07-06 17:53:51 +04:00
#endif // !COMPACT_FRAMEWORK
2006-05-15 13:08:01 +04:00
#if WHIDBEY & & ! STATIC_COMPILER
if ( assembly . ReflectionOnly )
{
2006-07-21 14:18:13 +04:00
lock ( wrapperLock )
2006-05-15 13:08:01 +04:00
{
ClassLoaderWrapper loader = ( ClassLoaderWrapper ) reflectionOnlyClassLoaders [ assembly ] ;
if ( loader = = null )
{
2006-07-21 14:18:13 +04:00
loader = new ReflectionOnlyClassLoader ( assembly ) ;
2006-05-15 13:08:01 +04:00
reflectionOnlyClassLoaders [ assembly ] = loader ;
2006-07-21 14:18:13 +04:00
JVM . Library . setWrapperForClassLoader ( loader . javaClassLoader , loader ) ;
2006-05-15 13:08:01 +04:00
}
return loader ;
}
}
#endif
return GetBootstrapClassLoader ( ) ;
}
2005-06-01 13:49:30 +04:00
internal static void SetWrapperForType ( Type type , TypeWrapper wrapper )
{
TypeWrapper . AssertFinished ( type ) ;
Debug . Assert ( ! typeToTypeWrapper . ContainsKey ( type ) ) ;
typeToTypeWrapper . Add ( type , wrapper ) ;
}
2004-11-23 20:46:39 +03:00
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static void PublishLibraryImplementationHelperType ( Type type )
2003-12-24 14:51:41 +03:00
{
2005-06-01 13:49:30 +04:00
CompiledTypeWrapper typeWrapper = CompiledTypeWrapper . newInstance ( type . FullName , type ) ;
SetWrapperForType ( type , typeWrapper ) ;
GetBootstrapClassLoader ( ) . types [ type . FullName ] = typeWrapper ;
2003-12-24 14:51:41 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static TypeWrapper LoadClassCritical ( string name )
2003-12-24 14:51:41 +03:00
{
2005-06-01 13:49:30 +04:00
try
{
return GetBootstrapClassLoader ( ) . LoadClassByDottedName ( name ) ;
}
catch ( Exception x )
{
JVM . CriticalFailure ( "Loading of critical class failed" , x ) ;
return null ;
}
2003-12-24 14:51:41 +03:00
}
2004-08-30 19:56:23 +04:00
2005-06-01 13:49:30 +04:00
internal void RegisterNativeLibrary ( IntPtr p )
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
if ( nativeLibraries = = null )
{
nativeLibraries = new ArrayList ( ) ;
}
nativeLibraries . Add ( p ) ;
2004-08-30 19:56:23 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal IntPtr [ ] GetNativeLibraries ( )
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
if ( nativeLibraries = = null )
{
return new IntPtr [ 0 ] ;
}
return ( IntPtr [ ] ) nativeLibraries . ToArray ( typeof ( IntPtr ) ) ;
2004-08-30 19:56:23 +04:00
}
}
2005-02-23 15:56:15 +03:00
2005-06-01 13:49:30 +04:00
public override string ToString ( )
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
if ( javaClassLoader = = null )
{
return "null" ;
}
return String . Format ( "{0}@{1:X}" , GetWrapperFromType ( javaClassLoader . GetType ( ) ) . Name , javaClassLoader . GetHashCode ( ) ) ;
2005-02-23 15:56:15 +03:00
}
}
2006-02-22 17:44:07 +03:00
class BootstrapClassLoader : ClassLoaderWrapper
{
internal BootstrapClassLoader ( )
: base ( null )
{
}
2006-07-10 13:37:06 +04:00
protected override TypeWrapper LoadClassImpl ( string name , bool throwClassNotFoundException )
{
Type t = GetBootstrapTypeRaw ( name ) ;
if ( t ! = null )
{
return GetWrapperFromBootstrapType ( t ) ;
}
2006-07-26 11:57:18 +04:00
return DotNetTypeWrapper . CreateDotNetTypeWrapper ( this , name ) ;
2006-07-10 13:37:06 +04:00
}
// NOTE this method only sees pre-compiled Java classes
private Type GetBootstrapTypeRaw ( string name )
{
#if COMPACT_FRAMEWORK
// TODO figure this out
return GetJavaTypeFromAssembly ( JVM . CoreAssembly , name ) ;
#else
Assembly [ ] assemblies ;
#if WHIDBEY
if ( JVM . IsStaticCompiler )
{
assemblies = AppDomain . CurrentDomain . ReflectionOnlyGetAssemblies ( ) ;
}
else
{
assemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
}
#else
assemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
#endif
foreach ( Assembly a in assemblies )
{
if ( ! ( a is AssemblyBuilder ) )
{
Type t = GetJavaTypeFromAssembly ( a , name ) ;
if ( t ! = null )
{
return t ;
}
}
}
return null ;
#endif
}
2006-07-21 14:18:13 +04:00
internal static Type GetJavaTypeFromAssembly ( Assembly a , string name )
2006-07-10 13:37:06 +04:00
{
try
{
Type t = a . GetType ( name ) ;
if ( t ! = null
& & AttributeHelper . IsJavaModule ( t . Module )
& & ! AttributeHelper . IsHideFromJava ( t )
& & ! t . IsArray
& & ! t . IsPointer
& & ! t . IsByRef )
{
return t ;
}
// HACK we might be looking for an inner classes
t = a . GetType ( name . Replace ( '$' , '+' ) ) ;
if ( t ! = null
& & AttributeHelper . IsJavaModule ( t . Module )
& & ! AttributeHelper . IsHideFromJava ( t )
& & ! t . IsArray
& & ! t . IsPointer
& & ! t . IsByRef )
{
return t ;
}
}
catch ( ArgumentException x )
{
// we can end up here because we replace the $ with a plus sign
// (or client code did a Class.forName() on an invalid name)
Tracer . Info ( Tracer . Runtime , x . Message ) ;
}
catch ( FileLoadException x )
{
// this can only happen if the assembly was loaded in the ReflectionOnly
// context and the requested type references a type in another assembly
// that cannot be found in the ReflectionOnly context
// TODO figure out what other exceptions Assembly.GetType() can throw
Tracer . Info ( Tracer . Runtime , x . Message ) ;
}
return null ;
}
2006-07-21 14:18:13 +04:00
internal override Type GetType ( string name )
{
Assembly [ ] assemblies ;
#if WHIDBEY & & STATIC_COMPILER
2006-07-26 11:57:18 +04:00
// mscorlib cannot be loaded in the ReflectionOnly context,
// so we have to search that separately
Type trycorlib = typeof ( object ) . Assembly . GetType ( name ) ;
if ( trycorlib ! = null )
{
return trycorlib ;
}
2006-07-21 14:18:13 +04:00
assemblies = AppDomain . CurrentDomain . ReflectionOnlyGetAssemblies ( ) ;
#else
assemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
#endif
foreach ( Assembly a in assemblies )
{
if ( ! ( a is AssemblyBuilder ) )
{
Type t = a . GetType ( name ) ;
if ( t ! = null )
{
return t ;
}
}
}
return null ;
}
2006-02-22 17:44:07 +03:00
}
2006-05-15 13:08:01 +04:00
2006-07-26 14:33:52 +04:00
class GenericClassLoader : ClassLoaderWrapper
{
private ClassLoaderWrapper [ ] delegates ;
// HACK we use a ReflectionOnlyClassLoader Java peer for the time being
internal GenericClassLoader ( ClassLoaderWrapper [ ] delegates )
: base ( JVM . Library . newReflectionOnlyClassLoader ( ) )
{
this . delegates = delegates ;
}
internal bool Matches ( ClassLoaderWrapper [ ] key )
{
if ( key . Length = = delegates . Length )
{
for ( int i = 0 ; i < key . Length ; i + + )
{
if ( key [ i ] ! = delegates [ i ] )
{
return false ;
}
}
return true ;
}
return false ;
}
internal override Type GetType ( string name )
{
foreach ( ClassLoaderWrapper loader in delegates )
{
Type t = loader . GetType ( name ) ;
if ( t ! = null )
{
return t ;
}
}
return null ;
}
protected override TypeWrapper LoadClassImpl ( string name , bool throwClassNotFoundException )
{
foreach ( ClassLoaderWrapper loader in delegates )
{
TypeWrapper tw = loader . LoadClassByDottedNameFast ( name ) ;
if ( tw ! = null )
{
return tw ;
}
}
return null ;
}
}
2006-07-21 14:18:13 +04:00
#if ! STATIC_COMPILER
2006-05-15 13:08:01 +04:00
class ReflectionOnlyClassLoader : ClassLoaderWrapper
{
2006-07-21 14:18:13 +04:00
private Assembly assembly ;
private bool isCoreAssembly ;
internal ReflectionOnlyClassLoader ( Assembly assembly )
: base ( JVM . Library . newReflectionOnlyClassLoader ( ) )
2006-05-15 13:08:01 +04:00
{
2006-07-21 14:18:13 +04:00
this . assembly = assembly ;
isCoreAssembly = AttributeHelper . GetRemappedClasses ( assembly ) . Length > 0 ;
2006-05-15 13:08:01 +04:00
}
2006-07-10 13:37:06 +04:00
2006-07-26 11:57:18 +04:00
internal override Type GetType ( string name )
{
return assembly . GetType ( name ) ;
}
2006-07-10 13:37:06 +04:00
protected override TypeWrapper LoadClassImpl ( string name , bool throwClassNotFoundException )
{
2006-07-21 14:18:13 +04:00
if ( isCoreAssembly )
{
Type t = BootstrapClassLoader . GetJavaTypeFromAssembly ( assembly , name ) ;
if ( t ! = null )
{
return GetWrapperFromBootstrapType ( t ) ;
}
}
2006-07-26 11:57:18 +04:00
TypeWrapper tw = DotNetTypeWrapper . CreateDotNetTypeWrapper ( this , name ) ;
if ( tw ! = null )
{
return tw ;
}
2006-07-10 18:40:31 +04:00
return GetBootstrapClassLoader ( ) . LoadClassByDottedNameFast ( name ) ;
2006-07-10 13:37:06 +04:00
}
2006-05-15 13:08:01 +04:00
}
2006-07-21 14:18:13 +04:00
#endif
2002-12-18 19:00:25 +03:00
}