2
Copyright (C) 2002-2012 Jeroen Frijters
4
This software is provided 'as-is', without any express or implied
5
warranty. In no event will the authors be held liable for any damages
6
arising from the use of this software.
8
Permission is granted to anyone to use this software for any purpose,
9
including commercial applications, and to alter it and redistribute it
10
freely, subject to the following restrictions:
12
1. The origin of this software must not be misrepresented; you must not
13
claim that you wrote the original software. If you use this software
14
in a product, an acknowledgment in the product documentation would be
15
appreciated but is not required.
16
2. Altered source versions must be plainly marked as such, and must not be
17
misrepresented as being the original software.
18
3. This notice may not be removed or altered from any source distribution.
26
using System.Collections.Generic;
27
using ICSharpCode.SharpZipLib.Zip;
28
using IKVM.Attributes;
30
using IKVM.Reflection;
31
using Type = IKVM.Reflection.Type;
35
private static int zipCount;
36
private static ZipOutputStream zipFile;
37
private static Dictionary<string, string> done = new Dictionary<string, string>();
38
private static Dictionary<string, TypeWrapper> todo = new Dictionary<string, TypeWrapper>();
39
private static FileInfo file;
40
private static bool includeSerialVersionUID;
41
private static bool includeNonPublicInterfaces;
42
private static bool includeNonPublicMembers;
43
private static List<string> namespaces = new List<string>();
45
static int Main(string[] args)
47
IKVM.Internal.Tracer.EnableTraceConsoleListener();
48
IKVM.Internal.Tracer.EnableTraceForDebug();
49
string assemblyNameOrPath = null;
50
bool continueOnError = false;
51
bool autoLoadSharedClassLoaderAssemblies = false;
52
List<string> references = new List<string>();
53
List<string> libpaths = new List<string>();
54
bool nostdlib = false;
55
bool bootstrap = false;
56
string outputFile = null;
57
bool forwarders = false;
58
foreach(string s in args)
60
if(s.StartsWith("-") || assemblyNameOrPath != null)
64
Console.Error.WriteLine("The -serialver option is deprecated and will be removed in the future. Use -japi instead.");
65
includeSerialVersionUID = true;
69
includeSerialVersionUID = true;
70
includeNonPublicInterfaces = true;
71
includeNonPublicMembers = true;
73
else if(s == "-skiperror")
75
continueOnError = true;
77
else if(s == "-shared")
79
autoLoadSharedClassLoaderAssemblies = true;
81
else if(s.StartsWith("-r:") || s.StartsWith("-reference:"))
83
references.Add(s.Substring(s.IndexOf(':') + 1));
85
else if(s == "-nostdlib")
89
else if(s.StartsWith("-lib:"))
91
libpaths.Add(s.Substring(5));
93
else if(s == "-bootstrap")
97
else if(s.StartsWith("-out:"))
99
outputFile = s.Substring(5);
101
else if(s.StartsWith("-namespace:"))
103
namespaces.Add(s.Substring(11) + ".");
105
else if(s == "-forwarders")
111
// unrecognized option, or multiple assemblies, print usage message and exit
112
assemblyNameOrPath = null;
118
assemblyNameOrPath = s;
121
if(assemblyNameOrPath == null)
123
Console.Error.WriteLine(GetVersionAndCopyrightInfo());
124
Console.Error.WriteLine();
125
Console.Error.WriteLine("usage: ikvmstub [-options] <assemblyNameOrPath>");
126
Console.Error.WriteLine();
127
Console.Error.WriteLine("options:");
128
Console.Error.WriteLine(" -out:<outputfile> Specify the output filename");
129
Console.Error.WriteLine(" -reference:<filespec> Reference an assembly (short form -r:<filespec>)");
130
Console.Error.WriteLine(" -japi Generate jar suitable for comparison with japitools");
131
Console.Error.WriteLine(" -skiperror Continue when errors are encountered");
132
Console.Error.WriteLine(" -shared Process all assemblies in shared group");
133
Console.Error.WriteLine(" -nostdlib Do not reference standard libraries");
134
Console.Error.WriteLine(" -lib:<dir> Additional directories to search for references");
135
Console.Error.WriteLine(" -namespace:<ns> Only include types from specified namespace");
136
Console.Error.WriteLine(" -forwarders Export forwarded types too");
139
if(File.Exists(assemblyNameOrPath) && nostdlib)
141
// Add the target assembly to the references list, to allow it to be considered as "mscorlib".
142
// This allows "ikvmstub -nostdlib \...\mscorlib.dll" to work.
143
references.Add(assemblyNameOrPath);
145
StaticCompiler.Resolver.Warning += new AssemblyResolver.WarningEvent(Resolver_Warning);
146
StaticCompiler.Resolver.Init(StaticCompiler.Universe, nostdlib, references, libpaths);
147
Dictionary<string, Assembly> cache = new Dictionary<string, Assembly>();
148
foreach (string reference in references)
150
Assembly[] dummy = null;
151
if (!StaticCompiler.Resolver.ResolveReference(cache, ref dummy, reference))
153
Console.Error.WriteLine("Error: reference not found {0}", reference);
157
Assembly assembly = null;
160
file = new FileInfo(assemblyNameOrPath);
162
catch(System.Exception x)
164
Console.Error.WriteLine("Error: unable to load \"{0}\"\n {1}", assemblyNameOrPath, x.Message);
167
if(file != null && file.Exists)
169
assembly = StaticCompiler.LoadFile(assemblyNameOrPath);
173
assembly = StaticCompiler.Resolver.LoadWithPartialName(assemblyNameOrPath);
178
Console.Error.WriteLine("Error: Assembly \"{0}\" not found", assemblyNameOrPath);
184
StaticCompiler.runtimeAssembly = StaticCompiler.LoadFile(typeof(NetExp).Assembly.Location);
185
ClassLoaderWrapper.SetBootstrapClassLoader(new BootstrapBootstrapClassLoader());
189
StaticCompiler.LoadFile(typeof(NetExp).Assembly.Location);
190
StaticCompiler.runtimeAssembly = StaticCompiler.LoadFile(Path.Combine(typeof(NetExp).Assembly.Location, "../IKVM.Runtime.dll"));
191
JVM.CoreAssembly = StaticCompiler.LoadFile(Path.Combine(typeof(NetExp).Assembly.Location, "../IKVM.OpenJDK.Core.dll"));
193
if (AttributeHelper.IsJavaModule(assembly.ManifestModule))
195
Console.Error.WriteLine("Warning: Running ikvmstub on ikvmc compiled assemblies is not supported.");
197
if (outputFile == null)
199
outputFile = assembly.GetName().Name + ".jar";
203
using (zipFile = new ZipOutputStream(new FileStream(outputFile, FileMode.Create)))
205
zipFile.SetComment(GetVersionAndCopyrightInfo());
208
List<Assembly> assemblies = new List<Assembly>();
209
assemblies.Add(assembly);
210
if (autoLoadSharedClassLoaderAssemblies)
212
LoadSharedClassLoaderAssemblies(assembly, assemblies);
214
foreach (Assembly asm in assemblies)
216
if (ProcessTypes(asm.GetTypes(), continueOnError) != 0)
219
if (!continueOnError)
224
if (forwarders && ProcessTypes(asm.ManifestModule.__GetExportedTypes(), continueOnError) != 0)
227
if (!continueOnError)
234
catch (System.Exception x)
236
Console.Error.WriteLine(x);
238
if (!continueOnError)
240
Console.Error.WriteLine("Warning: Assembly reflection encountered an error. Resultant JAR may be incomplete.");
247
catch (ZipException x)
252
Console.Error.WriteLine("Error: Assembly contains no public IKVM.NET compatible types");
256
Console.Error.WriteLine("Error: {0}", x.Message);
263
static void Resolver_Warning(AssemblyResolver.WarningId warning, string message, string[] parameters)
265
if (warning != AssemblyResolver.WarningId.HigherVersion)
267
Console.Error.WriteLine("Warning: " + message, parameters);
271
private static string GetVersionAndCopyrightInfo()
273
System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly();
274
object[] desc = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false);
275
if (desc.Length == 1)
277
object[] copyright = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyCopyrightAttribute), false);
278
if (copyright.Length == 1)
280
return string.Format("{0} version {1}{2}{3}{2}http://www.ikvm.net/",
281
((System.Reflection.AssemblyTitleAttribute)desc[0]).Title,
282
asm.GetName().Version,
284
((System.Reflection.AssemblyCopyrightAttribute)copyright[0]).Copyright);
290
private static void LoadSharedClassLoaderAssemblies(Assembly assembly, List<Assembly> assemblies)
292
if (assembly.GetManifestResourceInfo("ikvm.exports") != null)
294
using (Stream stream = assembly.GetManifestResourceStream("ikvm.exports"))
296
BinaryReader rdr = new BinaryReader(stream);
297
int assemblyCount = rdr.ReadInt32();
298
for (int i = 0; i < assemblyCount; i++)
300
string name = rdr.ReadString();
301
int typeCount = rdr.ReadInt32();
304
for (int j = 0; j < typeCount; j++)
310
assemblies.Add(StaticCompiler.Load(name));
314
Console.WriteLine("Warning: Unable to load shared class loader assembly: {0}", name);
322
private static void WriteClass(TypeWrapper tw)
324
string name = tw.Name.Replace('.', '/');
328
super = "java/lang/Object";
330
else if (tw.BaseTypeWrapper != null)
332
super = tw.BaseTypeWrapper.Name.Replace('.', '/');
334
IKVM.StubGen.ClassFileWriter writer = new IKVM.StubGen.ClassFileWriter(tw.Modifiers, name, super, 0, 49);
335
foreach (TypeWrapper iface in tw.Interfaces)
337
if (iface.IsPublic || includeNonPublicInterfaces)
339
writer.AddInterface(iface.Name.Replace('.', '/'));
342
IKVM.StubGen.InnerClassesAttribute innerClassesAttribute = null;
343
if (tw.DeclaringTypeWrapper != null)
345
TypeWrapper outer = tw.DeclaringTypeWrapper;
346
string innername = name;
347
int idx = name.LastIndexOf('$');
350
innername = innername.Substring(idx + 1);
352
innerClassesAttribute = new IKVM.StubGen.InnerClassesAttribute(writer);
353
innerClassesAttribute.Add(name, outer.Name.Replace('.', '/'), innername, (ushort)tw.ReflectiveModifiers);
355
foreach (TypeWrapper inner in tw.InnerClasses)
359
if (innerClassesAttribute == null)
361
innerClassesAttribute = new IKVM.StubGen.InnerClassesAttribute(writer);
363
string namePart = inner.Name;
364
namePart = namePart.Substring(namePart.LastIndexOf('$') + 1);
365
innerClassesAttribute.Add(inner.Name.Replace('.', '/'), name, namePart, (ushort)inner.ReflectiveModifiers);
368
if (innerClassesAttribute != null)
370
writer.AddAttribute(innerClassesAttribute);
372
string genericTypeSignature = tw.GetGenericSignature();
373
if (genericTypeSignature != null)
375
writer.AddStringAttribute("Signature", genericTypeSignature);
377
writer.AddStringAttribute("IKVM.NET.Assembly", GetAssemblyName(tw));
378
if (tw.TypeAsBaseType.IsDefined(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false))
380
writer.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer));
382
foreach (MethodWrapper mw in tw.GetMethods())
384
if (!mw.IsHideFromReflection && (mw.IsPublic || mw.IsProtected || includeNonPublicMembers))
386
IKVM.StubGen.FieldOrMethod m;
387
if (mw.Name == "<init>")
389
m = writer.AddMethod(mw.Modifiers, mw.Name, mw.Signature.Replace('.', '/'));
390
IKVM.StubGen.CodeAttribute code = new IKVM.StubGen.CodeAttribute(writer);
391
code.MaxLocals = (ushort)(mw.GetParameters().Length * 2 + 1);
393
ushort index1 = writer.AddClass("java/lang/UnsatisfiedLinkError");
394
ushort index2 = writer.AddString("ikvmstub generated stubs can only be used on IKVM.NET");
395
ushort index3 = writer.AddMethodRef("java/lang/UnsatisfiedLinkError", "<init>", "(Ljava/lang/String;)V");
396
code.ByteCode = new byte[] {
397
187, (byte)(index1 >> 8), (byte)index1, // new java/lang/UnsatisfiedLinkError
399
19, (byte)(index2 >> 8), (byte)index2, // ldc_w "..."
400
183, (byte)(index3 >> 8), (byte)index3, // invokespecial java/lang/UnsatisfiedLinkError/init()V
403
m.AddAttribute(code);
407
Modifiers mods = mw.Modifiers;
408
if ((mods & Modifiers.Abstract) == 0)
410
mods |= Modifiers.Native;
412
m = writer.AddMethod(mods, mw.Name, mw.Signature.Replace('.', '/'));
413
if (mw.IsOptionalAttributeAnnotationValue)
415
m.AddAttribute(new IKVM.StubGen.AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, mw.ReturnType)));
418
MethodBase mb = mw.GetMethod();
421
ThrowsAttribute throws = AttributeHelper.GetThrows(mb);
424
string[] throwsArray = mw.GetDeclaredExceptions();
425
if (throwsArray != null && throwsArray.Length > 0)
427
IKVM.StubGen.ExceptionsAttribute attrib = new IKVM.StubGen.ExceptionsAttribute(writer);
428
foreach (string ex in throwsArray)
430
attrib.Add(ex.Replace('.', '/'));
432
m.AddAttribute(attrib);
437
IKVM.StubGen.ExceptionsAttribute attrib = new IKVM.StubGen.ExceptionsAttribute(writer);
438
if (throws.classes != null)
440
foreach (string ex in throws.classes)
442
attrib.Add(ex.Replace('.', '/'));
445
if (throws.types != null)
447
foreach (Type ex in throws.types)
449
attrib.Add(ClassLoaderWrapper.GetWrapperFromType(ex).Name.Replace('.', '/'));
452
m.AddAttribute(attrib);
454
if (mb.IsDefined(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false)
455
// HACK the instancehelper methods are marked as Obsolete (to direct people toward the ikvm.extensions methods instead)
456
// but in the Java world most of them are not deprecated (and to keep the Japi results clean we need to reflect this)
457
&& (!mb.Name.StartsWith("instancehelper_")
458
|| mb.DeclaringType.FullName != "java.lang.String"
459
// the Java deprecated methods actually have two Obsolete attributes
460
|| mb.__GetCustomAttributes(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false).Count == 2))
462
m.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer));
464
IList<CustomAttributeData> attr = CustomAttributeData.__GetCustomAttributes(mb, JVM.LoadType(typeof(AnnotationDefaultAttribute)), false);
467
m.AddAttribute(new IKVM.StubGen.AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, attr[0].ConstructorArguments[0])));
470
string sig = tw.GetGenericMethodSignature(mw);
473
m.AddAttribute(writer.MakeStringAttribute("Signature", sig));
477
bool hasSerialVersionUID = false;
478
foreach (FieldWrapper fw in tw.GetFields())
480
if (!fw.IsHideFromReflection)
482
bool isSerialVersionUID = includeSerialVersionUID && fw.Name == "serialVersionUID" && fw.FieldTypeWrapper == PrimitiveTypeWrapper.LONG;
483
hasSerialVersionUID |= isSerialVersionUID;
484
if (fw.IsPublic || fw.IsProtected || isSerialVersionUID || includeNonPublicMembers)
486
object constant = null;
487
if (fw.GetField() != null && fw.GetField().IsLiteral && (fw.FieldTypeWrapper.IsPrimitive || fw.FieldTypeWrapper == CoreClasses.java.lang.String.Wrapper))
489
constant = fw.GetField().GetRawConstantValue();
490
if (fw.GetField().FieldType.IsEnum)
492
constant = EnumHelper.GetPrimitiveValue(EnumHelper.GetUnderlyingType(fw.GetField().FieldType), constant);
495
IKVM.StubGen.FieldOrMethod f = writer.AddField(fw.Modifiers, fw.Name, fw.Signature.Replace('.', '/'), constant);
496
string sig = tw.GetGenericFieldSignature(fw);
499
f.AddAttribute(writer.MakeStringAttribute("Signature", sig));
501
if (fw.GetField() != null && fw.GetField().IsDefined(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false))
503
f.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer));
508
if (includeSerialVersionUID && !hasSerialVersionUID && IsSerializable(tw))
510
// class is serializable but doesn't have an explicit serialVersionUID, so we add the field to record
511
// the serialVersionUID as we see it (mainly to make the Japi reports more realistic)
512
writer.AddField(Modifiers.Private | Modifiers.Static | Modifiers.Final, "serialVersionUID", "J", IKVM.StubGen.SerialVersionUID.Compute(tw));
514
AddMetaAnnotations(writer, tw);
516
MemoryStream mem = new MemoryStream();
518
ZipEntry entry = new ZipEntry(name + ".class");
519
entry.Size = mem.Position;
520
zipFile.PutNextEntry(entry);
521
mem.WriteTo(zipFile);
524
private static string GetAssemblyName(TypeWrapper tw)
526
ClassLoaderWrapper loader = tw.GetClassLoader();
527
AssemblyClassLoader acl = loader as AssemblyClassLoader;
530
return acl.GetAssembly(tw).FullName;
534
return ((GenericClassLoader)loader).GetName();
538
private static bool IsSerializable(TypeWrapper tw)
540
if (tw.Name == "java.io.Serializable")
546
foreach (TypeWrapper iface in tw.Interfaces)
548
if (IsSerializable(iface))
553
tw = tw.BaseTypeWrapper;
558
private static void AddMetaAnnotations(IKVM.StubGen.ClassFileWriter writer, TypeWrapper tw)
560
DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase attributeAnnotation = tw as DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase;
561
if (attributeAnnotation != null)
563
// TODO write the annotation directly, instead of going thru the object[] encoding
564
IKVM.StubGen.RuntimeVisibleAnnotationsAttribute annot = new IKVM.StubGen.RuntimeVisibleAnnotationsAttribute(writer);
565
annot.Add(new object[] {
566
AnnotationDefaultAttribute.TAG_ANNOTATION,
567
"Ljava/lang/annotation/Retention;",
569
new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME" }
571
AttributeTargets validOn = attributeAnnotation.AttributeTargets;
572
List<object[]> targets = new List<object[]>();
573
if ((validOn & (AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate | AttributeTargets.Assembly)) != 0)
575
targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "TYPE" });
577
if ((validOn & AttributeTargets.Constructor) != 0)
579
targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "CONSTRUCTOR" });
581
if ((validOn & AttributeTargets.Field) != 0)
583
targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "FIELD" });
585
if ((validOn & (AttributeTargets.Method | AttributeTargets.ReturnValue)) != 0)
587
targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "METHOD" });
589
if ((validOn & AttributeTargets.Parameter) != 0)
591
targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "PARAMETER" });
593
annot.Add(new object[] {
594
AnnotationDefaultAttribute.TAG_ANNOTATION,
595
"Ljava/lang/annotation/Target;",
597
new object[] { AnnotationDefaultAttribute.TAG_ARRAY, targets.ToArray() }
599
writer.AddAttribute(annot);
603
private static byte[] GetAnnotationDefault(IKVM.StubGen.ClassFileWriter classFile, TypeWrapper type)
605
MemoryStream mem = new MemoryStream();
606
IKVM.StubGen.BigEndianStream bes = new IKVM.StubGen.BigEndianStream(mem);
607
if (type == PrimitiveTypeWrapper.BOOLEAN)
609
bes.WriteByte((byte)'Z');
610
bes.WriteUInt16(classFile.AddInt(0));
612
else if(type == PrimitiveTypeWrapper.BYTE)
614
bes.WriteByte((byte)'B');
615
bes.WriteUInt16(classFile.AddInt(0));
617
else if(type == PrimitiveTypeWrapper.CHAR)
619
bes.WriteByte((byte)'C');
620
bes.WriteUInt16(classFile.AddInt(0));
622
else if(type == PrimitiveTypeWrapper.SHORT)
624
bes.WriteByte((byte)'S');
625
bes.WriteUInt16(classFile.AddInt(0));
627
else if(type == PrimitiveTypeWrapper.INT)
629
bes.WriteByte((byte)'I');
630
bes.WriteUInt16(classFile.AddInt(0));
632
else if(type == PrimitiveTypeWrapper.FLOAT)
634
bes.WriteByte((byte)'F');
635
bes.WriteUInt16(classFile.AddFloat(0));
637
else if(type == PrimitiveTypeWrapper.LONG)
639
bes.WriteByte((byte)'J');
640
bes.WriteUInt16(classFile.AddLong(0));
642
else if (type == PrimitiveTypeWrapper.DOUBLE)
644
bes.WriteByte((byte)'D');
645
bes.WriteUInt16(classFile.AddDouble(0));
647
else if (type == CoreClasses.java.lang.String.Wrapper)
649
bes.WriteByte((byte)'s');
650
bes.WriteUInt16(classFile.AddUtf8(""));
652
else if ((type.Modifiers & Modifiers.Enum) != 0)
654
bes.WriteByte((byte)'e');
655
bes.WriteUInt16(classFile.AddUtf8("L" + type.Name.Replace('.', '/') + ";"));
656
bes.WriteUInt16(classFile.AddUtf8("__unspecified"));
658
else if (type == CoreClasses.java.lang.Class.Wrapper)
660
bes.WriteByte((byte)'c');
661
bes.WriteUInt16(classFile.AddUtf8("Likvm/internal/__unspecified;"));
663
else if (type.IsArray)
665
bes.WriteByte((byte)'[');
670
throw new InvalidOperationException();
672
return mem.ToArray();
675
private static byte[] GetAnnotationDefault(IKVM.StubGen.ClassFileWriter classFile, CustomAttributeTypedArgument value)
677
MemoryStream mem = new MemoryStream();
678
IKVM.StubGen.BigEndianStream bes = new IKVM.StubGen.BigEndianStream(mem);
681
WriteAnnotationElementValue(classFile, bes, value);
683
catch (InvalidCastException)
685
Console.Error.WriteLine("Warning: incorrect annotation default value");
687
catch (IndexOutOfRangeException)
689
Console.Error.WriteLine("Warning: incorrect annotation default value");
691
return mem.ToArray();
694
private static void WriteAnnotationElementValue(IKVM.StubGen.ClassFileWriter classFile, IKVM.StubGen.BigEndianStream bes, CustomAttributeTypedArgument value)
696
if (value.ArgumentType == Types.Boolean)
698
bes.WriteByte((byte)'Z');
699
bes.WriteUInt16(classFile.AddInt((bool)value.Value ? 1 : 0));
701
else if (value.ArgumentType == Types.Byte)
703
bes.WriteByte((byte)'B');
704
bes.WriteUInt16(classFile.AddInt((byte)value.Value));
706
else if (value.ArgumentType == Types.Char)
708
bes.WriteByte((byte)'C');
709
bes.WriteUInt16(classFile.AddInt((char)value.Value));
711
else if (value.ArgumentType == Types.Int16)
713
bes.WriteByte((byte)'S');
714
bes.WriteUInt16(classFile.AddInt((short)value.Value));
716
else if (value.ArgumentType == Types.Int32)
718
bes.WriteByte((byte)'I');
719
bes.WriteUInt16(classFile.AddInt((int)value.Value));
721
else if (value.ArgumentType == Types.Single)
723
bes.WriteByte((byte)'F');
724
bes.WriteUInt16(classFile.AddFloat((float)value.Value));
726
else if (value.ArgumentType == Types.Int64)
728
bes.WriteByte((byte)'J');
729
bes.WriteUInt16(classFile.AddLong((long)value.Value));
731
else if (value.ArgumentType == Types.Double)
733
bes.WriteByte((byte)'D');
734
bes.WriteUInt16(classFile.AddDouble((double)value.Value));
736
else if (value.ArgumentType == Types.String)
738
bes.WriteByte((byte)'s');
739
bes.WriteUInt16(classFile.AddUtf8((string)value.Value));
741
else if (value.ArgumentType == Types.Object.MakeArrayType())
743
CustomAttributeTypedArgument[] array = (CustomAttributeTypedArgument[])value.Value;
744
byte type = (byte)array[0].Value;
745
if (type == AnnotationDefaultAttribute.TAG_ARRAY)
747
bes.WriteByte((byte)'[');
748
bes.WriteUInt16((ushort)(array.Length - 1));
749
for (int i = 1; i < array.Length; i++)
751
WriteAnnotationElementValue(classFile, bes, array[i]);
754
else if (type == AnnotationDefaultAttribute.TAG_CLASS)
756
bes.WriteByte((byte)'c');
757
bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value));
759
else if (type == AnnotationDefaultAttribute.TAG_ENUM)
761
bes.WriteByte((byte)'e');
762
bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value));
763
bes.WriteUInt16(classFile.AddUtf8((string)array[2].Value));
765
else if (type == AnnotationDefaultAttribute.TAG_ANNOTATION)
767
bes.WriteByte((byte)'@');
768
bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value));
769
bes.WriteUInt16((ushort)((array.Length - 2) / 2));
770
for (int i = 2; i < array.Length; i += 2)
772
bes.WriteUInt16(classFile.AddUtf8((string)array[i].Value));
773
WriteAnnotationElementValue(classFile, bes, array[i + 1]);
778
Console.Error.WriteLine("Warning: incorrect annotation default element tag: " + type);
783
Console.Error.WriteLine("Warning: incorrect annotation default element type: " + value.ArgumentType);
787
private static bool ExportNamespace(Type type)
789
if (namespaces.Count == 0)
793
string name = type.FullName;
794
foreach (string ns in namespaces)
796
if (name.StartsWith(ns, StringComparison.Ordinal))
804
private static int ProcessTypes(Type[] types, bool continueOnError)
807
foreach (Type t in types)
810
&& ExportNamespace(t)
811
&& !t.IsGenericTypeDefinition
812
&& !AttributeHelper.IsHideFromJava(t)
813
&& (!t.IsGenericType || !AttributeHelper.IsJavaModule(t.Module)))
816
if (ClassLoaderWrapper.IsRemappedType(t) || t.IsPrimitive || t == Types.Void)
818
c = DotNetTypeWrapper.GetWrapperFromDotNetType(t);
822
c = ClassLoaderWrapper.GetWrapperFromType(t);
834
foreach (TypeWrapper c in new List<TypeWrapper>(todo.Values))
836
if(!done.ContainsKey(c.Name))
839
done.Add(c.Name, null);
850
Console.WriteLine(x);
864
private static void AddToExportList(TypeWrapper c)
869
private static bool IsNonVectorArray(TypeWrapper tw)
871
return !tw.IsArray && tw.TypeAsBaseType.IsArray;
874
private static void AddToExportListIfNeeded(TypeWrapper tw)
878
tw = tw.ElementTypeWrapper;
880
if (tw.IsUnloadable && tw.Name.StartsWith("Missing/"))
882
Console.Error.WriteLine("Error: unable to find assembly '{0}'", tw.Name.Substring(8));
886
if (tw is StubTypeWrapper)
890
else if ((tw.TypeAsTBD != null && tw.TypeAsTBD.IsGenericType) || IsNonVectorArray(tw) || !tw.IsPublic)
896
private static void AddToExportListIfNeeded(TypeWrapper[] types)
898
foreach (TypeWrapper tw in types)
900
AddToExportListIfNeeded(tw);
904
private static void ProcessClass(TypeWrapper tw)
906
TypeWrapper superclass = tw.BaseTypeWrapper;
907
if (superclass != null)
909
AddToExportListIfNeeded(superclass);
911
AddToExportListIfNeeded(tw.Interfaces);
912
TypeWrapper outerClass = tw.DeclaringTypeWrapper;
913
if (outerClass != null)
915
AddToExportList(outerClass);
917
foreach (TypeWrapper innerClass in tw.InnerClasses)
919
if (innerClass.IsPublic)
921
AddToExportList(innerClass);
924
foreach (MethodWrapper mw in tw.GetMethods())
926
if (mw.IsPublic || mw.IsProtected)
929
AddToExportListIfNeeded(mw.ReturnType);
930
AddToExportListIfNeeded(mw.GetParameters());
933
foreach (FieldWrapper fw in tw.GetFields())
935
if (fw.IsPublic || fw.IsProtected)
938
AddToExportListIfNeeded(fw.FieldTypeWrapper);
944
static class Intrinsics
946
internal static bool IsIntrinsic(MethodWrapper methodWrapper)
952
static class StaticCompiler
954
internal static readonly Universe Universe = new Universe();
955
internal static readonly AssemblyResolver Resolver = new AssemblyResolver();
956
internal static Assembly runtimeAssembly;
958
internal static Type GetRuntimeType(string typeName)
960
return runtimeAssembly.GetType(typeName, true);
963
internal static Assembly LoadFile(string fileName)
965
return Resolver.LoadFile(fileName);
968
internal static Assembly Load(string name)
970
return Universe.Load(name);
974
static class FakeTypes
976
private static readonly Type genericType;
982
genericType = StaticCompiler.Universe.Import(typeof(Holder<>));
985
internal static Type GetAttributeType(Type type)
987
return genericType.MakeGenericType(type);
990
internal static Type GetAttributeReturnValueType(Type type)
992
return genericType.MakeGenericType(type);
995
internal static Type GetAttributeMultipleType(Type type)
997
return genericType.MakeGenericType(type);
1000
internal static Type GetDelegateType(Type type)
1002
return genericType.MakeGenericType(type);
1005
internal static Type GetEnumType(Type type)
1007
return genericType.MakeGenericType(type);
1011
sealed class BootstrapBootstrapClassLoader : ClassLoaderWrapper
1013
internal BootstrapBootstrapClassLoader()
1014
: base(CodeGenOptions.None, null)
1016
TypeWrapper javaLangObject = new StubTypeWrapper(Modifiers.Public, "java.lang.Object", null, true);
1017
SetRemappedType(JVM.Import(typeof(object)), javaLangObject);
1018
SetRemappedType(JVM.Import(typeof(string)), new StubTypeWrapper(Modifiers.Public | Modifiers.Final, "java.lang.String", javaLangObject, true));
1019
SetRemappedType(JVM.Import(typeof(Exception)), new StubTypeWrapper(Modifiers.Public, "java.lang.Throwable", javaLangObject, true));
1020
SetRemappedType(JVM.Import(typeof(IComparable)), new StubTypeWrapper(Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.Comparable", null, true));
1021
TypeWrapper tw = new StubTypeWrapper(Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.AutoCloseable", null, true);
1022
tw.SetMethods(new MethodWrapper[] { new SimpleCallMethodWrapper(tw, "close", "()V", JVM.Import(typeof(IDisposable)).GetMethod("Dispose"), PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Public | Modifiers.Abstract, MemberFlags.None, SimpleOpCode.Callvirt, SimpleOpCode.Callvirt) });
1023
SetRemappedType(JVM.Import(typeof(IDisposable)), tw);
1025
RegisterInitiatingLoader(new StubTypeWrapper(Modifiers.Public, "java.lang.Enum", javaLangObject, false));
1026
RegisterInitiatingLoader(new StubTypeWrapper(Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.annotation.Annotation", null, false));
1027
RegisterInitiatingLoader(new StubTypeWrapper(Modifiers.Public | Modifiers.Final, "java.lang.Class", javaLangObject, false));
1031
sealed class StubTypeWrapper : TypeWrapper
1033
private readonly bool remapped;
1034
private readonly TypeWrapper baseWrapper;
1036
internal StubTypeWrapper(Modifiers modifiers, string name, TypeWrapper baseWrapper, bool remapped)
1037
: base(modifiers, name)
1039
this.remapped = remapped;
1040
this.baseWrapper = baseWrapper;
1043
internal override TypeWrapper BaseTypeWrapper
1045
get { return baseWrapper; }
1048
internal override ClassLoaderWrapper GetClassLoader()
1050
return ClassLoaderWrapper.GetBootstrapClassLoader();
1053
internal override Type TypeAsTBD
1055
get { throw new NotSupportedException(); }
1058
internal override TypeWrapper[] Interfaces
1060
get { return TypeWrapper.EmptyArray; }
1063
internal override TypeWrapper[] InnerClasses
1065
get { return TypeWrapper.EmptyArray; }
1068
internal override TypeWrapper DeclaringTypeWrapper
1070
get { return null; }
1073
internal override void Finish()
1077
internal override bool IsRemapped
1079
get { return remapped; }