Browse Source

move Java type loading into a separate module, so we don't depend on genjava->gencommon for everything

Dan Korostelev 8 years ago
parent
commit
8decf1a38e
4 changed files with 1158 additions and 1137 deletions
  1. 2 2
      src/compiler/main.ml
  2. 0 1134
      src/generators/genjava.ml
  3. 1 1
      src/macro/macroApi.ml
  4. 1155 0
      src/typing/java.ml

+ 2 - 2
src/compiler/main.ml

@@ -307,7 +307,7 @@ module Initialize = struct
 					com.java_libs <- [];
 					old_flush()
 				);
-				Genjava.before_generate com;
+				Java.before_generate com;
 				add_std "java"; "java"
 			| Python ->
 				add_std "python";
@@ -603,7 +603,7 @@ try
 		),"<file> : use the SWF library for type checking");
 		("-java-lib",Arg.String (fun file ->
 			let std = file = "lib/hxjava-std.jar" in
-			arg_delays := (fun () -> Genjava.add_java_lib com file std) :: !arg_delays;
+			arg_delays := (fun () -> Java.add_java_lib com file std) :: !arg_delays;
 		),"<file> : add an external JAR or class directory library");
 		("-net-lib",Arg.String (fun file ->
 			let file, is_std = match ExtString.String.nsplit file "@" with

+ 0 - 1134
src/generators/genjava.ml

@@ -29,8 +29,6 @@ open Printf
 open Option
 open ExtString
 
-module SS = Set.Make(String)
-
 let is_boxed_type t = match follow t with
 	| TInst ({ cl_path = (["java";"lang"], "Boolean") }, [])
 	| TInst ({ cl_path = (["java";"lang"], "Double") }, [])
@@ -2474,21 +2472,6 @@ let configure gen =
 
 (* end of configure function *)
 
-let before_generate con =
-	let java_ver = try
-			int_of_string (PMap.find "java_ver" con.defines)
-		with | Not_found ->
-			Common.define_value con Define.JavaVer "7";
-			7
-	in
- if java_ver < 5 then failwith ("Java version is defined to target Java " ^ string_of_int java_ver ^ ", but the compiler can only output code to versions equal or superior to Java 5");
-	let rec loop i =
-		Common.raw_define con ("java" ^ (string_of_int i));
-		if i > 0 then loop (i - 1)
-	in
-	loop java_ver;
-	()
-
 let generate con =
 	let exists = ref false in
 	con.java_libs <- List.map (fun (file,std,close,la,gr) ->
@@ -2521,1120 +2504,3 @@ let generate con =
 		configure gen
 	with | TypeNotFound path -> con.error ("Error. Module '" ^ (s_type_path path) ^ "' is required and was not included in build.")	null_pos);
 	debug_mode := false
-
-(** Java lib *)
-
-open JData
-
-type java_lib_ctx = {
-	jcom : Common.context;
-	(* current tparams context *)
-	mutable jtparams : jtypes list;
-}
-
-exception ConversionError of string * pos
-
-let error s p = raise (ConversionError (s, p))
-
-let is_haxe_keyword = function
-	| "cast" | "extern" | "function" | "in" | "typedef" | "using" | "var" | "untyped" | "inline" -> true
-	| _ -> false
-
-let jname_to_hx name =
-	let name =
-		if name <> "" && (String.get name 0 < 'A' || String.get name 0 > 'Z') then
-			Char.escaped (Char.uppercase (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
-		else
-			name
-	in
-	let name = String.concat "__" (String.nsplit name "_") in
-	String.map (function | '$' -> '_' | c -> c) name
-
-let normalize_pack pack =
-	List.map (function
-		| "" -> ""
-		| str when String.get str 0 >= 'A' && String.get str 0 <= 'Z' ->
-			String.lowercase str
-		| str -> str
-	) pack
-
-let jpath_to_hx (pack,name) = match pack, name with
-	| ["haxe";"root"], name -> [], name
-	| "com" :: ("oracle" | "sun") :: _, _
-	| "javax" :: _, _
-	| "org" :: ("ietf" | "jcp" | "omg" | "w3c" | "xml") :: _, _
-	| "sun" :: _, _
-	| "sunw" :: _, _ -> "java" :: normalize_pack pack, jname_to_hx name
-	| pack, name -> normalize_pack pack, jname_to_hx name
-
-let real_java_path ctx (pack,name) =
-	s_type_path (pack, name)
-
-let lookup_jclass com path =
-	let path = jpath_to_hx path in
-	List.fold_right (fun (_,_,_,_,get_raw_class) acc ->
-		match acc with
-		| None -> get_raw_class path
-		| Some p -> Some p
-	) com.java_libs None
-
-let mk_type_path ctx path params =
-	let name, sub = try
-		let p, _ = String.split (snd path) "$" in
-		jname_to_hx p, Some (jname_to_hx (snd path))
-		with | Invalid_string ->
-			jname_to_hx (snd path), None
-	in
-	let pack = fst (jpath_to_hx path) in
-	let pack, sub, name = match path with
-		| [], ("Float" as c)
-		| [], ("Int" as c)
-		| [], ("Single" as c)
-		| [], ("Bool" as c)
-		| [], ("Dynamic" as c)
-		| [], ("Iterator" as c)
-		| [], ("ArrayAccess" as c)
-		| [], ("Iterable" as c) ->
-			[], Some c, "StdTypes"
-		| [], ("String" as c) ->
-			["std"], None, c
-		| _ ->
-			pack, sub, name
-	in
-	CTPath {
-		tpackage = pack;
-		tname = name;
-		tparams = params;
-		tsub = sub;
-	}
-
-let has_tparam name params = List.exists(fun (n,_,_) -> n = name) params
-
-let rec convert_arg ctx p arg =
-	match arg with
-	| TAny | TType (WSuper, _) -> TPType (mk_type_path ctx ([], "Dynamic") [],null_pos)
-	| TType (_, jsig) -> TPType (convert_signature ctx p jsig,null_pos)
-
-and convert_signature ctx p jsig =
-	match jsig with
-	| TByte -> mk_type_path ctx (["java"; "types"], "Int8") []
-	| TChar -> mk_type_path ctx (["java"; "types"], "Char16") []
-	| TDouble -> mk_type_path ctx ([], "Float") []
-	| TFloat -> mk_type_path ctx ([], "Single") []
-	| TInt -> mk_type_path ctx ([], "Int") []
-	| TLong -> mk_type_path ctx (["haxe"], "Int64") []
-	| TShort -> mk_type_path ctx (["java"; "types"], "Int16") []
-	| TBool -> mk_type_path ctx ([], "Bool") []
-	| TObject ( (["haxe";"root"], name), args ) -> mk_type_path ctx ([], name) (List.map (convert_arg ctx p) args)
-	(** nullable types *)
-	(* replaced from Null<Type> to the actual abstract type to fix #2738 *)
-	(* | TObject ( (["java";"lang"], "Integer"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Int") []) ] *)
-	(* | TObject ( (["java";"lang"], "Double"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Float") []) ] *)
-	(* | TObject ( (["java";"lang"], "Float"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Single") []) ] *)
-	(* | TObject ( (["java";"lang"], "Boolean"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Bool") []) ] *)
-	(* | TObject ( (["java";"lang"], "Byte"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["java";"types"], "Int8") []) ] *)
-	(* | TObject ( (["java";"lang"], "Character"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["java";"types"], "Char16") []) ] *)
-	(* | TObject ( (["java";"lang"], "Short"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["java";"types"], "Int16") []) ] *)
-	(* | TObject ( (["java";"lang"], "Long"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["haxe"], "Int64") []) ] *)
-	(** other std types *)
-	| TObject ( (["java";"lang"], "Object"), [] ) -> mk_type_path ctx ([], "Dynamic") []
-	| TObject ( (["java";"lang"], "String"), [] ) -> mk_type_path ctx ([], "String") []
-	| TObject ( (["java";"lang"], "Enum"), [_] ) -> mk_type_path ctx ([], "EnumValue") []
-	(** other types *)
-	| TObject ( path, [] ) ->
-		(match lookup_jclass ctx.jcom path with
-		| Some (jcl, _, _) -> mk_type_path ctx path (List.map (fun _ -> convert_arg ctx p TAny) jcl.ctypes)
-		| None -> mk_type_path ctx path [])
-	| TObject ( path, args ) -> mk_type_path ctx path (List.map (convert_arg ctx p) args)
-	| TObjectInner (pack, (name, params) :: inners) ->
-			let actual_param = match List.rev inners with
-			| (_, p) :: _ -> p
-			| _ -> assert false in
-			mk_type_path ctx (pack, name ^ "$" ^ String.concat "$" (List.map fst inners)) (List.map (fun param -> convert_arg ctx p param) actual_param)
-	| TObjectInner (pack, inners) -> assert false
-	| TArray (jsig, _) -> mk_type_path ctx (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig,null_pos) ]
-	| TMethod _ -> JReader.error "TMethod cannot be converted directly into Complex Type"
-	| TTypeParameter s -> (match ctx.jtparams with
-		| cur :: others ->
-			if has_tparam s cur then
-				mk_type_path ctx ([], s) []
-			else begin
-				if ctx.jcom.verbose && not(List.exists (has_tparam s) others) then print_endline ("Type parameter " ^ s ^ " was not found while building type!");
-				mk_type_path ctx ([], "Dynamic") []
-			end
-		| _ ->
-			if ctx.jcom.verbose then print_endline ("Empty type parameter stack!");
-			mk_type_path ctx ([], "Dynamic") [])
-
-let convert_constant ctx p const =
-	Option.map_default (function
-		| ConstString s -> Some (EConst (String s), p)
-		| ConstInt i -> Some (EConst (Int (Printf.sprintf "%ld" i)), p)
-		| ConstFloat f | ConstDouble f -> Some (EConst (Float (Printf.sprintf "%E" f)), p)
-		| _ -> None) None const
-
-let rec same_sig parent jsig =
-	match jsig with
-	| TObject (p,targs) -> parent = p || List.exists (function | TType (_,s) -> same_sig parent s | _ -> false) targs
-	| TObjectInner(p, ntargs) ->
-			parent = (p, String.concat "$" (List.map fst ntargs)) ||
-			List.exists (fun (_,targs) -> List.exists (function | TType(_,s) -> same_sig parent s | _ -> false) targs) ntargs
-	| TArray(s,_) -> same_sig parent s
-	| _ -> false
-
-let convert_param ctx p parent param =
-	let name, constraints = match param with
-		| (name, Some extends_sig, implem_sig) ->
-			name, extends_sig :: implem_sig
-		| (name, None, implemem_sig) ->
-			name, implemem_sig
-		in
-		let constraints = List.map (fun s -> if same_sig parent s then (TObject( (["java";"lang"], "Object"), [])) else s) constraints in
-		{
-			tp_name = name,null_pos;
-			tp_params = [];
-			tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) constraints;
-			tp_meta = [];
-		}
-
-let get_type_path ctx ct = match ct with | CTPath p -> p | _ -> assert false
-
-let is_override field =
-	List.exists (function | AttrVisibleAnnotations [{ ann_type = TObject( (["java";"lang"], "Override"), _ ) }] -> true | _ -> false) field.jf_attributes
-
-let mk_override field =
-	{ field with jf_attributes = ((AttrVisibleAnnotations [{ ann_type = TObject( (["java";"lang"], "Override"), [] ); ann_elements = [] }]) :: field.jf_attributes) }
-
-let del_override field =
-	{ field with jf_attributes = List.filter (fun a -> not (is_override_attrib a)) field.jf_attributes }
-
-let get_canonical ctx p pack name =
-	(Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst (String name), p], p)
-
-let convert_java_enum ctx p pe =
-	let meta = ref (get_canonical ctx p (fst pe.cpath) (snd pe.cpath) :: [Meta.Native, [EConst (String (real_java_path ctx pe.cpath) ), p], p ]) in
-	let data = ref [] in
-	List.iter (fun f ->
-		(* if List.mem JEnum f.jf_flags then *)
-		match f.jf_vmsignature with
-		| TObject( path, [] ) when path = pe.cpath && List.mem JStatic f.jf_flags && List.mem JFinal f.jf_flags ->
-			data := { ec_name = f.jf_name,null_pos; ec_doc = None; ec_meta = []; ec_args = []; ec_pos = p; ec_params = []; ec_type = None; } :: !data;
-		| _ -> ()
-	) pe.cfields;
-
-	EEnum {
-		d_name = jname_to_hx (snd pe.cpath),null_pos;
-		d_doc = None;
-		d_params = []; (* enums never have type parameters *)
-		d_meta = !meta;
-		d_flags = [EExtern];
-		d_data = List.rev !data;
-	}
-
-	let convert_java_field ctx p jc field =
-		let p = { p with pfile =	p.pfile ^" (" ^field.jf_name ^")" } in
-		let cff_doc = None in
-		let cff_pos = p in
-		let cff_meta = ref [] in
-		let cff_access = ref [] in
-		let cff_name = match field.jf_name with
-			| "<init>" -> "new"
-			| "<clinit>"-> raise Exit (* __init__ field *)
-			| name when String.length name > 5 ->
-					(match String.sub name 0 5 with
-					| "__hx_" | "this$" -> raise Exit
-					| _ -> name)
-			| name -> name
-		in
-		let jf_constant = ref field.jf_constant in
-		let readonly = ref false in
-
-		List.iter (function
-			| JPublic -> cff_access := APublic :: !cff_access
-			| JPrivate -> raise Exit (* private instances aren't useful on externs *)
-			| JProtected -> cff_access := APrivate :: !cff_access
-			| JStatic -> cff_access := AStatic :: !cff_access
-			| JFinal ->
-				cff_meta := (Meta.Final, [], p) :: !cff_meta;
-				(match field.jf_kind, field.jf_vmsignature, field.jf_constant with
-				| JKField, TObject _, _ ->
-					jf_constant := None
-				| JKField, _, Some _ ->
-					readonly := true;
-					jf_constant := None;
-				| _ -> jf_constant := None)
-			(* | JSynchronized -> cff_meta := (Meta.Synchronized, [], p) :: !cff_meta *)
-			| JVolatile -> cff_meta := (Meta.Volatile, [], p) :: !cff_meta
-			| JTransient -> cff_meta := (Meta.Transient, [], p) :: !cff_meta
-			(* | JVarArgs -> cff_meta := (Meta.VarArgs, [], p) :: !cff_meta *)
-			| _ -> ()
-		) field.jf_flags;
-
-		List.iter (function
-			| AttrDeprecated when jc.cpath <> (["java";"util"],"Date") -> cff_meta := (Meta.Deprecated, [], p) :: !cff_meta
-			(* TODO: pass anotations as @:meta *)
-			| AttrVisibleAnnotations ann ->
-				List.iter (function
-					| { ann_type = TObject( (["java";"lang"], "Override"), [] ) } ->
-						cff_access := AOverride :: !cff_access
-					| _ -> ()
-				) ann
-			| _ -> ()
-		) field.jf_attributes;
-
-		List.iter (fun jsig ->
-			match convert_signature ctx p jsig with
-				| CTPath path ->
-					cff_meta := (Meta.Throws, [Ast.EConst (Ast.String (s_type_path (path.tpackage,path.tname))), p],p) :: !cff_meta
-				| _ -> ()
-		) field.jf_throws;
-
-		let kind = match field.jf_kind with
-			| JKField when !readonly ->
-				FProp (("default",null_pos), ("null",null_pos), Some (convert_signature ctx p field.jf_signature,null_pos), None)
-			| JKField ->
-				FVar (Some (convert_signature ctx p field.jf_signature,null_pos), None)
-			| JKMethod ->
-				match field.jf_signature with
-				| TMethod (args, ret) ->
-					let old_types = ctx.jtparams in
-					(match ctx.jtparams with
-					| c :: others -> ctx.jtparams <- (c @ field.jf_types) :: others
-					| [] -> ctx.jtparams <- field.jf_types :: []);
-					let i = ref 0 in
-					let args = List.map (fun s ->
-						incr i;
-						("param" ^ string_of_int !i,null_pos), false, [], Some(convert_signature ctx p s,null_pos), None
-					) args in
-					let t = Option.map_default (convert_signature ctx p) (mk_type_path ctx ([], "Void") []) ret in
-					cff_meta := (Meta.Overload, [], p) :: !cff_meta;
-
-					let types = List.map (function
-						| (name, Some ext, impl) ->
-							{
-								tp_name = name,null_pos;
-								tp_params = [];
-								tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (ext :: impl);
-								tp_meta = [];
-							}
-						| (name, None, impl) ->
-							{
-								tp_name = name,null_pos;
-								tp_params = [];
-								tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (impl);
-								tp_meta = [];
-							}
-					) field.jf_types in
-					ctx.jtparams <- old_types;
-
-					FFun ({
-						f_params = types;
-						f_args = args;
-						f_type = Some (t,null_pos);
-						f_expr = None
-					})
-				| _ -> error "Method signature was expected" p
-		in
-		let cff_name, cff_meta =
-			match String.get cff_name 0 with
-				| '%' ->
-					let name = (String.sub cff_name 1 (String.length cff_name - 1)) in
-					if not (is_haxe_keyword name) then
-						cff_meta := (Meta.Deprecated, [EConst(String(
-							"This static field `_" ^ name ^ "` is deprecated and will be removed in later versions. Please use `" ^ name ^ "` instead")
-						),p], p) :: !cff_meta;
-					"_" ^ name,
-					(Meta.Native, [EConst (String (name) ), cff_pos], cff_pos) :: !cff_meta
-				| _ ->
-					match String.nsplit cff_name "$" with
-						| [ no_dollar ] ->
-							cff_name, !cff_meta
-						| parts ->
-							String.concat "_" parts,
-							(Meta.Native, [EConst (String (cff_name) ), cff_pos], cff_pos) :: !cff_meta
-		in
-		if PMap.mem "java_loader_debug" ctx.jcom.defines then
-			Printf.printf "\t%s%sfield %s : %s\n" (if List.mem AStatic !cff_access then "static " else "") (if List.mem AOverride !cff_access then "override " else "") cff_name (s_sig field.jf_signature);
-
-		{
-			cff_name = cff_name,null_pos;
-			cff_doc = cff_doc;
-			cff_pos = cff_pos;
-			cff_meta = cff_meta;
-			cff_access = !cff_access;
-			cff_kind = kind
-		}
-
-	let rec japply_params params jsig = match params with
-	| [] -> jsig
-	| _ -> match jsig with
-		| TTypeParameter s -> (try
-			List.assoc s params
-		with | Not_found -> jsig)
-		| TObject(p,tl) ->
-			TObject(p, args params tl)
-		| TObjectInner(sl, stll) ->
-			TObjectInner(sl, List.map (fun (s,tl) -> (s, args params tl)) stll)
-		| TArray(s,io) ->
-			TArray(japply_params params s, io)
-		| TMethod(sl, sopt) ->
-			TMethod(List.map (japply_params params) sl, Option.map (japply_params params) sopt)
-		| _ -> jsig
-
-	and args params tl = match params with
-	| [] -> tl
-	| _ -> List.map (function
-		| TAny -> TAny
-		| TType(w,s) -> TType(w,japply_params params s)) tl
-
-	let mk_params jtypes = List.map (fun (s,_,_) -> (s,TTypeParameter s)) jtypes
-
-	let convert_java_class ctx p jc =
-		match List.mem JEnum jc.cflags with
-		| true -> (* is enum *)
-				[convert_java_enum ctx p jc]
-		| false ->
-			let flags = ref [HExtern] in
-			if PMap.mem "java_loader_debug" ctx.jcom.defines then begin
-				let sup = jc.csuper :: jc.cinterfaces in
-				print_endline ("converting " ^ (if List.mem JAbstract jc.cflags then "abstract " else "") ^ JData.path_s jc.cpath ^ " : " ^ (String.concat ", " (List.map s_sig sup)));
-			end;
-			(* todo: instead of JavaNative, use more specific definitions *)
-			let meta = ref [Meta.JavaNative, [], p; Meta.Native, [EConst (String (real_java_path ctx jc.cpath) ), p], p; get_canonical ctx p (fst jc.cpath) (snd jc.cpath)] in
-			let force_check = Common.defined ctx.jcom Define.ForceLibCheck in
-			if not force_check then
-				meta := (Meta.LibType,[],p) :: !meta;
-
-			let is_interface = ref false in
-			List.iter (fun f -> match f with
-				| JFinal -> meta := (Meta.Final, [], p) :: !meta
-				| JInterface ->
-						is_interface := true;
-						flags := HInterface :: !flags
-				| JAbstract -> meta := (Meta.Abstract, [], p) :: !meta
-				| JAnnotation -> meta := (Meta.Annotation, [], p) :: !meta
-				| _ -> ()
-			) jc.cflags;
-
-			(match jc.csuper with
-				| TObject( (["java";"lang"], "Object"), _ ) -> ()
-				| TObject( (["haxe";"lang"], "HxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta
-				| _ -> flags := HExtends (get_type_path ctx (convert_signature ctx p jc.csuper),null_pos) :: !flags
-			);
-
-			List.iter (fun i ->
-				match i with
-				| TObject ( (["haxe";"lang"], "IHxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta
-				| _ -> flags :=
-					if !is_interface then
-						HExtends (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
-					else
-						HImplements (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
-			) jc.cinterfaces;
-
-			let fields = ref [] in
-			let jfields = ref [] in
-
-			if jc.cpath <> (["java";"lang"], "CharSequence") then
-				List.iter (fun f ->
-					try
-						if !is_interface && List.mem JStatic f.jf_flags then
-							()
-						else begin
-							fields := convert_java_field ctx p jc f :: !fields;
-							jfields := f :: !jfields
-						end
-					with
-						| Exit -> ()
-				) (jc.cfields @ jc.cmethods);
-
-			(* make sure the throws types are imported correctly *)
-			let imports = List.concat (List.map (fun f ->
-				List.map (fun jsig ->
-					match convert_signature ctx p jsig with
-						| CTPath path ->
-							let pos = { p with pfile = p.pfile ^ " (" ^ f.jf_name ^" @:throws)" } in
-							EImport( List.map (fun s -> s,pos) (path.tpackage @ [path.tname]), INormal )
-						| _ -> assert false
-				) f.jf_throws
-			) jc.cmethods) in
-
-			(EClass {
-				d_name = jname_to_hx (snd jc.cpath),null_pos;
-				d_doc = None;
-				d_params = List.map (convert_param ctx p jc.cpath) jc.ctypes;
-				d_meta = !meta;
-				d_flags = !flags;
-				d_data = !fields;
-			}) :: imports
-
-	let create_ctx com =
-		{
-			jcom = com;
-			jtparams = [];
-		}
-
-	let rec has_type_param = function
-		| TTypeParameter _ -> true
-		| TMethod (lst, opt) -> List.exists has_type_param lst || Option.map_default has_type_param false opt
-		| TArray (s,_) -> has_type_param s
-		| TObjectInner (_, stpl) -> List.exists (fun (_,sigs) -> List.exists has_type_param_arg sigs) stpl
-		| TObject(_, pl) -> List.exists has_type_param_arg pl
-		| _ -> false
-
-	and has_type_param_arg = function | TType(_,s) -> has_type_param s | _ -> false
-
-let rec japply_params jparams jsig = match jparams with
-	| [] -> jsig
-	| _ ->
-		match jsig with
-		| TObject(path,p) ->
-			TObject(path, List.map (japply_params_tp jparams ) p)
-		| TObjectInner(sl,stargl) ->
-			TObjectInner(sl,List.map (fun (s,targ) -> (s, List.map (japply_params_tp jparams) targ)) stargl)
-		| TArray(jsig,io) ->
-			TArray(japply_params jparams jsig,io)
-		| TMethod(args,ret) ->
-			TMethod(List.map (japply_params jparams ) args, Option.map (japply_params jparams ) ret)
-		| TTypeParameter s -> (try
-			List.assoc s jparams
-		with | Not_found -> jsig)
-		| _ -> jsig
-
-
-and japply_params_tp jparams jtype_argument = match jtype_argument with
-	| TAny -> TAny
-	| TType(w,jsig) -> TType(w,japply_params jparams jsig)
-
-let mk_jparams jtypes params = match jtypes, params with
-	| [], [] -> []
-	| _, [] -> List.map (fun (s,_,_) -> s, TObject( (["java";"lang"], "Object"), [] ) ) jtypes
-	| _ -> List.map2 (fun (s,_,_) jt -> match jt with
-		| TAny -> s, TObject((["java";"lang"],"Object"),[])
-		| TType(_,jsig) -> s, jsig) jtypes params
-
-let rec compatible_signature_arg ?arg_test f1 f2 =
-	let arg_test = match arg_test with
-		| None -> (fun _ _ -> true)
-		| Some a -> a
-	in
-	if f1 = f2 then
-		true
-	else match f1, f2 with
-	| TObject(p,a), TObject(p2,a2) -> p = p2 && arg_test a a2
-	| TObjectInner(sl, stal), TObjectInner(sl2, stal2) -> sl = sl2 && List.map fst stal = List.map fst stal2
-	| TArray(s,_) , TArray(s2,_) -> compatible_signature_arg s s2
-	| TTypeParameter t1 , TTypeParameter t2 -> t1 = t2
-	| _ -> false
-
-let rec compatible_param p1 p2 = match p1, p2 with
-	| TType (_,s1), TType(_,s2) -> compatible_signature_arg ~arg_test:compatible_tparams s1 s2
-	| TAny, TType(_, TObject( (["java";"lang"],"Object"), _ )) -> true
-	| TType(_, TObject( (["java";"lang"],"Object"), _ )), TAny -> true
-	| _ -> false
-
-and compatible_tparams p1 p2 = try match p1, p2 with
-	| [], [] -> true
-	| _, [] ->
-		let p2 = List.map (fun _ -> TAny) p1 in
-		List.for_all2 compatible_param p1 p2
-	| [], _ ->
-		let p1 = List.map (fun _ -> TAny) p2 in
-		List.for_all2 compatible_param p1 p2
-	| _, _ ->
-		List.for_all2 compatible_param p1 p2
-	with | Invalid_argument("List.for_all2") -> false
-
-let get_adapted_sig f f2 = match f.jf_types with
-	| [] ->
-		f.jf_signature
-	| _ ->
-		let jparams = mk_jparams f.jf_types (List.map (fun (s,_,_) -> TType(WNone, TTypeParameter s)) f2.jf_types) in
-		japply_params jparams f.jf_signature
-
-let compatible_methods f1 f2 =
-	if List.length f1.jf_types <> List.length f2.jf_types then
-		false
-	else match (get_adapted_sig f1 f2), f2.jf_signature with
-	| TMethod(a1,_), TMethod(a2,_) when List.length a1 = List.length a2 ->
-		List.for_all2 compatible_signature_arg a1 a2
-	| _ -> false
-
-let jcl_from_jsig com jsig =
-	let path, params = match jsig with
-	| TObject(path, params) ->
-		path,params
-	| TObjectInner(sl, stll) ->
-		let last_params = ref [] in
-		let real_path = sl, String.concat "$" (List.map (fun (s,p) -> last_params := p; s) stll) in
-		real_path, !last_params
-	| _ -> raise Not_found
-	in
-	match lookup_jclass com path with
-	| None -> raise Not_found
-	| Some(c,_,_) -> c,params
-
-let jclass_with_params com cls params = try
-	match cls.ctypes with
-	| [] -> cls
-	| _ ->
-		let jparams = mk_jparams cls.ctypes params in
-		{ cls with
-			cfields = List.map (fun f -> { f with jf_signature = japply_params jparams f.jf_signature }) cls.cfields;
-			cmethods = List.map (fun f -> { f with jf_signature = japply_params jparams f.jf_signature }) cls.cmethods;
-			csuper = japply_params jparams cls.csuper;
-			cinterfaces = List.map (japply_params jparams) cls.cinterfaces;
-		}
-	with Invalid_argument("List.map2") ->
-		if com.verbose then prerr_endline ("Differing parameters for class: " ^ s_type_path cls.cpath);
-		cls
-
-let is_object = function | TObject( (["java";"lang"], "Object"), [] ) -> true | _ -> false
-
-let is_tobject = function | TObject _ | TObjectInner _ -> true | _ -> false
-
-let simplify_args args =
-	if List.for_all (function | TAny -> true | _ -> false) args then [] else args
-
-let compare_type com s1 s2 =
-	if s1 = s2 then
-		0
-	else if not (is_tobject s1) then
-		if is_tobject s2 then (* Dynamic *)
-			1
-		else if compatible_signature_arg s1 s2 then
-			0
-		else
-			raise Exit
-	else if not (is_tobject s2) then
-		-1
-	else begin
-		let rec loop ?(first_error=true) s1 s2 : bool =
-			if is_object s1 then
-				s1 = s2
-			else if compatible_signature_arg s1 s2 then begin
-				let p1, p2 = match s1, s2 with
-				| TObject(_, p1), TObject(_,p2) ->
-					p1, p2
-				| TObjectInner(_, npl1), TObjectInner(_, npl2) ->
-					snd (List.hd (List.rev npl1)), snd (List.hd (List.rev npl2))
-				| _ -> assert false (* not tobject *)
-				in
-				let p1, p2 = simplify_args p1, simplify_args p2 in
-				let lp1 = List.length p1 in
-				let lp2 = List.length p2 in
-				if lp1 > lp2 then
-					true
-				else if lp2 > lp1 then
-					false
-				else begin
-					(* if compatible tparams, it's fine *)
-					if not (compatible_tparams p1 p2) then
-						raise Exit; (* meaning: found, but incompatible type parameters *)
-					true
-				end
-			end else try
-				let c, p = jcl_from_jsig com s1 in
-				let jparams = mk_jparams c.ctypes p in
-				let super = japply_params jparams c.csuper in
-				let implements = List.map (japply_params jparams) c.cinterfaces in
-				loop ~first_error:first_error super s2 || List.exists (fun super -> loop ~first_error:first_error super s2) implements
-			with | Not_found ->
-				prerr_endline ("-java-lib: The type " ^ (s_sig s1) ^ " is referred but was not found. Compilation may not occur correctly.");
-				prerr_endline "Did you forget to include a needed lib?";
-				if first_error then
-					not (loop ~first_error:false s2 s1)
-				else
-					false
-		in
-		if loop s1 s2 then
-			if loop s2 s1 then
-				0
-			else
-				1
-		else
-			if loop s2 s1 then
-				-1
-			else
-				-2
-	end
-
-(* given a list of same overload functions, choose the best (or none) *)
-let select_best com flist =
-	let rec loop cur_best = function
-		| [] ->
-			Some cur_best
-		| f :: flist -> match get_adapted_sig f cur_best, cur_best.jf_signature with
-			| TMethod(_,Some r), TMethod(_, Some r2) -> (try
-				match compare_type com r r2 with
-				| 0 -> (* same type - select any of them *)
-					loop cur_best flist
-				| 1 ->
-					loop f flist
-				| -1 ->
-					loop cur_best flist
-				| -2 -> (* error - no type is compatible *)
-					if com.verbose then prerr_endline (f.jf_name ^ ": The types " ^ (s_sig r) ^ " and " ^ (s_sig r2) ^ " are incompatible");
-					(* bet that the current best has "beaten" other types *)
-					loop cur_best flist
-				| _ -> assert false
-			with | Exit -> (* incompatible type parameters *)
-				(* error mode *)
-				if com.verbose then prerr_endline (f.jf_name ^ ": Incompatible argument return signatures: " ^ (s_sig r) ^ " and " ^ (s_sig r2));
-				None)
-			| TMethod _, _ -> (* select the method *)
-				loop f flist
-			| _ ->
-				loop cur_best flist
-	in
-	match loop (List.hd flist) (List.tl flist) with
-	| Some f ->
-		Some f
-	| None -> match List.filter (fun f -> not (is_override f)) flist with
-		(* error mode; take off all override methods *)
-		| [] -> None
-		| f :: [] -> Some f
-		| f :: flist -> Some f (* pick one *)
-
-(**** begin normalize_jclass helpers ****)
-
-let fix_overrides_jclass com cls =
-	let force_check = Common.defined com Define.ForceLibCheck in
-	let methods = if force_check then List.map (fun f -> del_override f) cls.cmethods else cls.cmethods in
-	let cmethods = methods in
-	let super_fields = [] in
-	let super_methods = [] in
-	let nonstatics = List.filter (fun f -> not (List.mem JStatic f.jf_flags)) (cls.cfields @ cls.cmethods) in
-
-	let is_pub = fun f -> List.exists (function | JPublic | JProtected -> true | _ -> false) f.jf_flags in
-	let cmethods, super_fields = if not (List.mem JInterface cls.cflags) then
-		List.filter is_pub cmethods,
-		List.filter is_pub super_fields
-	else
-		cmethods,super_fields
-	in
-
-	let rec loop cls super_methods super_fields cmethods nonstatics = try
-		match cls.csuper with
-		| TObject((["java";"lang"],"Object"),_) ->
-				super_methods,super_fields,cmethods,nonstatics
-		| _ ->
-			let cls, params = jcl_from_jsig com cls.csuper in
-			let cls = jclass_with_params com cls params in
-			let nonstatics = (List.filter (fun f -> (List.mem JStatic f.jf_flags)) (cls.cfields @ cls.cmethods)) @ nonstatics in
-			let super_methods = cls.cmethods @ super_methods in
-			let super_fields = cls.cfields @ super_fields in
-			let cmethods = if force_check then begin
-				let overriden = ref [] in
-				let cmethods = List.map (fun jm ->
-					(* TODO rewrite/standardize empty spaces *)
-					if not (is_override jm) && not (List.mem JStatic jm.jf_flags) && List.exists (fun msup ->
-						let ret = msup.jf_name = jm.jf_name && not(List.mem JStatic msup.jf_flags) && compatible_methods msup jm in
-						if ret then begin
-							let f = mk_override msup in
-							overriden := { f with jf_flags = jm.jf_flags } :: !overriden
-						end;
-						ret
-					) cls.cmethods then
-						mk_override jm
-					else
-						jm
-				) cmethods in
-				!overriden @ cmethods
-			end else
-				cmethods
-			in
-			loop cls super_methods super_fields cmethods nonstatics
-		with | Not_found ->
-			super_methods,super_fields,cmethods,nonstatics
-	in
-	loop cls super_methods super_fields cmethods nonstatics
-
-let normalize_jclass com cls =
-	(* after adding the noCheck metadata, this option will annotate what changes were needed *)
-	(* and that are now deprecated *)
-	let force_check = Common.defined com Define.ForceLibCheck in
-	(* fix overrides *)
-	let super_methods, super_fields, cmethods, nonstatics = fix_overrides_jclass com cls in
-	let all_methods = cmethods @ super_methods in
-
-	(* look for interfaces and add missing implementations (may happen on abstracts or by vmsig differences *)
-	(* (libType): even with libType enabled, we need to add these missing fields - otherwise we won't be able to use them from Haxe *)
-	let added_interface_fields = ref [] in
-	let rec loop_interface abstract cls iface = try
-		match iface with
-			| TObject ((["java";"lang"],"Object"), _) -> ()
-			| TObject (path,_) when path = cls.cpath -> ()
-			| _ ->
-				let cif, params = jcl_from_jsig com iface in
-				let cif = jclass_with_params com cif params in
-				List.iter (fun jf ->
-					if not(List.mem JStatic jf.jf_flags) && not (List.exists (fun jf2 -> jf.jf_name = jf2.jf_name && not (List.mem JStatic jf2.jf_flags) && jf.jf_signature = jf2.jf_signature) all_methods) then begin
-						let jf = if abstract && force_check then del_override jf else jf in
-						let jf = { jf with jf_flags = JPublic :: jf.jf_flags } in (* interfaces implementations are always public *)
-
-						added_interface_fields := jf :: !added_interface_fields;
-					end
-				) cif.cmethods;
-				(* we don't need to loop again in the interface unless we are in an abstract class, since these interfaces are already normalized *)
-				if abstract then List.iter (loop_interface abstract cif) cif.cinterfaces;
-		with Not_found -> ()
-	in
-	List.iter (loop_interface (List.mem JAbstract cls.cflags) cls) cls.cinterfaces;
-	let nonstatics = !added_interface_fields @ nonstatics in
-	let cmethods = !added_interface_fields @ cmethods in
-
-	(* for each added field in the interface, lookup in super_methods possible methods to include *)
-	(* so we can choose the better method still *)
-	let cmethods = if not force_check then
-		cmethods
-	else
-		List.fold_left (fun cmethods im ->
-			(* see if any of the added_interface_fields need to be declared as override *)
-			let f = List.find_all (fun jf -> jf.jf_name = im.jf_name && compatible_methods jf im) super_methods in
-			let f = List.map mk_override f in
-			f @ cmethods
-		) cmethods !added_interface_fields;
-	in
-
-	(* take off equals, hashCode and toString from interface *)
-	let cmethods = if List.mem JInterface cls.cflags then List.filter (fun jf -> match jf.jf_name, jf.jf_vmsignature with
-			| "equals", TMethod([TObject( (["java";"lang"],"Object"), _)],_)
-			| "hashCode", TMethod([], _)
-			| "toString", TMethod([], _) -> false
-			| _ -> true
-	) cmethods
-	else
-		cmethods
-	in
-
-	(* change field name to not collide with haxe keywords and with static/non-static members *)
-	let fold_field acc f =
-		let change, both = match f.jf_name with
-		| _ when List.mem JStatic f.jf_flags && List.exists (fun f2 -> f.jf_name = f2.jf_name) nonstatics -> true, true
-		| _ -> is_haxe_keyword f.jf_name, false
-		in
-		let f2 = if change then
-				{ f with jf_name = "%" ^ f.jf_name }
-			else
-				f
-		in
-		if both then f :: f2 :: acc else f2 :: acc
-	in
-
-	(* change static fields that have the same name as methods *)
-	let cfields = List.fold_left fold_field [] cls.cfields in
-	let cmethods = List.fold_left fold_field [] cmethods in
-	(* take off variable fields that have the same name as methods *)
-	(* and take off variables that already have been declared *)
-	let filter_field f f2 = f != f2 && (List.mem JStatic f.jf_flags = List.mem JStatic f2.jf_flags) && f.jf_name = f2.jf_name && f2.jf_kind <> f.jf_kind in
-	let cfields = List.filter (fun f ->
-		if List.mem JStatic f.jf_flags then
-			not (List.exists (filter_field f) cmethods)
-		else
-			not (List.exists (filter_field f) nonstatics) && not (List.exists (fun f2 -> f != f2 && f.jf_name = f2.jf_name && not (List.mem JStatic f2.jf_flags)) super_fields) ) cfields
-	in
-	(* now filter any method that clashes with a field - on a superclass *)
-	let cmethods = if force_check then List.filter (fun f ->
-		if List.mem JStatic f.jf_flags then
-			true
-		else
-			not (List.exists (filter_field f) super_fields) ) cmethods
-	else
-		cmethods
-	in
-	(* removing duplicate fields. They are there because of return type covariance in Java *)
-	(* Also, if a method overrides a previous definition, and changes a type parameters' variance, *)
-	(* we will take it off *)
-	(* this means that some rare codes will never compile on Haxe, but unless Haxe adds variance support *)
-	(* I can't see how this can be any different *)
-	let rec loop acc = function
-		| [] -> acc
-		| f :: cmeths ->
-			match List.partition (fun f2 -> f.jf_name = f2.jf_name && compatible_methods f f2) cmeths with
-			| [], cmeths ->
-				loop (f :: acc) cmeths
-			| flist, cmeths -> match select_best com (f :: flist) with
-				| None ->
-					loop acc cmeths
-				| Some f ->
-					loop (f :: acc) cmeths
-	in
-	(* last pass: take off all cfields that are internal / private (they won't be accessible anyway) *)
-	let cfields = List.filter(fun f -> List.exists (fun f -> f = JPublic || f = JProtected) f.jf_flags) cfields in
-	let cmethods = loop [] cmethods in
-	{ cls with cfields = cfields; cmethods = cmethods }
-
-(**** end normalize_jclass helpers ****)
-
-let get_classes_zip zip =
-	let ret = ref [] in
-	List.iter (function
-		| { Zip.is_directory = false; Zip.filename = f } when (String.sub (String.uncapitalize f) (String.length f - 6) 6) = ".class" && not (String.exists f "$") ->
-				(match List.rev (String.nsplit f "/") with
-				| clsname :: pack ->
-					if not (String.contains clsname '$') then begin
-						let path = jpath_to_hx (List.rev pack, String.sub clsname 0 (String.length clsname - 6)) in
-						ret := path :: !ret
-					end
-				| _ ->
-						ret := ([], jname_to_hx f) :: !ret)
-		| _ -> ()
-	) (Zip.entries zip);
-	!ret
-
-let add_java_lib com file std =
-	let file = if Sys.file_exists file then
-		file
-	else try Common.find_file com file with
-		| Not_found -> try Common.find_file com (file ^ ".jar") with
-		| Not_found ->
-			failwith ("Java lib " ^ file ^ " not found")
-	in
-	let hxpack_to_jpack = Hashtbl.create 16 in
-	let get_raw_class, close, list_all_files =
-		(* check if it is a directory or jar file *)
-		match (Unix.stat file).st_kind with
-		| S_DIR -> (* open classes directly from directory *)
-			let all = ref [] in
-			let rec iter_files pack dir path = try
-				let file = Unix.readdir dir in
-				let filepath = path ^ "/" ^ file in
-				(if String.ends_with file ".class" && not (String.exists file "$") then
-					let file = String.sub file 0 (String.length file - 6) in
-					let path = jpath_to_hx (pack,file) in
-					all := path :: !all;
-					Hashtbl.add hxpack_to_jpack path (pack,file)
-				else if (Unix.stat filepath).st_kind = S_DIR && file <> "." && file <> ".." then
-					let pack = pack @ [file] in
-					iter_files (pack) (Unix.opendir filepath) filepath);
-				iter_files pack dir path
-			with | End_of_file | Unix.Unix_error _ ->
-				Unix.closedir dir
-			in
-			iter_files [] (Unix.opendir file) file;
-			let all = !all in
-
-			(fun (pack, name) ->
-				let real_path = file ^ "/" ^ (String.concat "/" pack) ^ "/" ^ (name ^ ".class") in
-				try
-					let data = Std.input_file ~bin:true real_path in
-					Some(JReader.parse_class (IO.input_string data), real_path, real_path)
-				with
-					| _ -> None), (fun () -> ()), (fun () -> all)
-		| _ -> (* open zip file *)
-			let closed = ref false in
-			let zip = ref (Zip.open_in file) in
-			let check_open () =
-				if !closed then begin
-					prerr_endline ("JAR file " ^ file ^ " already closed"); (* if this happens, find when *)
-					zip := Zip.open_in file;
-					closed := false
-				end
-			in
-			List.iter (function
-				| { Zip.is_directory = false; Zip.filename = filename } when String.ends_with filename ".class" ->
-					let pack = String.nsplit filename "/" in
-					(match List.rev pack with
-						| [] -> ()
-						| name :: pack ->
-							let name = String.sub name 0 (String.length name - 6) in
-							let pack = List.rev pack in
-							Hashtbl.add hxpack_to_jpack (jpath_to_hx (pack,name)) (pack,name))
-				| _ -> ()
-			) (Zip.entries !zip);
-			(fun (pack, name) ->
-				check_open();
-				try
-					let location = (String.concat "/" (pack @ [name]) ^ ".class") in
-					let entry = Zip.find_entry !zip location in
-					let data = Zip.read_entry !zip entry in
-					Some(JReader.parse_class (IO.input_string data), file, file ^ "@" ^ location)
-				with
-					| Not_found ->
-						None),
-			(fun () -> if not !closed then begin closed := true; Zip.close_in !zip end),
-			(fun () -> check_open(); get_classes_zip !zip)
-	in
-	let cached_types = Hashtbl.create 12 in
-	let get_raw_class path =
-		try
-			Hashtbl.find cached_types path
-		with | Not_found -> try
-			let pack, name = Hashtbl.find hxpack_to_jpack path in
-			let try_file (pack,name) =
-				match get_raw_class (pack,name) with
-				| None ->
-						Hashtbl.add cached_types path None;
-						None
-				| Some (i, p1, p2) ->
-						Hashtbl.add cached_types path (Some(i,p1,p2)); (* type loop normalization *)
-						let ret = Some (normalize_jclass com i, p1, p2) in
-						Hashtbl.replace cached_types path ret;
-						ret
-			in
-			try_file (pack,name)
-		with Not_found ->
-			None
-	in
-	let replace_canonical_name p pack name_original name_replace decl =
-		let mk_meta name = (Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst(String name), p], p) in
-		let add_meta name metas =
-			if Meta.has Meta.JavaCanonical metas then
-				List.map (function
-					| (Meta.JavaCanonical,[EConst (String cpack), _; EConst(String cname), _],_) ->
-						let did_replace,name = String.replace cname name_original name_replace in
-						if not did_replace then print_endline (cname ^ " -> " ^ name_original ^ " -> " ^ name_replace);
-						mk_meta name
-					| m -> m
-				) metas
-			else
-				mk_meta name :: metas
-		in
-		match decl with
-			| EClass c ->
-				EClass { c with d_meta = add_meta (fst c.d_name) c.d_meta }
-			| EEnum e ->
-				EEnum { e with d_meta = add_meta (fst e.d_name) e.d_meta }
-			| EAbstract a ->
-				EAbstract { a with d_meta = add_meta (fst a.d_name) a.d_meta }
-			| d -> d
-	in
-	let rec build ctx path p types =
-		try
-			if List.mem path !types then
-				None
-			else begin
-				let first = match !types with
-					| [ ["java";"lang"], "String" ] | [] -> true
-					| p :: _ ->
-						false
-				in
-				types := path :: !types;
-				match get_raw_class path, path with
-				| None, ([], c) -> build ctx (["haxe";"root"], c) p types
-				| None, _ -> None
-				| Some (cls, real_path, pos_path), _ ->
-						let is_disallowed_inner = first && String.exists (snd cls.cpath) "$" in
-						let is_disallowed_inner = if is_disallowed_inner then begin
-								let outer, inner = String.split (snd cls.cpath) "$" in
-								match get_raw_class (fst path, outer) with
-									| None -> false
-									| _ -> true
-							end else
-								false
-						in
-						if is_disallowed_inner then
-							None
-						else begin
-							if com.verbose then print_endline ("Parsed Java class " ^ (s_type_path cls.cpath));
-							let old_types = ctx.jtparams in
-							ctx.jtparams <- cls.ctypes :: ctx.jtparams;
-
-							let pos = { pfile = pos_path; pmin = 0; pmax = 0; } in
-
-							let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
-
-							let ppath = Hashtbl.find hxpack_to_jpack path in
-							let inner = List.fold_left (fun acc (path,out,_,_) ->
-								let path = jpath_to_hx path in
-								(if out <> Some ppath then
-									acc
-								else match build ctx path p types with
-									| Some(_,(_, classes)) ->
-										let base = snd ppath ^ "$" in
-										(List.map (fun (def,p) ->
-											replace_canonical_name p (fst ppath) base (snd ppath ^ ".") def, p) classes) @ acc
-									| _ -> acc);
-							) [] cls.cinner_types in
-
-							(* add _Statics class *)
-							let inner = try
-								if not (List.mem JInterface cls.cflags) then raise Not_found;
-								let smethods = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cmethods in
-								let sfields = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cfields in
-								if not (smethods <> [] || sfields <> []) then raise Not_found;
-								let obj = TObject( (["java";"lang"],"Object"), []) in
-								let ncls = convert_java_class ctx pos { cls with cmethods = smethods; cfields = sfields; cflags = []; csuper = obj; cinterfaces = []; cinner_types = []; ctypes = [] } in
-								match ncls with
-								| EClass c :: imports ->
-									(EClass { c with d_name = (fst c.d_name ^ "_Statics"),snd c.d_name }, pos) :: inner @ List.map (fun i -> i,pos) imports
-								| _ -> assert false
-							with | Not_found ->
-								inner
-							in
-							let inner_alias = ref SS.empty in
-							List.iter (fun x ->
-								match fst x with
-								| EClass c ->
-									inner_alias := SS.add (fst c.d_name) !inner_alias;
-								| _ -> ()
-							) inner;
-							let alias_list = ref [] in
-							List.iter (fun x ->
-								match x with
-								| (EClass c, pos) -> begin
-									let parts = String.nsplit (fst c.d_name) "_24" in
-									match parts with
-										| _ :: _ ->
-											let alias_name = String.concat "_" parts in
-											if (not (SS.mem alias_name !inner_alias)) && (not (String.exists (snd path) "_24")) then begin
-												let alias_def = ETypedef {
-													d_name = alias_name,null_pos;
-													d_doc = None;
-													d_params = c.d_params;
-													d_meta = [];
-													d_flags = [];
-													d_data = CTPath {
-														tpackage = pack;
-														tname = snd path;
-														tparams = List.map (fun tp ->
-															TPType (CTPath {
-																tpackage = [];
-																tname = fst tp.tp_name;
-																tparams = [];
-																tsub = None;
-															},null_pos)
-														) c.d_params;
-														tsub = Some(fst c.d_name);
-													},null_pos;
-												} in
-												inner_alias := SS.add alias_name !inner_alias;
-												alias_list := (alias_def, pos) :: !alias_list;
-											end
-										| _ -> ()
-								end
-								| _ -> ()
-							) inner;
-							let inner = List.concat [!alias_list ; inner] in
-							let classes = List.map (fun t -> t,pos) (convert_java_class ctx pos cls) in
-							let imports, defs = List.partition (function | (EImport(_),_) -> true | _ -> false) (classes @ inner) in
-							let ret = Some ( real_path, (pack, imports @ defs) ) in
-							ctx.jtparams <- old_types;
-							ret
-						end
-			end
-		with
-		| JReader.Error_message msg ->
-			prerr_endline ("Class reader failed: " ^ msg);
-			None
-		| e ->
-			if com.verbose then begin
-				(* prerr_endline (Printexc.get_backtrace ()); requires ocaml 3.11 *)
-				prerr_endline (Printexc.to_string e)
-			end;
-			None
-	in
-	let build path p = build (create_ctx com) path p (ref [["java";"lang"], "String"]) in
-	let cached_files = ref None in
-	let list_all_files () = match !cached_files with
-		| None ->
-				let ret = list_all_files () in
-				cached_files := Some ret;
-				ret
-		| Some r -> r
-	in
-
-	(* TODO: add_dependency m mdep *)
-	com.load_extern_type <- com.load_extern_type @ [build];
-	com.java_libs <- (file, std, close, list_all_files, get_raw_class) :: com.java_libs

+ 1 - 1
src/macro/macroApi.ml

@@ -1761,7 +1761,7 @@ let macro_api ccom get_api =
 			let com = ccom() in
 			(match com.platform with
 			| Globals.Flash -> Genswf.add_swf_lib com file false
-			| Globals.Java -> Genjava.add_java_lib com file false
+			| Globals.Java -> Java.add_java_lib com file false
 			| Globals.Cs ->
 				let file, is_std = match ExtString.String.nsplit file "@" with
 					| [file] ->

+ 1155 - 0
src/typing/java.ml

@@ -0,0 +1,1155 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2017  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*)
+open Unix
+open ExtString
+open Common
+open Globals
+open Ast
+open JData
+
+(** Java lib *)
+
+module SS = Set.Make(String)
+
+type java_lib_ctx = {
+	jcom : Common.context;
+	(* current tparams context *)
+	mutable jtparams : jtypes list;
+}
+
+exception ConversionError of string * pos
+
+let error s p = raise (ConversionError (s, p))
+
+let is_haxe_keyword = function
+	| "cast" | "extern" | "function" | "in" | "typedef" | "using" | "var" | "untyped" | "inline" -> true
+	| _ -> false
+
+let jname_to_hx name =
+	let name =
+		if name <> "" && (String.get name 0 < 'A' || String.get name 0 > 'Z') then
+			Char.escaped (Char.uppercase (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
+		else
+			name
+	in
+	let name = String.concat "__" (String.nsplit name "_") in
+	String.map (function | '$' -> '_' | c -> c) name
+
+let normalize_pack pack =
+	List.map (function
+		| "" -> ""
+		| str when String.get str 0 >= 'A' && String.get str 0 <= 'Z' ->
+			String.lowercase str
+		| str -> str
+	) pack
+
+let jpath_to_hx (pack,name) = match pack, name with
+	| ["haxe";"root"], name -> [], name
+	| "com" :: ("oracle" | "sun") :: _, _
+	| "javax" :: _, _
+	| "org" :: ("ietf" | "jcp" | "omg" | "w3c" | "xml") :: _, _
+	| "sun" :: _, _
+	| "sunw" :: _, _ -> "java" :: normalize_pack pack, jname_to_hx name
+	| pack, name -> normalize_pack pack, jname_to_hx name
+
+let real_java_path ctx (pack,name) =
+	s_type_path (pack, name)
+
+let lookup_jclass com path =
+	let path = jpath_to_hx path in
+	List.fold_right (fun (_,_,_,_,get_raw_class) acc ->
+		match acc with
+		| None -> get_raw_class path
+		| Some p -> Some p
+	) com.java_libs None
+
+let mk_type_path ctx path params =
+	let name, sub = try
+		let p, _ = String.split (snd path) "$" in
+		jname_to_hx p, Some (jname_to_hx (snd path))
+		with | Invalid_string ->
+			jname_to_hx (snd path), None
+	in
+	let pack = fst (jpath_to_hx path) in
+	let pack, sub, name = match path with
+		| [], ("Float" as c)
+		| [], ("Int" as c)
+		| [], ("Single" as c)
+		| [], ("Bool" as c)
+		| [], ("Dynamic" as c)
+		| [], ("Iterator" as c)
+		| [], ("ArrayAccess" as c)
+		| [], ("Iterable" as c) ->
+			[], Some c, "StdTypes"
+		| [], ("String" as c) ->
+			["std"], None, c
+		| _ ->
+			pack, sub, name
+	in
+	CTPath {
+		tpackage = pack;
+		tname = name;
+		tparams = params;
+		tsub = sub;
+	}
+
+let has_tparam name params = List.exists(fun (n,_,_) -> n = name) params
+
+let rec convert_arg ctx p arg =
+	match arg with
+	| TAny | TType (WSuper, _) -> TPType (mk_type_path ctx ([], "Dynamic") [],null_pos)
+	| TType (_, jsig) -> TPType (convert_signature ctx p jsig,null_pos)
+
+and convert_signature ctx p jsig =
+	match jsig with
+	| TByte -> mk_type_path ctx (["java"; "types"], "Int8") []
+	| TChar -> mk_type_path ctx (["java"; "types"], "Char16") []
+	| TDouble -> mk_type_path ctx ([], "Float") []
+	| TFloat -> mk_type_path ctx ([], "Single") []
+	| TInt -> mk_type_path ctx ([], "Int") []
+	| TLong -> mk_type_path ctx (["haxe"], "Int64") []
+	| TShort -> mk_type_path ctx (["java"; "types"], "Int16") []
+	| TBool -> mk_type_path ctx ([], "Bool") []
+	| TObject ( (["haxe";"root"], name), args ) -> mk_type_path ctx ([], name) (List.map (convert_arg ctx p) args)
+	(** nullable types *)
+	(* replaced from Null<Type> to the actual abstract type to fix #2738 *)
+	(* | TObject ( (["java";"lang"], "Integer"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Int") []) ] *)
+	(* | TObject ( (["java";"lang"], "Double"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Float") []) ] *)
+	(* | TObject ( (["java";"lang"], "Float"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Single") []) ] *)
+	(* | TObject ( (["java";"lang"], "Boolean"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Bool") []) ] *)
+	(* | TObject ( (["java";"lang"], "Byte"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["java";"types"], "Int8") []) ] *)
+	(* | TObject ( (["java";"lang"], "Character"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["java";"types"], "Char16") []) ] *)
+	(* | TObject ( (["java";"lang"], "Short"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["java";"types"], "Int16") []) ] *)
+	(* | TObject ( (["java";"lang"], "Long"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["haxe"], "Int64") []) ] *)
+	(** other std types *)
+	| TObject ( (["java";"lang"], "Object"), [] ) -> mk_type_path ctx ([], "Dynamic") []
+	| TObject ( (["java";"lang"], "String"), [] ) -> mk_type_path ctx ([], "String") []
+	| TObject ( (["java";"lang"], "Enum"), [_] ) -> mk_type_path ctx ([], "EnumValue") []
+	(** other types *)
+	| TObject ( path, [] ) ->
+		(match lookup_jclass ctx.jcom path with
+		| Some (jcl, _, _) -> mk_type_path ctx path (List.map (fun _ -> convert_arg ctx p TAny) jcl.ctypes)
+		| None -> mk_type_path ctx path [])
+	| TObject ( path, args ) -> mk_type_path ctx path (List.map (convert_arg ctx p) args)
+	| TObjectInner (pack, (name, params) :: inners) ->
+			let actual_param = match List.rev inners with
+			| (_, p) :: _ -> p
+			| _ -> assert false in
+			mk_type_path ctx (pack, name ^ "$" ^ String.concat "$" (List.map fst inners)) (List.map (fun param -> convert_arg ctx p param) actual_param)
+	| TObjectInner (pack, inners) -> assert false
+	| TArray (jsig, _) -> mk_type_path ctx (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig,null_pos) ]
+	| TMethod _ -> JReader.error "TMethod cannot be converted directly into Complex Type"
+	| TTypeParameter s -> (match ctx.jtparams with
+		| cur :: others ->
+			if has_tparam s cur then
+				mk_type_path ctx ([], s) []
+			else begin
+				if ctx.jcom.verbose && not(List.exists (has_tparam s) others) then print_endline ("Type parameter " ^ s ^ " was not found while building type!");
+				mk_type_path ctx ([], "Dynamic") []
+			end
+		| _ ->
+			if ctx.jcom.verbose then print_endline ("Empty type parameter stack!");
+			mk_type_path ctx ([], "Dynamic") [])
+
+let convert_constant ctx p const =
+	Option.map_default (function
+		| ConstString s -> Some (EConst (String s), p)
+		| ConstInt i -> Some (EConst (Int (Printf.sprintf "%ld" i)), p)
+		| ConstFloat f | ConstDouble f -> Some (EConst (Float (Printf.sprintf "%E" f)), p)
+		| _ -> None) None const
+
+let rec same_sig parent jsig =
+	match jsig with
+	| TObject (p,targs) -> parent = p || List.exists (function | TType (_,s) -> same_sig parent s | _ -> false) targs
+	| TObjectInner(p, ntargs) ->
+			parent = (p, String.concat "$" (List.map fst ntargs)) ||
+			List.exists (fun (_,targs) -> List.exists (function | TType(_,s) -> same_sig parent s | _ -> false) targs) ntargs
+	| TArray(s,_) -> same_sig parent s
+	| _ -> false
+
+let convert_param ctx p parent param =
+	let name, constraints = match param with
+		| (name, Some extends_sig, implem_sig) ->
+			name, extends_sig :: implem_sig
+		| (name, None, implemem_sig) ->
+			name, implemem_sig
+		in
+		let constraints = List.map (fun s -> if same_sig parent s then (TObject( (["java";"lang"], "Object"), [])) else s) constraints in
+		{
+			tp_name = name,null_pos;
+			tp_params = [];
+			tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) constraints;
+			tp_meta = [];
+		}
+
+let get_type_path ctx ct = match ct with | CTPath p -> p | _ -> assert false
+
+let is_override field =
+	List.exists (function | AttrVisibleAnnotations [{ ann_type = TObject( (["java";"lang"], "Override"), _ ) }] -> true | _ -> false) field.jf_attributes
+
+let mk_override field =
+	{ field with jf_attributes = ((AttrVisibleAnnotations [{ ann_type = TObject( (["java";"lang"], "Override"), [] ); ann_elements = [] }]) :: field.jf_attributes) }
+
+let del_override field =
+	{ field with jf_attributes = List.filter (fun a -> not (is_override_attrib a)) field.jf_attributes }
+
+let get_canonical ctx p pack name =
+	(Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst (String name), p], p)
+
+let convert_java_enum ctx p pe =
+	let meta = ref (get_canonical ctx p (fst pe.cpath) (snd pe.cpath) :: [Meta.Native, [EConst (String (real_java_path ctx pe.cpath) ), p], p ]) in
+	let data = ref [] in
+	List.iter (fun f ->
+		(* if List.mem JEnum f.jf_flags then *)
+		match f.jf_vmsignature with
+		| TObject( path, [] ) when path = pe.cpath && List.mem JStatic f.jf_flags && List.mem JFinal f.jf_flags ->
+			data := { ec_name = f.jf_name,null_pos; ec_doc = None; ec_meta = []; ec_args = []; ec_pos = p; ec_params = []; ec_type = None; } :: !data;
+		| _ -> ()
+	) pe.cfields;
+
+	EEnum {
+		d_name = jname_to_hx (snd pe.cpath),null_pos;
+		d_doc = None;
+		d_params = []; (* enums never have type parameters *)
+		d_meta = !meta;
+		d_flags = [EExtern];
+		d_data = List.rev !data;
+	}
+
+	let convert_java_field ctx p jc field =
+		let p = { p with pfile =	p.pfile ^" (" ^field.jf_name ^")" } in
+		let cff_doc = None in
+		let cff_pos = p in
+		let cff_meta = ref [] in
+		let cff_access = ref [] in
+		let cff_name = match field.jf_name with
+			| "<init>" -> "new"
+			| "<clinit>"-> raise Exit (* __init__ field *)
+			| name when String.length name > 5 ->
+					(match String.sub name 0 5 with
+					| "__hx_" | "this$" -> raise Exit
+					| _ -> name)
+			| name -> name
+		in
+		let jf_constant = ref field.jf_constant in
+		let readonly = ref false in
+
+		List.iter (function
+			| JPublic -> cff_access := APublic :: !cff_access
+			| JPrivate -> raise Exit (* private instances aren't useful on externs *)
+			| JProtected -> cff_access := APrivate :: !cff_access
+			| JStatic -> cff_access := AStatic :: !cff_access
+			| JFinal ->
+				cff_meta := (Meta.Final, [], p) :: !cff_meta;
+				(match field.jf_kind, field.jf_vmsignature, field.jf_constant with
+				| JKField, TObject _, _ ->
+					jf_constant := None
+				| JKField, _, Some _ ->
+					readonly := true;
+					jf_constant := None;
+				| _ -> jf_constant := None)
+			(* | JSynchronized -> cff_meta := (Meta.Synchronized, [], p) :: !cff_meta *)
+			| JVolatile -> cff_meta := (Meta.Volatile, [], p) :: !cff_meta
+			| JTransient -> cff_meta := (Meta.Transient, [], p) :: !cff_meta
+			(* | JVarArgs -> cff_meta := (Meta.VarArgs, [], p) :: !cff_meta *)
+			| _ -> ()
+		) field.jf_flags;
+
+		List.iter (function
+			| AttrDeprecated when jc.cpath <> (["java";"util"],"Date") -> cff_meta := (Meta.Deprecated, [], p) :: !cff_meta
+			(* TODO: pass anotations as @:meta *)
+			| AttrVisibleAnnotations ann ->
+				List.iter (function
+					| { ann_type = TObject( (["java";"lang"], "Override"), [] ) } ->
+						cff_access := AOverride :: !cff_access
+					| _ -> ()
+				) ann
+			| _ -> ()
+		) field.jf_attributes;
+
+		List.iter (fun jsig ->
+			match convert_signature ctx p jsig with
+				| CTPath path ->
+					cff_meta := (Meta.Throws, [Ast.EConst (Ast.String (s_type_path (path.tpackage,path.tname))), p],p) :: !cff_meta
+				| _ -> ()
+		) field.jf_throws;
+
+		let kind = match field.jf_kind with
+			| JKField when !readonly ->
+				FProp (("default",null_pos), ("null",null_pos), Some (convert_signature ctx p field.jf_signature,null_pos), None)
+			| JKField ->
+				FVar (Some (convert_signature ctx p field.jf_signature,null_pos), None)
+			| JKMethod ->
+				match field.jf_signature with
+				| TMethod (args, ret) ->
+					let old_types = ctx.jtparams in
+					(match ctx.jtparams with
+					| c :: others -> ctx.jtparams <- (c @ field.jf_types) :: others
+					| [] -> ctx.jtparams <- field.jf_types :: []);
+					let i = ref 0 in
+					let args = List.map (fun s ->
+						incr i;
+						("param" ^ string_of_int !i,null_pos), false, [], Some(convert_signature ctx p s,null_pos), None
+					) args in
+					let t = Option.map_default (convert_signature ctx p) (mk_type_path ctx ([], "Void") []) ret in
+					cff_meta := (Meta.Overload, [], p) :: !cff_meta;
+
+					let types = List.map (function
+						| (name, Some ext, impl) ->
+							{
+								tp_name = name,null_pos;
+								tp_params = [];
+								tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (ext :: impl);
+								tp_meta = [];
+							}
+						| (name, None, impl) ->
+							{
+								tp_name = name,null_pos;
+								tp_params = [];
+								tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (impl);
+								tp_meta = [];
+							}
+					) field.jf_types in
+					ctx.jtparams <- old_types;
+
+					FFun ({
+						f_params = types;
+						f_args = args;
+						f_type = Some (t,null_pos);
+						f_expr = None
+					})
+				| _ -> error "Method signature was expected" p
+		in
+		let cff_name, cff_meta =
+			match String.get cff_name 0 with
+				| '%' ->
+					let name = (String.sub cff_name 1 (String.length cff_name - 1)) in
+					if not (is_haxe_keyword name) then
+						cff_meta := (Meta.Deprecated, [EConst(String(
+							"This static field `_" ^ name ^ "` is deprecated and will be removed in later versions. Please use `" ^ name ^ "` instead")
+						),p], p) :: !cff_meta;
+					"_" ^ name,
+					(Meta.Native, [EConst (String (name) ), cff_pos], cff_pos) :: !cff_meta
+				| _ ->
+					match String.nsplit cff_name "$" with
+						| [ no_dollar ] ->
+							cff_name, !cff_meta
+						| parts ->
+							String.concat "_" parts,
+							(Meta.Native, [EConst (String (cff_name) ), cff_pos], cff_pos) :: !cff_meta
+		in
+		if PMap.mem "java_loader_debug" ctx.jcom.defines then
+			Printf.printf "\t%s%sfield %s : %s\n" (if List.mem AStatic !cff_access then "static " else "") (if List.mem AOverride !cff_access then "override " else "") cff_name (s_sig field.jf_signature);
+
+		{
+			cff_name = cff_name,null_pos;
+			cff_doc = cff_doc;
+			cff_pos = cff_pos;
+			cff_meta = cff_meta;
+			cff_access = !cff_access;
+			cff_kind = kind
+		}
+
+	let rec japply_params params jsig = match params with
+	| [] -> jsig
+	| _ -> match jsig with
+		| TTypeParameter s -> (try
+			List.assoc s params
+		with | Not_found -> jsig)
+		| TObject(p,tl) ->
+			TObject(p, args params tl)
+		| TObjectInner(sl, stll) ->
+			TObjectInner(sl, List.map (fun (s,tl) -> (s, args params tl)) stll)
+		| TArray(s,io) ->
+			TArray(japply_params params s, io)
+		| TMethod(sl, sopt) ->
+			TMethod(List.map (japply_params params) sl, Option.map (japply_params params) sopt)
+		| _ -> jsig
+
+	and args params tl = match params with
+	| [] -> tl
+	| _ -> List.map (function
+		| TAny -> TAny
+		| TType(w,s) -> TType(w,japply_params params s)) tl
+
+	let mk_params jtypes = List.map (fun (s,_,_) -> (s,TTypeParameter s)) jtypes
+
+	let convert_java_class ctx p jc =
+		match List.mem JEnum jc.cflags with
+		| true -> (* is enum *)
+				[convert_java_enum ctx p jc]
+		| false ->
+			let flags = ref [HExtern] in
+			if PMap.mem "java_loader_debug" ctx.jcom.defines then begin
+				let sup = jc.csuper :: jc.cinterfaces in
+				print_endline ("converting " ^ (if List.mem JAbstract jc.cflags then "abstract " else "") ^ JData.path_s jc.cpath ^ " : " ^ (String.concat ", " (List.map s_sig sup)));
+			end;
+			(* todo: instead of JavaNative, use more specific definitions *)
+			let meta = ref [Meta.JavaNative, [], p; Meta.Native, [EConst (String (real_java_path ctx jc.cpath) ), p], p; get_canonical ctx p (fst jc.cpath) (snd jc.cpath)] in
+			let force_check = Common.defined ctx.jcom Define.ForceLibCheck in
+			if not force_check then
+				meta := (Meta.LibType,[],p) :: !meta;
+
+			let is_interface = ref false in
+			List.iter (fun f -> match f with
+				| JFinal -> meta := (Meta.Final, [], p) :: !meta
+				| JInterface ->
+						is_interface := true;
+						flags := HInterface :: !flags
+				| JAbstract -> meta := (Meta.Abstract, [], p) :: !meta
+				| JAnnotation -> meta := (Meta.Annotation, [], p) :: !meta
+				| _ -> ()
+			) jc.cflags;
+
+			(match jc.csuper with
+				| TObject( (["java";"lang"], "Object"), _ ) -> ()
+				| TObject( (["haxe";"lang"], "HxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta
+				| _ -> flags := HExtends (get_type_path ctx (convert_signature ctx p jc.csuper),null_pos) :: !flags
+			);
+
+			List.iter (fun i ->
+				match i with
+				| TObject ( (["haxe";"lang"], "IHxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta
+				| _ -> flags :=
+					if !is_interface then
+						HExtends (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
+					else
+						HImplements (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
+			) jc.cinterfaces;
+
+			let fields = ref [] in
+			let jfields = ref [] in
+
+			if jc.cpath <> (["java";"lang"], "CharSequence") then
+				List.iter (fun f ->
+					try
+						if !is_interface && List.mem JStatic f.jf_flags then
+							()
+						else begin
+							fields := convert_java_field ctx p jc f :: !fields;
+							jfields := f :: !jfields
+						end
+					with
+						| Exit -> ()
+				) (jc.cfields @ jc.cmethods);
+
+			(* make sure the throws types are imported correctly *)
+			let imports = List.concat (List.map (fun f ->
+				List.map (fun jsig ->
+					match convert_signature ctx p jsig with
+						| CTPath path ->
+							let pos = { p with pfile = p.pfile ^ " (" ^ f.jf_name ^" @:throws)" } in
+							EImport( List.map (fun s -> s,pos) (path.tpackage @ [path.tname]), INormal )
+						| _ -> assert false
+				) f.jf_throws
+			) jc.cmethods) in
+
+			(EClass {
+				d_name = jname_to_hx (snd jc.cpath),null_pos;
+				d_doc = None;
+				d_params = List.map (convert_param ctx p jc.cpath) jc.ctypes;
+				d_meta = !meta;
+				d_flags = !flags;
+				d_data = !fields;
+			}) :: imports
+
+	let create_ctx com =
+		{
+			jcom = com;
+			jtparams = [];
+		}
+
+	let rec has_type_param = function
+		| TTypeParameter _ -> true
+		| TMethod (lst, opt) -> List.exists has_type_param lst || Option.map_default has_type_param false opt
+		| TArray (s,_) -> has_type_param s
+		| TObjectInner (_, stpl) -> List.exists (fun (_,sigs) -> List.exists has_type_param_arg sigs) stpl
+		| TObject(_, pl) -> List.exists has_type_param_arg pl
+		| _ -> false
+
+	and has_type_param_arg = function | TType(_,s) -> has_type_param s | _ -> false
+
+let rec japply_params jparams jsig = match jparams with
+	| [] -> jsig
+	| _ ->
+		match jsig with
+		| TObject(path,p) ->
+			TObject(path, List.map (japply_params_tp jparams ) p)
+		| TObjectInner(sl,stargl) ->
+			TObjectInner(sl,List.map (fun (s,targ) -> (s, List.map (japply_params_tp jparams) targ)) stargl)
+		| TArray(jsig,io) ->
+			TArray(japply_params jparams jsig,io)
+		| TMethod(args,ret) ->
+			TMethod(List.map (japply_params jparams ) args, Option.map (japply_params jparams ) ret)
+		| TTypeParameter s -> (try
+			List.assoc s jparams
+		with | Not_found -> jsig)
+		| _ -> jsig
+
+
+and japply_params_tp jparams jtype_argument = match jtype_argument with
+	| TAny -> TAny
+	| TType(w,jsig) -> TType(w,japply_params jparams jsig)
+
+let mk_jparams jtypes params = match jtypes, params with
+	| [], [] -> []
+	| _, [] -> List.map (fun (s,_,_) -> s, TObject( (["java";"lang"], "Object"), [] ) ) jtypes
+	| _ -> List.map2 (fun (s,_,_) jt -> match jt with
+		| TAny -> s, TObject((["java";"lang"],"Object"),[])
+		| TType(_,jsig) -> s, jsig) jtypes params
+
+let rec compatible_signature_arg ?arg_test f1 f2 =
+	let arg_test = match arg_test with
+		| None -> (fun _ _ -> true)
+		| Some a -> a
+	in
+	if f1 = f2 then
+		true
+	else match f1, f2 with
+	| TObject(p,a), TObject(p2,a2) -> p = p2 && arg_test a a2
+	| TObjectInner(sl, stal), TObjectInner(sl2, stal2) -> sl = sl2 && List.map fst stal = List.map fst stal2
+	| TArray(s,_) , TArray(s2,_) -> compatible_signature_arg s s2
+	| TTypeParameter t1 , TTypeParameter t2 -> t1 = t2
+	| _ -> false
+
+let rec compatible_param p1 p2 = match p1, p2 with
+	| TType (_,s1), TType(_,s2) -> compatible_signature_arg ~arg_test:compatible_tparams s1 s2
+	| TAny, TType(_, TObject( (["java";"lang"],"Object"), _ )) -> true
+	| TType(_, TObject( (["java";"lang"],"Object"), _ )), TAny -> true
+	| _ -> false
+
+and compatible_tparams p1 p2 = try match p1, p2 with
+	| [], [] -> true
+	| _, [] ->
+		let p2 = List.map (fun _ -> TAny) p1 in
+		List.for_all2 compatible_param p1 p2
+	| [], _ ->
+		let p1 = List.map (fun _ -> TAny) p2 in
+		List.for_all2 compatible_param p1 p2
+	| _, _ ->
+		List.for_all2 compatible_param p1 p2
+	with | Invalid_argument("List.for_all2") -> false
+
+let get_adapted_sig f f2 = match f.jf_types with
+	| [] ->
+		f.jf_signature
+	| _ ->
+		let jparams = mk_jparams f.jf_types (List.map (fun (s,_,_) -> TType(WNone, TTypeParameter s)) f2.jf_types) in
+		japply_params jparams f.jf_signature
+
+let compatible_methods f1 f2 =
+	if List.length f1.jf_types <> List.length f2.jf_types then
+		false
+	else match (get_adapted_sig f1 f2), f2.jf_signature with
+	| TMethod(a1,_), TMethod(a2,_) when List.length a1 = List.length a2 ->
+		List.for_all2 compatible_signature_arg a1 a2
+	| _ -> false
+
+let jcl_from_jsig com jsig =
+	let path, params = match jsig with
+	| TObject(path, params) ->
+		path,params
+	| TObjectInner(sl, stll) ->
+		let last_params = ref [] in
+		let real_path = sl, String.concat "$" (List.map (fun (s,p) -> last_params := p; s) stll) in
+		real_path, !last_params
+	| _ -> raise Not_found
+	in
+	match lookup_jclass com path with
+	| None -> raise Not_found
+	| Some(c,_,_) -> c,params
+
+let jclass_with_params com cls params = try
+	match cls.ctypes with
+	| [] -> cls
+	| _ ->
+		let jparams = mk_jparams cls.ctypes params in
+		{ cls with
+			cfields = List.map (fun f -> { f with jf_signature = japply_params jparams f.jf_signature }) cls.cfields;
+			cmethods = List.map (fun f -> { f with jf_signature = japply_params jparams f.jf_signature }) cls.cmethods;
+			csuper = japply_params jparams cls.csuper;
+			cinterfaces = List.map (japply_params jparams) cls.cinterfaces;
+		}
+	with Invalid_argument("List.map2") ->
+		if com.verbose then prerr_endline ("Differing parameters for class: " ^ s_type_path cls.cpath);
+		cls
+
+let is_object = function | TObject( (["java";"lang"], "Object"), [] ) -> true | _ -> false
+
+let is_tobject = function | TObject _ | TObjectInner _ -> true | _ -> false
+
+let simplify_args args =
+	if List.for_all (function | TAny -> true | _ -> false) args then [] else args
+
+let compare_type com s1 s2 =
+	if s1 = s2 then
+		0
+	else if not (is_tobject s1) then
+		if is_tobject s2 then (* Dynamic *)
+			1
+		else if compatible_signature_arg s1 s2 then
+			0
+		else
+			raise Exit
+	else if not (is_tobject s2) then
+		-1
+	else begin
+		let rec loop ?(first_error=true) s1 s2 : bool =
+			if is_object s1 then
+				s1 = s2
+			else if compatible_signature_arg s1 s2 then begin
+				let p1, p2 = match s1, s2 with
+				| TObject(_, p1), TObject(_,p2) ->
+					p1, p2
+				| TObjectInner(_, npl1), TObjectInner(_, npl2) ->
+					snd (List.hd (List.rev npl1)), snd (List.hd (List.rev npl2))
+				| _ -> assert false (* not tobject *)
+				in
+				let p1, p2 = simplify_args p1, simplify_args p2 in
+				let lp1 = List.length p1 in
+				let lp2 = List.length p2 in
+				if lp1 > lp2 then
+					true
+				else if lp2 > lp1 then
+					false
+				else begin
+					(* if compatible tparams, it's fine *)
+					if not (compatible_tparams p1 p2) then
+						raise Exit; (* meaning: found, but incompatible type parameters *)
+					true
+				end
+			end else try
+				let c, p = jcl_from_jsig com s1 in
+				let jparams = mk_jparams c.ctypes p in
+				let super = japply_params jparams c.csuper in
+				let implements = List.map (japply_params jparams) c.cinterfaces in
+				loop ~first_error:first_error super s2 || List.exists (fun super -> loop ~first_error:first_error super s2) implements
+			with | Not_found ->
+				prerr_endline ("-java-lib: The type " ^ (s_sig s1) ^ " is referred but was not found. Compilation may not occur correctly.");
+				prerr_endline "Did you forget to include a needed lib?";
+				if first_error then
+					not (loop ~first_error:false s2 s1)
+				else
+					false
+		in
+		if loop s1 s2 then
+			if loop s2 s1 then
+				0
+			else
+				1
+		else
+			if loop s2 s1 then
+				-1
+			else
+				-2
+	end
+
+(* given a list of same overload functions, choose the best (or none) *)
+let select_best com flist =
+	let rec loop cur_best = function
+		| [] ->
+			Some cur_best
+		| f :: flist -> match get_adapted_sig f cur_best, cur_best.jf_signature with
+			| TMethod(_,Some r), TMethod(_, Some r2) -> (try
+				match compare_type com r r2 with
+				| 0 -> (* same type - select any of them *)
+					loop cur_best flist
+				| 1 ->
+					loop f flist
+				| -1 ->
+					loop cur_best flist
+				| -2 -> (* error - no type is compatible *)
+					if com.verbose then prerr_endline (f.jf_name ^ ": The types " ^ (s_sig r) ^ " and " ^ (s_sig r2) ^ " are incompatible");
+					(* bet that the current best has "beaten" other types *)
+					loop cur_best flist
+				| _ -> assert false
+			with | Exit -> (* incompatible type parameters *)
+				(* error mode *)
+				if com.verbose then prerr_endline (f.jf_name ^ ": Incompatible argument return signatures: " ^ (s_sig r) ^ " and " ^ (s_sig r2));
+				None)
+			| TMethod _, _ -> (* select the method *)
+				loop f flist
+			| _ ->
+				loop cur_best flist
+	in
+	match loop (List.hd flist) (List.tl flist) with
+	| Some f ->
+		Some f
+	| None -> match List.filter (fun f -> not (is_override f)) flist with
+		(* error mode; take off all override methods *)
+		| [] -> None
+		| f :: [] -> Some f
+		| f :: flist -> Some f (* pick one *)
+
+(**** begin normalize_jclass helpers ****)
+
+let fix_overrides_jclass com cls =
+	let force_check = Common.defined com Define.ForceLibCheck in
+	let methods = if force_check then List.map (fun f -> del_override f) cls.cmethods else cls.cmethods in
+	let cmethods = methods in
+	let super_fields = [] in
+	let super_methods = [] in
+	let nonstatics = List.filter (fun f -> not (List.mem JStatic f.jf_flags)) (cls.cfields @ cls.cmethods) in
+
+	let is_pub = fun f -> List.exists (function | JPublic | JProtected -> true | _ -> false) f.jf_flags in
+	let cmethods, super_fields = if not (List.mem JInterface cls.cflags) then
+		List.filter is_pub cmethods,
+		List.filter is_pub super_fields
+	else
+		cmethods,super_fields
+	in
+
+	let rec loop cls super_methods super_fields cmethods nonstatics = try
+		match cls.csuper with
+		| TObject((["java";"lang"],"Object"),_) ->
+				super_methods,super_fields,cmethods,nonstatics
+		| _ ->
+			let cls, params = jcl_from_jsig com cls.csuper in
+			let cls = jclass_with_params com cls params in
+			let nonstatics = (List.filter (fun f -> (List.mem JStatic f.jf_flags)) (cls.cfields @ cls.cmethods)) @ nonstatics in
+			let super_methods = cls.cmethods @ super_methods in
+			let super_fields = cls.cfields @ super_fields in
+			let cmethods = if force_check then begin
+				let overriden = ref [] in
+				let cmethods = List.map (fun jm ->
+					(* TODO rewrite/standardize empty spaces *)
+					if not (is_override jm) && not (List.mem JStatic jm.jf_flags) && List.exists (fun msup ->
+						let ret = msup.jf_name = jm.jf_name && not(List.mem JStatic msup.jf_flags) && compatible_methods msup jm in
+						if ret then begin
+							let f = mk_override msup in
+							overriden := { f with jf_flags = jm.jf_flags } :: !overriden
+						end;
+						ret
+					) cls.cmethods then
+						mk_override jm
+					else
+						jm
+				) cmethods in
+				!overriden @ cmethods
+			end else
+				cmethods
+			in
+			loop cls super_methods super_fields cmethods nonstatics
+		with | Not_found ->
+			super_methods,super_fields,cmethods,nonstatics
+	in
+	loop cls super_methods super_fields cmethods nonstatics
+
+let normalize_jclass com cls =
+	(* after adding the noCheck metadata, this option will annotate what changes were needed *)
+	(* and that are now deprecated *)
+	let force_check = Common.defined com Define.ForceLibCheck in
+	(* fix overrides *)
+	let super_methods, super_fields, cmethods, nonstatics = fix_overrides_jclass com cls in
+	let all_methods = cmethods @ super_methods in
+
+	(* look for interfaces and add missing implementations (may happen on abstracts or by vmsig differences *)
+	(* (libType): even with libType enabled, we need to add these missing fields - otherwise we won't be able to use them from Haxe *)
+	let added_interface_fields = ref [] in
+	let rec loop_interface abstract cls iface = try
+		match iface with
+			| TObject ((["java";"lang"],"Object"), _) -> ()
+			| TObject (path,_) when path = cls.cpath -> ()
+			| _ ->
+				let cif, params = jcl_from_jsig com iface in
+				let cif = jclass_with_params com cif params in
+				List.iter (fun jf ->
+					if not(List.mem JStatic jf.jf_flags) && not (List.exists (fun jf2 -> jf.jf_name = jf2.jf_name && not (List.mem JStatic jf2.jf_flags) && jf.jf_signature = jf2.jf_signature) all_methods) then begin
+						let jf = if abstract && force_check then del_override jf else jf in
+						let jf = { jf with jf_flags = JPublic :: jf.jf_flags } in (* interfaces implementations are always public *)
+
+						added_interface_fields := jf :: !added_interface_fields;
+					end
+				) cif.cmethods;
+				(* we don't need to loop again in the interface unless we are in an abstract class, since these interfaces are already normalized *)
+				if abstract then List.iter (loop_interface abstract cif) cif.cinterfaces;
+		with Not_found -> ()
+	in
+	List.iter (loop_interface (List.mem JAbstract cls.cflags) cls) cls.cinterfaces;
+	let nonstatics = !added_interface_fields @ nonstatics in
+	let cmethods = !added_interface_fields @ cmethods in
+
+	(* for each added field in the interface, lookup in super_methods possible methods to include *)
+	(* so we can choose the better method still *)
+	let cmethods = if not force_check then
+		cmethods
+	else
+		List.fold_left (fun cmethods im ->
+			(* see if any of the added_interface_fields need to be declared as override *)
+			let f = List.find_all (fun jf -> jf.jf_name = im.jf_name && compatible_methods jf im) super_methods in
+			let f = List.map mk_override f in
+			f @ cmethods
+		) cmethods !added_interface_fields;
+	in
+
+	(* take off equals, hashCode and toString from interface *)
+	let cmethods = if List.mem JInterface cls.cflags then List.filter (fun jf -> match jf.jf_name, jf.jf_vmsignature with
+			| "equals", TMethod([TObject( (["java";"lang"],"Object"), _)],_)
+			| "hashCode", TMethod([], _)
+			| "toString", TMethod([], _) -> false
+			| _ -> true
+	) cmethods
+	else
+		cmethods
+	in
+
+	(* change field name to not collide with haxe keywords and with static/non-static members *)
+	let fold_field acc f =
+		let change, both = match f.jf_name with
+		| _ when List.mem JStatic f.jf_flags && List.exists (fun f2 -> f.jf_name = f2.jf_name) nonstatics -> true, true
+		| _ -> is_haxe_keyword f.jf_name, false
+		in
+		let f2 = if change then
+				{ f with jf_name = "%" ^ f.jf_name }
+			else
+				f
+		in
+		if both then f :: f2 :: acc else f2 :: acc
+	in
+
+	(* change static fields that have the same name as methods *)
+	let cfields = List.fold_left fold_field [] cls.cfields in
+	let cmethods = List.fold_left fold_field [] cmethods in
+	(* take off variable fields that have the same name as methods *)
+	(* and take off variables that already have been declared *)
+	let filter_field f f2 = f != f2 && (List.mem JStatic f.jf_flags = List.mem JStatic f2.jf_flags) && f.jf_name = f2.jf_name && f2.jf_kind <> f.jf_kind in
+	let cfields = List.filter (fun f ->
+		if List.mem JStatic f.jf_flags then
+			not (List.exists (filter_field f) cmethods)
+		else
+			not (List.exists (filter_field f) nonstatics) && not (List.exists (fun f2 -> f != f2 && f.jf_name = f2.jf_name && not (List.mem JStatic f2.jf_flags)) super_fields) ) cfields
+	in
+	(* now filter any method that clashes with a field - on a superclass *)
+	let cmethods = if force_check then List.filter (fun f ->
+		if List.mem JStatic f.jf_flags then
+			true
+		else
+			not (List.exists (filter_field f) super_fields) ) cmethods
+	else
+		cmethods
+	in
+	(* removing duplicate fields. They are there because of return type covariance in Java *)
+	(* Also, if a method overrides a previous definition, and changes a type parameters' variance, *)
+	(* we will take it off *)
+	(* this means that some rare codes will never compile on Haxe, but unless Haxe adds variance support *)
+	(* I can't see how this can be any different *)
+	let rec loop acc = function
+		| [] -> acc
+		| f :: cmeths ->
+			match List.partition (fun f2 -> f.jf_name = f2.jf_name && compatible_methods f f2) cmeths with
+			| [], cmeths ->
+				loop (f :: acc) cmeths
+			| flist, cmeths -> match select_best com (f :: flist) with
+				| None ->
+					loop acc cmeths
+				| Some f ->
+					loop (f :: acc) cmeths
+	in
+	(* last pass: take off all cfields that are internal / private (they won't be accessible anyway) *)
+	let cfields = List.filter(fun f -> List.exists (fun f -> f = JPublic || f = JProtected) f.jf_flags) cfields in
+	let cmethods = loop [] cmethods in
+	{ cls with cfields = cfields; cmethods = cmethods }
+
+(**** end normalize_jclass helpers ****)
+
+let get_classes_zip zip =
+	let ret = ref [] in
+	List.iter (function
+		| { Zip.is_directory = false; Zip.filename = f } when (String.sub (String.uncapitalize f) (String.length f - 6) 6) = ".class" && not (String.exists f "$") ->
+				(match List.rev (String.nsplit f "/") with
+				| clsname :: pack ->
+					if not (String.contains clsname '$') then begin
+						let path = jpath_to_hx (List.rev pack, String.sub clsname 0 (String.length clsname - 6)) in
+						ret := path :: !ret
+					end
+				| _ ->
+						ret := ([], jname_to_hx f) :: !ret)
+		| _ -> ()
+	) (Zip.entries zip);
+	!ret
+
+let add_java_lib com file std =
+	let file = if Sys.file_exists file then
+		file
+	else try Common.find_file com file with
+		| Not_found -> try Common.find_file com (file ^ ".jar") with
+		| Not_found ->
+			failwith ("Java lib " ^ file ^ " not found")
+	in
+	let hxpack_to_jpack = Hashtbl.create 16 in
+	let get_raw_class, close, list_all_files =
+		(* check if it is a directory or jar file *)
+		match (Unix.stat file).st_kind with
+		| S_DIR -> (* open classes directly from directory *)
+			let all = ref [] in
+			let rec iter_files pack dir path = try
+				let file = Unix.readdir dir in
+				let filepath = path ^ "/" ^ file in
+				(if String.ends_with file ".class" && not (String.exists file "$") then
+					let file = String.sub file 0 (String.length file - 6) in
+					let path = jpath_to_hx (pack,file) in
+					all := path :: !all;
+					Hashtbl.add hxpack_to_jpack path (pack,file)
+				else if (Unix.stat filepath).st_kind = S_DIR && file <> "." && file <> ".." then
+					let pack = pack @ [file] in
+					iter_files (pack) (Unix.opendir filepath) filepath);
+				iter_files pack dir path
+			with | End_of_file | Unix.Unix_error _ ->
+				Unix.closedir dir
+			in
+			iter_files [] (Unix.opendir file) file;
+			let all = !all in
+
+			(fun (pack, name) ->
+				let real_path = file ^ "/" ^ (String.concat "/" pack) ^ "/" ^ (name ^ ".class") in
+				try
+					let data = Std.input_file ~bin:true real_path in
+					Some(JReader.parse_class (IO.input_string data), real_path, real_path)
+				with
+					| _ -> None), (fun () -> ()), (fun () -> all)
+		| _ -> (* open zip file *)
+			let closed = ref false in
+			let zip = ref (Zip.open_in file) in
+			let check_open () =
+				if !closed then begin
+					prerr_endline ("JAR file " ^ file ^ " already closed"); (* if this happens, find when *)
+					zip := Zip.open_in file;
+					closed := false
+				end
+			in
+			List.iter (function
+				| { Zip.is_directory = false; Zip.filename = filename } when String.ends_with filename ".class" ->
+					let pack = String.nsplit filename "/" in
+					(match List.rev pack with
+						| [] -> ()
+						| name :: pack ->
+							let name = String.sub name 0 (String.length name - 6) in
+							let pack = List.rev pack in
+							Hashtbl.add hxpack_to_jpack (jpath_to_hx (pack,name)) (pack,name))
+				| _ -> ()
+			) (Zip.entries !zip);
+			(fun (pack, name) ->
+				check_open();
+				try
+					let location = (String.concat "/" (pack @ [name]) ^ ".class") in
+					let entry = Zip.find_entry !zip location in
+					let data = Zip.read_entry !zip entry in
+					Some(JReader.parse_class (IO.input_string data), file, file ^ "@" ^ location)
+				with
+					| Not_found ->
+						None),
+			(fun () -> if not !closed then begin closed := true; Zip.close_in !zip end),
+			(fun () -> check_open(); get_classes_zip !zip)
+	in
+	let cached_types = Hashtbl.create 12 in
+	let get_raw_class path =
+		try
+			Hashtbl.find cached_types path
+		with | Not_found -> try
+			let pack, name = Hashtbl.find hxpack_to_jpack path in
+			let try_file (pack,name) =
+				match get_raw_class (pack,name) with
+				| None ->
+						Hashtbl.add cached_types path None;
+						None
+				| Some (i, p1, p2) ->
+						Hashtbl.add cached_types path (Some(i,p1,p2)); (* type loop normalization *)
+						let ret = Some (normalize_jclass com i, p1, p2) in
+						Hashtbl.replace cached_types path ret;
+						ret
+			in
+			try_file (pack,name)
+		with Not_found ->
+			None
+	in
+	let replace_canonical_name p pack name_original name_replace decl =
+		let mk_meta name = (Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst(String name), p], p) in
+		let add_meta name metas =
+			if Meta.has Meta.JavaCanonical metas then
+				List.map (function
+					| (Meta.JavaCanonical,[EConst (String cpack), _; EConst(String cname), _],_) ->
+						let did_replace,name = String.replace cname name_original name_replace in
+						if not did_replace then print_endline (cname ^ " -> " ^ name_original ^ " -> " ^ name_replace);
+						mk_meta name
+					| m -> m
+				) metas
+			else
+				mk_meta name :: metas
+		in
+		match decl with
+			| EClass c ->
+				EClass { c with d_meta = add_meta (fst c.d_name) c.d_meta }
+			| EEnum e ->
+				EEnum { e with d_meta = add_meta (fst e.d_name) e.d_meta }
+			| EAbstract a ->
+				EAbstract { a with d_meta = add_meta (fst a.d_name) a.d_meta }
+			| d -> d
+	in
+	let rec build ctx path p types =
+		try
+			if List.mem path !types then
+				None
+			else begin
+				let first = match !types with
+					| [ ["java";"lang"], "String" ] | [] -> true
+					| p :: _ ->
+						false
+				in
+				types := path :: !types;
+				match get_raw_class path, path with
+				| None, ([], c) -> build ctx (["haxe";"root"], c) p types
+				| None, _ -> None
+				| Some (cls, real_path, pos_path), _ ->
+						let is_disallowed_inner = first && String.exists (snd cls.cpath) "$" in
+						let is_disallowed_inner = if is_disallowed_inner then begin
+								let outer, inner = String.split (snd cls.cpath) "$" in
+								match get_raw_class (fst path, outer) with
+									| None -> false
+									| _ -> true
+							end else
+								false
+						in
+						if is_disallowed_inner then
+							None
+						else begin
+							if com.verbose then print_endline ("Parsed Java class " ^ (s_type_path cls.cpath));
+							let old_types = ctx.jtparams in
+							ctx.jtparams <- cls.ctypes :: ctx.jtparams;
+
+							let pos = { pfile = pos_path; pmin = 0; pmax = 0; } in
+
+							let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
+
+							let ppath = Hashtbl.find hxpack_to_jpack path in
+							let inner = List.fold_left (fun acc (path,out,_,_) ->
+								let path = jpath_to_hx path in
+								(if out <> Some ppath then
+									acc
+								else match build ctx path p types with
+									| Some(_,(_, classes)) ->
+										let base = snd ppath ^ "$" in
+										(List.map (fun (def,p) ->
+											replace_canonical_name p (fst ppath) base (snd ppath ^ ".") def, p) classes) @ acc
+									| _ -> acc);
+							) [] cls.cinner_types in
+
+							(* add _Statics class *)
+							let inner = try
+								if not (List.mem JInterface cls.cflags) then raise Not_found;
+								let smethods = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cmethods in
+								let sfields = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cfields in
+								if not (smethods <> [] || sfields <> []) then raise Not_found;
+								let obj = TObject( (["java";"lang"],"Object"), []) in
+								let ncls = convert_java_class ctx pos { cls with cmethods = smethods; cfields = sfields; cflags = []; csuper = obj; cinterfaces = []; cinner_types = []; ctypes = [] } in
+								match ncls with
+								| EClass c :: imports ->
+									(EClass { c with d_name = (fst c.d_name ^ "_Statics"),snd c.d_name }, pos) :: inner @ List.map (fun i -> i,pos) imports
+								| _ -> assert false
+							with | Not_found ->
+								inner
+							in
+							let inner_alias = ref SS.empty in
+							List.iter (fun x ->
+								match fst x with
+								| EClass c ->
+									inner_alias := SS.add (fst c.d_name) !inner_alias;
+								| _ -> ()
+							) inner;
+							let alias_list = ref [] in
+							List.iter (fun x ->
+								match x with
+								| (EClass c, pos) -> begin
+									let parts = String.nsplit (fst c.d_name) "_24" in
+									match parts with
+										| _ :: _ ->
+											let alias_name = String.concat "_" parts in
+											if (not (SS.mem alias_name !inner_alias)) && (not (String.exists (snd path) "_24")) then begin
+												let alias_def = ETypedef {
+													d_name = alias_name,null_pos;
+													d_doc = None;
+													d_params = c.d_params;
+													d_meta = [];
+													d_flags = [];
+													d_data = CTPath {
+														tpackage = pack;
+														tname = snd path;
+														tparams = List.map (fun tp ->
+															TPType (CTPath {
+																tpackage = [];
+																tname = fst tp.tp_name;
+																tparams = [];
+																tsub = None;
+															},null_pos)
+														) c.d_params;
+														tsub = Some(fst c.d_name);
+													},null_pos;
+												} in
+												inner_alias := SS.add alias_name !inner_alias;
+												alias_list := (alias_def, pos) :: !alias_list;
+											end
+										| _ -> ()
+								end
+								| _ -> ()
+							) inner;
+							let inner = List.concat [!alias_list ; inner] in
+							let classes = List.map (fun t -> t,pos) (convert_java_class ctx pos cls) in
+							let imports, defs = List.partition (function | (EImport(_),_) -> true | _ -> false) (classes @ inner) in
+							let ret = Some ( real_path, (pack, imports @ defs) ) in
+							ctx.jtparams <- old_types;
+							ret
+						end
+			end
+		with
+		| JReader.Error_message msg ->
+			prerr_endline ("Class reader failed: " ^ msg);
+			None
+		| e ->
+			if com.verbose then begin
+				(* prerr_endline (Printexc.get_backtrace ()); requires ocaml 3.11 *)
+				prerr_endline (Printexc.to_string e)
+			end;
+			None
+	in
+	let build path p = build (create_ctx com) path p (ref [["java";"lang"], "String"]) in
+	let cached_files = ref None in
+	let list_all_files () = match !cached_files with
+		| None ->
+				let ret = list_all_files () in
+				cached_files := Some ret;
+				ret
+		| Some r -> r
+	in
+
+	(* TODO: add_dependency m mdep *)
+	com.load_extern_type <- com.load_extern_type @ [build];
+	com.java_libs <- (file, std, close, list_all_files, get_raw_class) :: com.java_libs
+
+let before_generate con =
+	let java_ver = try
+			int_of_string (PMap.find "java_ver" con.defines)
+		with | Not_found ->
+			Common.define_value con Define.JavaVer "7";
+			7
+	in
+	if java_ver < 5 then failwith ("Java version is defined to target Java " ^ string_of_int java_ver ^ ", but the compiler can only output code to versions equal or superior to Java 5");
+	let rec loop i =
+		Common.raw_define con ("java" ^ (string_of_int i));
+		if i > 0 then loop (i - 1)
+	in
+	loop java_ver