Tue, 12 Oct 2010 13:19:47 -0700
4942232: missing param class processes without error
Reviewed-by: darcy
1.1 --- a/src/share/classes/com/sun/tools/javah/JNI.java Tue Oct 12 13:15:46 2010 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javah/JNI.java Tue Oct 12 13:19:47 2010 -0700 1.3 @@ -59,72 +59,76 @@ 1.4 } 1.5 1.6 public void write(OutputStream o, TypeElement clazz) throws Util.Exit { 1.7 - String cname = mangler.mangle(clazz.getQualifiedName(), Mangle.Type.CLASS); 1.8 - PrintWriter pw = wrapWriter(o); 1.9 - pw.println(guardBegin(cname)); 1.10 - pw.println(cppGuardBegin()); 1.11 + try { 1.12 + String cname = mangler.mangle(clazz.getQualifiedName(), Mangle.Type.CLASS); 1.13 + PrintWriter pw = wrapWriter(o); 1.14 + pw.println(guardBegin(cname)); 1.15 + pw.println(cppGuardBegin()); 1.16 1.17 - /* Write statics. */ 1.18 - List<VariableElement> classfields = getAllFields(clazz); 1.19 + /* Write statics. */ 1.20 + List<VariableElement> classfields = getAllFields(clazz); 1.21 1.22 - for (VariableElement v: classfields) { 1.23 - if (!v.getModifiers().contains(Modifier.STATIC)) 1.24 - continue; 1.25 - String s = null; 1.26 - s = defineForStatic(clazz, v); 1.27 - if (s != null) { 1.28 - pw.println(s); 1.29 + for (VariableElement v: classfields) { 1.30 + if (!v.getModifiers().contains(Modifier.STATIC)) 1.31 + continue; 1.32 + String s = null; 1.33 + s = defineForStatic(clazz, v); 1.34 + if (s != null) { 1.35 + pw.println(s); 1.36 + } 1.37 } 1.38 + 1.39 + /* Write methods. */ 1.40 + List<ExecutableElement> classmethods = ElementFilter.methodsIn(clazz.getEnclosedElements()); 1.41 + for (ExecutableElement md: classmethods) { 1.42 + if(md.getModifiers().contains(Modifier.NATIVE)){ 1.43 + TypeMirror mtr = types.erasure(md.getReturnType()); 1.44 + String sig = signature(md); 1.45 + TypeSignature newtypesig = new TypeSignature(elems); 1.46 + CharSequence methodName = md.getSimpleName(); 1.47 + boolean longName = false; 1.48 + for (ExecutableElement md2: classmethods) { 1.49 + if ((md2 != md) 1.50 + && (methodName.equals(md2.getSimpleName())) 1.51 + && (md2.getModifiers().contains(Modifier.NATIVE))) 1.52 + longName = true; 1.53 + 1.54 + } 1.55 + pw.println("/*"); 1.56 + pw.println(" * Class: " + cname); 1.57 + pw.println(" * Method: " + 1.58 + mangler.mangle(methodName, Mangle.Type.FIELDSTUB)); 1.59 + pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr)); 1.60 + pw.println(" */"); 1.61 + pw.println("JNIEXPORT " + jniType(mtr) + 1.62 + " JNICALL " + 1.63 + mangler.mangleMethod(md, clazz, 1.64 + (longName) ? 1.65 + Mangle.Type.METHOD_JNI_LONG : 1.66 + Mangle.Type.METHOD_JNI_SHORT)); 1.67 + pw.print(" (JNIEnv *, "); 1.68 + List<? extends VariableElement> paramargs = md.getParameters(); 1.69 + List<TypeMirror> args = new ArrayList<TypeMirror>(); 1.70 + for (VariableElement p: paramargs) { 1.71 + args.add(types.erasure(p.asType())); 1.72 + } 1.73 + if (md.getModifiers().contains(Modifier.STATIC)) 1.74 + pw.print("jclass"); 1.75 + else 1.76 + pw.print("jobject"); 1.77 + 1.78 + for (TypeMirror arg: args) { 1.79 + pw.print(", "); 1.80 + pw.print(jniType(arg)); 1.81 + } 1.82 + pw.println(");" + lineSep); 1.83 + } 1.84 + } 1.85 + pw.println(cppGuardEnd()); 1.86 + pw.println(guardEnd(cname)); 1.87 + } catch (TypeSignature.SignatureException e) { 1.88 + util.error("jni.sigerror", e.getMessage()); 1.89 } 1.90 - 1.91 - /* Write methods. */ 1.92 - List<ExecutableElement> classmethods = ElementFilter.methodsIn(clazz.getEnclosedElements()); 1.93 - for (ExecutableElement md: classmethods) { 1.94 - if(md.getModifiers().contains(Modifier.NATIVE)){ 1.95 - TypeMirror mtr = types.erasure(md.getReturnType()); 1.96 - String sig = signature(md); 1.97 - TypeSignature newtypesig = new TypeSignature(elems); 1.98 - CharSequence methodName = md.getSimpleName(); 1.99 - boolean longName = false; 1.100 - for (ExecutableElement md2: classmethods) { 1.101 - if ((md2 != md) 1.102 - && (methodName.equals(md2.getSimpleName())) 1.103 - && (md2.getModifiers().contains(Modifier.NATIVE))) 1.104 - longName = true; 1.105 - 1.106 - } 1.107 - pw.println("/*"); 1.108 - pw.println(" * Class: " + cname); 1.109 - pw.println(" * Method: " + 1.110 - mangler.mangle(methodName, Mangle.Type.FIELDSTUB)); 1.111 - pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr)); 1.112 - pw.println(" */"); 1.113 - pw.println("JNIEXPORT " + jniType(mtr) + 1.114 - " JNICALL " + 1.115 - mangler.mangleMethod(md, clazz, 1.116 - (longName) ? 1.117 - Mangle.Type.METHOD_JNI_LONG : 1.118 - Mangle.Type.METHOD_JNI_SHORT)); 1.119 - pw.print(" (JNIEnv *, "); 1.120 - List<? extends VariableElement> paramargs = md.getParameters(); 1.121 - List<TypeMirror> args = new ArrayList<TypeMirror>(); 1.122 - for (VariableElement p: paramargs) { 1.123 - args.add(types.erasure(p.asType())); 1.124 - } 1.125 - if (md.getModifiers().contains(Modifier.STATIC)) 1.126 - pw.print("jclass"); 1.127 - else 1.128 - pw.print("jobject"); 1.129 - 1.130 - for (TypeMirror arg: args) { 1.131 - pw.print(", "); 1.132 - pw.print(jniType(arg)); 1.133 - } 1.134 - pw.println(");" + lineSep); 1.135 - } 1.136 - } 1.137 - pw.println(cppGuardEnd()); 1.138 - pw.println(guardEnd(cname)); 1.139 } 1.140 1.141
2.1 --- a/src/share/classes/com/sun/tools/javah/JavahTask.java Tue Oct 12 13:15:46 2010 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javah/JavahTask.java Tue Oct 12 13:19:47 2010 -0700 2.3 @@ -46,9 +46,9 @@ 2.4 2.5 import javax.annotation.processing.AbstractProcessor; 2.6 import javax.annotation.processing.Messager; 2.7 +import javax.annotation.processing.ProcessingEnvironment; 2.8 import javax.annotation.processing.RoundEnvironment; 2.9 import javax.annotation.processing.SupportedAnnotationTypes; 2.10 -import javax.annotation.processing.SupportedSourceVersion; 2.11 2.12 import javax.lang.model.SourceVersion; 2.13 import javax.lang.model.element.ExecutableElement; 2.14 @@ -71,6 +71,9 @@ 2.15 import javax.tools.StandardJavaFileManager; 2.16 import javax.tools.StandardLocation; 2.17 import javax.tools.ToolProvider; 2.18 +import static javax.tools.Diagnostic.Kind.*; 2.19 + 2.20 +import com.sun.tools.javac.code.Symbol.CompletionFailure; 2.21 2.22 /** 2.23 * Javah generates support files for native methods. 2.24 @@ -233,6 +236,15 @@ 2.25 task.doubleAlign = true; 2.26 } 2.27 }, 2.28 + 2.29 + new HiddenOption(false) { 2.30 + boolean matches(String opt) { 2.31 + return opt.startsWith("-XD"); 2.32 + } 2.33 + void process(JavahTask task, String opt, String arg) { 2.34 + task.javac_extras.add(opt); 2.35 + } 2.36 + }, 2.37 }; 2.38 2.39 JavahTask() { 2.40 @@ -326,6 +338,8 @@ 2.41 } catch (InternalError e) { 2.42 diagnosticListener.report(createDiagnostic("err.internal.error", e.getMessage())); 2.43 return 1; 2.44 + } catch (Util.Exit e) { 2.45 + return e.exitValue; 2.46 } finally { 2.47 log.flush(); 2.48 } 2.49 @@ -475,7 +489,9 @@ 2.50 ((JavahFileManager) fileManager).setIgnoreSymbolFile(true); 2.51 2.52 JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 2.53 - List<String> opts = Arrays.asList("-proc:only"); 2.54 + List<String> opts = new ArrayList<String>(); 2.55 + opts.add("-proc:only"); 2.56 + opts.addAll(javac_extras); 2.57 CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, internalize(classes), null); 2.58 JavahProcessor p = new JavahProcessor(g); 2.59 t.setProcessors(Collections.singleton(p)); 2.60 @@ -642,6 +658,7 @@ 2.61 boolean doubleAlign; 2.62 boolean force; 2.63 boolean old; 2.64 + Set<String> javac_extras = new LinkedHashSet<String>(); 2.65 2.66 PrintWriter log; 2.67 JavaFileManager fileManager; 2.68 @@ -652,30 +669,45 @@ 2.69 private static final String progname = "javah"; 2.70 2.71 @SupportedAnnotationTypes("*") 2.72 - @SupportedSourceVersion(SourceVersion.RELEASE_7) 2.73 class JavahProcessor extends AbstractProcessor { 2.74 + private Messager messager; 2.75 + 2.76 JavahProcessor(Gen g) { 2.77 this.g = g; 2.78 } 2.79 2.80 + @Override 2.81 + public SourceVersion getSupportedSourceVersion() { 2.82 + // since this is co-bundled with javac, we can assume it supports 2.83 + // the latest source version 2.84 + return SourceVersion.latest(); 2.85 + } 2.86 + 2.87 + @Override 2.88 + public void init(ProcessingEnvironment pEnv) { 2.89 + super.init(pEnv); 2.90 + messager = processingEnv.getMessager(); 2.91 + } 2.92 + 2.93 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 2.94 - Messager messager = processingEnv.getMessager(); 2.95 - Set<TypeElement> classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements())); 2.96 - if (classes.size() > 0) { 2.97 - checkMethodParameters(classes); 2.98 - g.setProcessingEnvironment(processingEnv); 2.99 - g.setClasses(classes); 2.100 + try { 2.101 + Set<TypeElement> classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements())); 2.102 + if (classes.size() > 0) { 2.103 + checkMethodParameters(classes); 2.104 + g.setProcessingEnvironment(processingEnv); 2.105 + g.setClasses(classes); 2.106 + g.run(); 2.107 + } 2.108 + } catch (CompletionFailure cf) { 2.109 + messager.printMessage(ERROR, getMessage("class.not.found", cf.sym.getQualifiedName().toString())); 2.110 + } catch (ClassNotFoundException cnfe) { 2.111 + messager.printMessage(ERROR, getMessage("class.not.found", cnfe.getMessage())); 2.112 + } catch (IOException ioe) { 2.113 + messager.printMessage(ERROR, getMessage("io.exception", ioe.getMessage())); 2.114 + } catch (Util.Exit e) { 2.115 + exit = e; 2.116 + } 2.117 2.118 - try { 2.119 - g.run(); 2.120 - } catch (ClassNotFoundException cnfe) { 2.121 - messager.printMessage(Diagnostic.Kind.ERROR, getMessage("class.not.found", cnfe.getMessage())); 2.122 - } catch (IOException ioe) { 2.123 - messager.printMessage(Diagnostic.Kind.ERROR, getMessage("io.exception", ioe.getMessage())); 2.124 - } catch (Util.Exit e) { 2.125 - exit = e; 2.126 - } 2.127 - } 2.128 return true; 2.129 } 2.130
3.1 --- a/src/share/classes/com/sun/tools/javah/LLNI.java Tue Oct 12 13:15:46 2010 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javah/LLNI.java Tue Oct 12 13:19:47 2010 -0700 3.3 @@ -74,16 +74,21 @@ 3.4 } 3.5 3.6 protected void write(OutputStream o, TypeElement clazz) throws Util.Exit { 3.7 - String cname = mangleClassName(clazz.getQualifiedName().toString()); 3.8 - PrintWriter pw = wrapWriter(o); 3.9 - fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); 3.10 - methods = ElementFilter.methodsIn(clazz.getEnclosedElements()); 3.11 - generateDeclsForClass(pw, clazz, cname); 3.12 - // FIXME check if errors occurred on the PrintWriter and throw exception if so 3.13 + try { 3.14 + String cname = mangleClassName(clazz.getQualifiedName().toString()); 3.15 + PrintWriter pw = wrapWriter(o); 3.16 + fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); 3.17 + methods = ElementFilter.methodsIn(clazz.getEnclosedElements()); 3.18 + generateDeclsForClass(pw, clazz, cname); 3.19 + // FIXME check if errors occurred on the PrintWriter and throw exception if so 3.20 + } catch (TypeSignature.SignatureException e) { 3.21 + util.error("llni.sigerror", e.getMessage()); 3.22 + } 3.23 } 3.24 3.25 protected void generateDeclsForClass(PrintWriter pw, 3.26 - TypeElement clazz, String cname) throws Util.Exit { 3.27 + TypeElement clazz, String cname) 3.28 + throws TypeSignature.SignatureException, Util.Exit { 3.29 doneHandleTypes = new HashSet<String>(); 3.30 /* The following handle types are predefined in "typedefs.h". Suppress 3.31 inclusion in the output by generating them "into the blue" here. */ 3.32 @@ -127,7 +132,8 @@ 3.33 .replace(innerDelim, '_'); 3.34 } 3.35 3.36 - protected void forwardDecls(PrintWriter pw, TypeElement clazz) { 3.37 + protected void forwardDecls(PrintWriter pw, TypeElement clazz) 3.38 + throws TypeSignature.SignatureException { 3.39 TypeElement object = elems.getTypeElement("java.lang.Object"); 3.40 if (clazz.equals(object)) 3.41 return; 3.42 @@ -403,7 +409,7 @@ 3.43 3.44 protected void methodSectionForClass(PrintWriter pw, 3.45 TypeElement clazz, String cname) 3.46 - throws Util.Exit { 3.47 + throws TypeSignature.SignatureException, Util.Exit { 3.48 String methods = methodDecls(clazz, cname); 3.49 3.50 if (methods.length() != 0) { 3.51 @@ -418,7 +424,8 @@ 3.52 } 3.53 } 3.54 3.55 - protected String methodDecls(TypeElement clazz, String cname) throws Util.Exit { 3.56 + protected String methodDecls(TypeElement clazz, String cname) 3.57 + throws TypeSignature.SignatureException, Util.Exit { 3.58 3.59 String res = ""; 3.60 for (ExecutableElement method: methods) { 3.61 @@ -430,7 +437,7 @@ 3.62 3.63 protected String methodDecl(ExecutableElement method, 3.64 TypeElement clazz, String cname) 3.65 - throws Util.Exit { 3.66 + throws TypeSignature.SignatureException, Util.Exit { 3.67 String res = null; 3.68 3.69 TypeMirror retType = types.erasure(method.getReturnType()); 3.70 @@ -474,7 +481,8 @@ 3.71 } 3.72 3.73 protected final String jniMethodName(ExecutableElement method, String cname, 3.74 - boolean longName) { 3.75 + boolean longName) 3.76 + throws TypeSignature.SignatureException { 3.77 String res = "Java_" + cname + "_" + method.getSimpleName(); 3.78 3.79 if (longName) {
4.1 --- a/src/share/classes/com/sun/tools/javah/Mangle.java Tue Oct 12 13:15:46 2010 -0700 4.2 +++ b/src/share/classes/com/sun/tools/javah/Mangle.java Tue Oct 12 13:19:47 2010 -0700 4.3 @@ -114,7 +114,7 @@ 4.4 } 4.5 4.6 public String mangleMethod(ExecutableElement method, TypeElement clazz, 4.7 - int mtype) { 4.8 + int mtype) throws TypeSignature.SignatureException { 4.9 StringBuffer result = new StringBuffer(100); 4.10 result.append("Java_"); 4.11
5.1 --- a/src/share/classes/com/sun/tools/javah/TypeSignature.java Tue Oct 12 13:15:46 2010 -0700 5.2 +++ b/src/share/classes/com/sun/tools/javah/TypeSignature.java Tue Oct 12 13:19:47 2010 -0700 5.3 @@ -51,7 +51,13 @@ 5.4 * @author Sucheta Dambalkar 5.5 */ 5.6 5.7 -public class TypeSignature{ 5.8 +public class TypeSignature { 5.9 + static class SignatureException extends Exception { 5.10 + private static final long serialVersionUID = 1L; 5.11 + SignatureException(String reason) { 5.12 + super(reason); 5.13 + } 5.14 + } 5.15 5.16 Elements elems; 5.17 5.18 @@ -78,14 +84,15 @@ 5.19 /* 5.20 * Returns the type signature of a field according to JVM specs 5.21 */ 5.22 - public String getTypeSignature(String javasignature){ 5.23 + public String getTypeSignature(String javasignature) throws SignatureException { 5.24 return getParamJVMSignature(javasignature); 5.25 } 5.26 5.27 /* 5.28 * Returns the type signature of a method according to JVM specs 5.29 */ 5.30 - public String getTypeSignature(String javasignature, TypeMirror returnType){ 5.31 + public String getTypeSignature(String javasignature, TypeMirror returnType) 5.32 + throws SignatureException { 5.33 String signature = null; //Java type signature. 5.34 String typeSignature = null; //Internal type signature. 5.35 List<String> params = new ArrayList<String>(); //List of parameters. 5.36 @@ -166,7 +173,7 @@ 5.37 /* 5.38 * Returns internal signature of a parameter. 5.39 */ 5.40 - private String getParamJVMSignature(String paramsig) { 5.41 + private String getParamJVMSignature(String paramsig) throws SignatureException { 5.42 String paramJVMSig = ""; 5.43 String componentType =""; 5.44 5.45 @@ -197,7 +204,7 @@ 5.46 /* 5.47 * Returns internal signature of a component. 5.48 */ 5.49 - private String getComponentType(String componentType){ 5.50 + private String getComponentType(String componentType) throws SignatureException { 5.51 5.52 String JVMSig = ""; 5.53 5.54 @@ -216,8 +223,7 @@ 5.55 TypeElement classNameDoc = elems.getTypeElement(componentType); 5.56 5.57 if(classNameDoc == null){ 5.58 - System.out.println("Invalid class type for " + componentType); 5.59 - new Exception().printStackTrace(); 5.60 + throw new SignatureException(componentType); 5.61 }else { 5.62 String classname = classNameDoc.getQualifiedName().toString(); 5.63 String newclassname = classname.replace('.', '/');
6.1 --- a/src/share/classes/com/sun/tools/javah/resources/l10n.properties Tue Oct 12 13:15:46 2010 -0700 6.2 +++ b/src/share/classes/com/sun/tools/javah/resources/l10n.properties Tue Oct 12 13:19:47 2010 -0700 6.3 @@ -45,6 +45,8 @@ 6.4 Can''t mix options -jni and -llni. Try -help. 6.5 jni.no.stubs=\ 6.6 JNI does not require stubs, please refer to the JNI documentation. 6.7 +jni.sigerror=\ 6.8 + Cannot determine signature for {0} 6.9 dir.file.mixed=\ 6.10 Can''t mix options -d and -o. Try -help. 6.11 no.classes.specified=\
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javah/4942232/ParamClassTest.java Tue Oct 12 13:19:47 2010 -0700 7.3 @@ -0,0 +1,36 @@ 7.4 +/* 7.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. 7.11 + * 7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 + * version 2 for more details (a copy is included in the LICENSE file that 7.16 + * accompanied this code). 7.17 + * 7.18 + * You should have received a copy of the GNU General Public License version 7.19 + * 2 along with this work; if not, write to the Free Software Foundation, 7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 + * 7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.23 + * or visit www.oracle.com if you need additional information or have any 7.24 + * questions. 7.25 + */ 7.26 + 7.27 +public class ParamClassTest { 7.28 + static { 7.29 + System.loadLibrary("Test"); 7.30 + } 7.31 + 7.32 + public native void method(Param s); 7.33 + 7.34 + public static void main(String[] a) { 7.35 + } 7.36 +} 7.37 + 7.38 +class Param { 7.39 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javah/4942232/Test.java Tue Oct 12 13:19:47 2010 -0700 8.3 @@ -0,0 +1,141 @@ 8.4 +/* 8.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + */ 8.26 + 8.27 +/* 8.28 + * @test 8.29 + * @bug 4942232 8.30 + * @summary missing param class processes without error 8.31 + * @build ParamClassTest Test 8.32 + * @run main Test 8.33 + */ 8.34 + 8.35 +import java.io.*; 8.36 +import java.util.*; 8.37 + 8.38 +public class Test { 8.39 + public static void main(String... args) throws Exception { 8.40 + new Test().run(); 8.41 + } 8.42 + 8.43 + void run() throws Exception { 8.44 + File testSrc = new File(System.getProperty("test.src")); 8.45 + File testClasses = new File(System.getProperty("test.classes")); 8.46 + 8.47 + // standard use of javah on valid class file 8.48 + String[] test1Args = { 8.49 + "-d", mkdir("test1/out").getPath(), 8.50 + "-classpath", testClasses.getPath(), 8.51 + "ParamClassTest" 8.52 + }; 8.53 + test(test1Args, 0); 8.54 + 8.55 + // extended use of javah on valid source file 8.56 + String[] test2Args = { 8.57 + "-d", mkdir("test2/out").getPath(), 8.58 + "-classpath", testSrc.getPath(), 8.59 + "ParamClassTest" 8.60 + }; 8.61 + test(test2Args, 0); 8.62 + 8.63 + // javah on class file with missing referents 8.64 + File test3Classes = mkdir("test3/classes"); 8.65 + copy(new File(testClasses, "ParamClassTest.class"), test3Classes); 8.66 + String[] test3Args = { 8.67 + "-d", mkdir("test3/out").getPath(), 8.68 + "-classpath", test3Classes.getPath(), 8.69 + "ParamClassTest" 8.70 + }; 8.71 + test(test3Args, 1); 8.72 + 8.73 + // javah on source file with missing referents 8.74 + File test4Src = mkdir("test4/src"); 8.75 + String paramClassTestSrc = readFile(new File(testSrc, "ParamClassTest.java")); 8.76 + writeFile(new File(test4Src, "ParamClassTest.java"), 8.77 + paramClassTestSrc.replaceAll("class Param \\{\\s+\\}", "")); 8.78 + String[] test4Args = { 8.79 + "-d", mkdir("test4/out").getPath(), 8.80 + "-classpath", test4Src.getPath(), 8.81 + "ParamClassTest" 8.82 + }; 8.83 + test(test4Args, 15); 8.84 + 8.85 + if (errors > 0) 8.86 + throw new Exception(errors + " errors occurred"); 8.87 + } 8.88 + 8.89 + void test(String[] args, int expect) { 8.90 + System.err.println("test: " + Arrays.asList(args)); 8.91 + int rc = javah(args); 8.92 + if (rc != expect) 8.93 + error("Unexpected return code: " + rc + "; expected: " + expect); 8.94 + } 8.95 + 8.96 + int javah(String... args) { 8.97 + StringWriter sw = new StringWriter(); 8.98 + PrintWriter pw = new PrintWriter(sw); 8.99 + int rc = com.sun.tools.javah.Main.run(args, pw); 8.100 + pw.close(); 8.101 + String out = sw.toString(); 8.102 + if (!out.isEmpty()) 8.103 + System.err.println(out); 8.104 + return rc; 8.105 + } 8.106 + 8.107 + File mkdir(String path) { 8.108 + File f = new File(path); 8.109 + f.mkdirs(); 8.110 + return f; 8.111 + } 8.112 + 8.113 + void copy(File from, File to) throws IOException { 8.114 + if (to.isDirectory()) 8.115 + to = new File(to, from.getName()); 8.116 + try (DataInputStream in = new DataInputStream(new FileInputStream(from)); 8.117 + FileOutputStream out = new FileOutputStream(to)) { 8.118 + byte[] buf = new byte[(int) from.length()]; 8.119 + in.readFully(buf); 8.120 + out.write(buf); 8.121 + } 8.122 + } 8.123 + 8.124 + String readFile(File f) throws IOException { 8.125 + try (DataInputStream in = new DataInputStream(new FileInputStream(f))) { 8.126 + byte[] buf = new byte[(int) f.length()]; 8.127 + in.readFully(buf); 8.128 + return new String(buf); 8.129 + } 8.130 + } 8.131 + 8.132 + void writeFile(File f, String body) throws IOException { 8.133 + try (FileWriter out = new FileWriter(f)) { 8.134 + out.write(body); 8.135 + } 8.136 + } 8.137 + 8.138 + void error(String msg) { 8.139 + System.err.println(msg); 8.140 + errors++; 8.141 + } 8.142 + 8.143 + int errors; 8.144 +}