Merge jdk8-b32

Mon, 26 Mar 2012 17:32:17 -0700

author
lana
date
Mon, 26 Mar 2012 17:32:17 -0700
changeset 1234
be069d72dde2
parent 1229
ebfe9b8ce039
parent 1233
6b473c9ebf1e
child 1235
46831c72b7f6

Merge

     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Mar 22 12:41:36 2012 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Mar 26 17:32:17 2012 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -126,6 +126,7 @@
    1.11      public final Type cloneableType;
    1.12      public final Type serializableType;
    1.13      public final Type methodHandleType;
    1.14 +    public final Type nativeHeaderType;
    1.15      public final Type polymorphicSignatureType;
    1.16      public final Type throwableType;
    1.17      public final Type errorType;
    1.18 @@ -477,6 +478,7 @@
    1.19                                              List.of(exceptionType), methodClass),
    1.20                               autoCloseableType.tsym);
    1.21          trustMeType = enterClass("java.lang.SafeVarargs");
    1.22 +        nativeHeaderType = enterClass("javax.tools.annotation.GenerateNativeHeader");
    1.23  
    1.24          synthesizeEmptyInterfaceIfMissing(autoCloseableType);
    1.25          synthesizeEmptyInterfaceIfMissing(cloneableType);
     2.1 --- a/src/share/classes/com/sun/tools/javac/file/Locations.java	Thu Mar 22 12:41:36 2012 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/file/Locations.java	Mon Mar 26 17:32:17 2012 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -648,7 +648,8 @@
    2.11              new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCEPATH),
    2.12              new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSORPATH),
    2.13              new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), Option.D),
    2.14 -            new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), Option.S)
    2.15 +            new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), Option.S),
    2.16 +            new OutputLocationHandler((StandardLocation.NATIVE_HEADER_OUTPUT), Option.H)
    2.17          };
    2.18  
    2.19          for (LocationHandler h: handlers) {
     3.1 --- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Thu Mar 22 12:41:36 2012 -0700
     3.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Mar 26 17:32:17 2012 -0700
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -69,11 +69,11 @@
    3.11       */
    3.12      private boolean verbose;
    3.13  
    3.14 -    /** Switch: scrable private names.
    3.15 +    /** Switch: scramble private names.
    3.16       */
    3.17      private boolean scramble;
    3.18  
    3.19 -    /** Switch: scrable private names.
    3.20 +    /** Switch: scramble private names.
    3.21       */
    3.22      private boolean scrambleAll;
    3.23  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java	Mon Mar 26 17:32:17 2012 -0700
     4.3 @@ -0,0 +1,856 @@
     4.4 +/*
     4.5 + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Oracle designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Oracle in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.25 + * or visit www.oracle.com if you need additional information or have any
    4.26 + * questions.
    4.27 + */
    4.28 +
    4.29 +package com.sun.tools.javac.jvm;
    4.30 +
    4.31 +import java.io.IOException;
    4.32 +import java.io.Writer;
    4.33 +import java.util.ArrayList;
    4.34 +import java.util.List;
    4.35 +import java.util.Stack;
    4.36 +import java.util.StringTokenizer;
    4.37 +
    4.38 +import javax.lang.model.element.Element;
    4.39 +import javax.lang.model.element.ExecutableElement;
    4.40 +import javax.lang.model.element.Modifier;
    4.41 +import javax.lang.model.element.Name;
    4.42 +import javax.lang.model.element.TypeElement;
    4.43 +import javax.lang.model.element.VariableElement;
    4.44 +import javax.lang.model.type.ArrayType;
    4.45 +import javax.lang.model.type.DeclaredType;
    4.46 +import javax.lang.model.type.NoType;
    4.47 +import javax.lang.model.type.PrimitiveType;
    4.48 +import javax.lang.model.type.TypeKind;
    4.49 +import javax.lang.model.type.TypeMirror;
    4.50 +import javax.lang.model.type.TypeVariable;
    4.51 +import javax.lang.model.type.TypeVisitor;
    4.52 +import javax.lang.model.util.ElementFilter;
    4.53 +import javax.lang.model.util.Elements;
    4.54 +import javax.lang.model.util.SimpleTypeVisitor8;
    4.55 +import javax.lang.model.util.Types;
    4.56 +
    4.57 +import javax.tools.FileObject;
    4.58 +import javax.tools.JavaFileManager;
    4.59 +import javax.tools.StandardLocation;
    4.60 +
    4.61 +import com.sun.tools.javac.code.Attribute;
    4.62 +import com.sun.tools.javac.code.Flags;
    4.63 +import com.sun.tools.javac.code.Kinds;
    4.64 +import com.sun.tools.javac.code.Scope;
    4.65 +import com.sun.tools.javac.code.Symbol.ClassSymbol;
    4.66 +import com.sun.tools.javac.code.Symtab;
    4.67 +import com.sun.tools.javac.model.JavacElements;
    4.68 +import com.sun.tools.javac.model.JavacTypes;
    4.69 +import com.sun.tools.javac.util.Assert;
    4.70 +import com.sun.tools.javac.util.Context;
    4.71 +import com.sun.tools.javac.util.Log;
    4.72 +import com.sun.tools.javac.util.Options;
    4.73 +
    4.74 +import static com.sun.tools.javac.main.Option.*;
    4.75 +
    4.76 +/** This class provides operations to write native header files for classes.
    4.77 + *
    4.78 + *  <p><b>This is NOT part of any supported API.
    4.79 + *  If you write code that depends on this, you do so at your own risk.
    4.80 + *  This code and its internal interfaces are subject to change or
    4.81 + *  deletion without notice.</b>
    4.82 + */
    4.83 +public class JNIWriter {
    4.84 +    protected static final Context.Key<JNIWriter> jniWriterKey =
    4.85 +        new Context.Key<JNIWriter>();
    4.86 +
    4.87 +    /** Access to files. */
    4.88 +    private final JavaFileManager fileManager;
    4.89 +
    4.90 +    JavacElements elements;
    4.91 +    JavacTypes types;
    4.92 +
    4.93 +    /** The log to use for verbose output.
    4.94 +     */
    4.95 +    private final Log log;
    4.96 +
    4.97 +    /** Switch: verbose output.
    4.98 +     */
    4.99 +    private boolean verbose;
   4.100 +
   4.101 +    /** Switch: check all nested classes of top level class
   4.102 +     */
   4.103 +    private boolean checkAll;
   4.104 +
   4.105 +    private Mangle mangler;
   4.106 +
   4.107 +    private Context context;
   4.108 +
   4.109 +    private Symtab syms;
   4.110 +
   4.111 +    private String lineSep;
   4.112 +
   4.113 +    private final boolean isWindows =
   4.114 +        System.getProperty("os.name").startsWith("Windows");
   4.115 +
   4.116 +    /** Get the ClassWriter instance for this context. */
   4.117 +    public static JNIWriter instance(Context context) {
   4.118 +        JNIWriter instance = context.get(jniWriterKey);
   4.119 +        if (instance == null)
   4.120 +            instance = new JNIWriter(context);
   4.121 +        return instance;
   4.122 +    }
   4.123 +
   4.124 +    /** Construct a class writer, given an options table.
   4.125 +     */
   4.126 +    private JNIWriter(Context context) {
   4.127 +        context.put(jniWriterKey, this);
   4.128 +        fileManager = context.get(JavaFileManager.class);
   4.129 +        log = Log.instance(context);
   4.130 +
   4.131 +        Options options = Options.instance(context);
   4.132 +        verbose = options.isSet(VERBOSE);
   4.133 +        checkAll = options.isSet("javah:full");
   4.134 +
   4.135 +        this.context = context; // for lazyInit()
   4.136 +        syms = Symtab.instance(context);
   4.137 +
   4.138 +        lineSep = System.getProperty("line.separator");
   4.139 +    }
   4.140 +
   4.141 +    private void lazyInit() {
   4.142 +        if (mangler == null) {
   4.143 +            elements = JavacElements.instance(context);
   4.144 +            types = JavacTypes.instance(context);
   4.145 +            mangler = new Mangle(elements, types);
   4.146 +        }
   4.147 +    }
   4.148 +
   4.149 +    public boolean needsHeader(ClassSymbol c) {
   4.150 +        if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
   4.151 +            return false;
   4.152 +
   4.153 +        if (checkAll)
   4.154 +            return needsHeader(c.outermostClass(), true);
   4.155 +        else
   4.156 +            return needsHeader(c, false);
   4.157 +    }
   4.158 +
   4.159 +    private boolean needsHeader(ClassSymbol c, boolean checkNestedClasses) {
   4.160 +        if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
   4.161 +            return false;
   4.162 +
   4.163 +        for (Attribute.Compound a: c.attributes_field) {
   4.164 +            if (a.type.tsym == syms.nativeHeaderType.tsym)
   4.165 +                return true;
   4.166 +        }
   4.167 +        for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
   4.168 +            if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0)
   4.169 +                return true;
   4.170 +        }
   4.171 +        if (checkNestedClasses) {
   4.172 +            for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
   4.173 +                if ((i.sym.kind == Kinds.TYP) && needsHeader(((ClassSymbol) i.sym), true))
   4.174 +                    return true;
   4.175 +            }
   4.176 +        }
   4.177 +        return false;
   4.178 +    }
   4.179 +
   4.180 +    /** Emit a class file for a given class.
   4.181 +     *  @param c      The class from which a class file is generated.
   4.182 +     */
   4.183 +    public FileObject write(ClassSymbol c)
   4.184 +        throws IOException
   4.185 +    {
   4.186 +        String className = c.flatName().toString();
   4.187 +        FileObject outFile
   4.188 +            = fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
   4.189 +                "", className.replaceAll("[.$]", "_") + ".h", null);
   4.190 +        Writer out = outFile.openWriter();
   4.191 +        try {
   4.192 +            write(out, c);
   4.193 +            if (verbose)
   4.194 +                log.printVerbose("wrote.file", outFile);
   4.195 +            out.close();
   4.196 +            out = null;
   4.197 +        } finally {
   4.198 +            if (out != null) {
   4.199 +                // if we are propogating an exception, delete the file
   4.200 +                out.close();
   4.201 +                outFile.delete();
   4.202 +                outFile = null;
   4.203 +            }
   4.204 +        }
   4.205 +        return outFile; // may be null if write failed
   4.206 +    }
   4.207 +
   4.208 +    public void write(Writer out, ClassSymbol sym)
   4.209 +            throws IOException {
   4.210 +        lazyInit();
   4.211 +        try {
   4.212 +            String cname = mangler.mangle(sym.fullname, Mangle.Type.CLASS);
   4.213 +            println(out, fileTop());
   4.214 +            println(out, includes());
   4.215 +            println(out, guardBegin(cname));
   4.216 +            println(out, cppGuardBegin());
   4.217 +
   4.218 +            writeStatics(out, sym);
   4.219 +            writeMethods(out, sym, cname);
   4.220 +
   4.221 +            println(out, cppGuardEnd());
   4.222 +            println(out, guardEnd(cname));
   4.223 +        } catch (TypeSignature.SignatureException e) {
   4.224 +            throw new IOException(e);
   4.225 +        }
   4.226 +    }
   4.227 +
   4.228 +    protected void writeStatics(Writer out, ClassSymbol sym) throws IOException {
   4.229 +        List<VariableElement> classfields = getAllFields(sym);
   4.230 +
   4.231 +        for (VariableElement v: classfields) {
   4.232 +            if (!v.getModifiers().contains(Modifier.STATIC))
   4.233 +                continue;
   4.234 +            String s = null;
   4.235 +            s = defineForStatic(sym, v);
   4.236 +            if (s != null) {
   4.237 +                println(out, s);
   4.238 +            }
   4.239 +        }
   4.240 +    }
   4.241 +
   4.242 +    /**
   4.243 +     * Including super class fields.
   4.244 +     */
   4.245 +    List<VariableElement> getAllFields(TypeElement subclazz) {
   4.246 +        List<VariableElement> fields = new ArrayList<VariableElement>();
   4.247 +        TypeElement cd = null;
   4.248 +        Stack<TypeElement> s = new Stack<TypeElement>();
   4.249 +
   4.250 +        cd = subclazz;
   4.251 +        while (true) {
   4.252 +            s.push(cd);
   4.253 +            TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
   4.254 +            if (c == null)
   4.255 +                break;
   4.256 +            cd = c;
   4.257 +        }
   4.258 +
   4.259 +        while (!s.empty()) {
   4.260 +            cd = s.pop();
   4.261 +            fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
   4.262 +        }
   4.263 +
   4.264 +        return fields;
   4.265 +    }
   4.266 +
   4.267 +    protected String defineForStatic(TypeElement c, VariableElement f) {
   4.268 +        CharSequence cnamedoc = c.getQualifiedName();
   4.269 +        CharSequence fnamedoc = f.getSimpleName();
   4.270 +
   4.271 +        String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
   4.272 +        String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
   4.273 +
   4.274 +        Assert.check(f.getModifiers().contains(Modifier.STATIC));
   4.275 +
   4.276 +        if (f.getModifiers().contains(Modifier.FINAL)) {
   4.277 +            Object value = null;
   4.278 +
   4.279 +            value = f.getConstantValue();
   4.280 +
   4.281 +            if (value != null) { /* so it is a ConstantExpression */
   4.282 +                String constString = null;
   4.283 +                if ((value instanceof Integer)
   4.284 +                    || (value instanceof Byte)
   4.285 +                    || (value instanceof Short)) {
   4.286 +                    /* covers byte, short, int */
   4.287 +                    constString = value.toString() + "L";
   4.288 +                } else if (value instanceof Boolean) {
   4.289 +                    constString = ((Boolean) value) ? "1L" : "0L";
   4.290 +                } else if (value instanceof Character) {
   4.291 +                    Character ch = (Character) value;
   4.292 +                    constString = String.valueOf(((int) ch) & 0xffff) + "L";
   4.293 +                } else if (value instanceof Long) {
   4.294 +                    // Visual C++ supports the i64 suffix, not LL.
   4.295 +                    if (isWindows)
   4.296 +                        constString = value.toString() + "i64";
   4.297 +                    else
   4.298 +                        constString = value.toString() + "LL";
   4.299 +                } else if (value instanceof Float) {
   4.300 +                    /* bug for bug */
   4.301 +                    float fv = ((Float)value).floatValue();
   4.302 +                    if (Float.isInfinite(fv))
   4.303 +                        constString = ((fv < 0) ? "-" : "") + "Inff";
   4.304 +                    else
   4.305 +                        constString = value.toString() + "f";
   4.306 +                } else if (value instanceof Double) {
   4.307 +                    /* bug for bug */
   4.308 +                    double d = ((Double)value).doubleValue();
   4.309 +                    if (Double.isInfinite(d))
   4.310 +                        constString = ((d < 0) ? "-" : "") + "InfD";
   4.311 +                    else
   4.312 +                        constString = value.toString();
   4.313 +                }
   4.314 +
   4.315 +                if (constString != null) {
   4.316 +                    StringBuilder s = new StringBuilder("#undef ");
   4.317 +                    s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
   4.318 +                    s.append("#define "); s.append(cname); s.append("_");
   4.319 +                    s.append(fname); s.append(" "); s.append(constString);
   4.320 +                    return s.toString();
   4.321 +                }
   4.322 +
   4.323 +            }
   4.324 +        }
   4.325 +
   4.326 +        return null;
   4.327 +    }
   4.328 +
   4.329 +
   4.330 +    protected void writeMethods(Writer out, ClassSymbol sym, String cname)
   4.331 +            throws IOException, TypeSignature.SignatureException {
   4.332 +        List<ExecutableElement> classmethods = ElementFilter.methodsIn(sym.getEnclosedElements());
   4.333 +        for (ExecutableElement md: classmethods) {
   4.334 +            if(md.getModifiers().contains(Modifier.NATIVE)){
   4.335 +                TypeMirror mtr = types.erasure(md.getReturnType());
   4.336 +                String sig = signature(md);
   4.337 +                TypeSignature newtypesig = new TypeSignature(elements);
   4.338 +                CharSequence methodName = md.getSimpleName();
   4.339 +                boolean longName = false;
   4.340 +                for (ExecutableElement md2: classmethods) {
   4.341 +                    if ((md2 != md)
   4.342 +                        && (methodName.equals(md2.getSimpleName()))
   4.343 +                        && (md2.getModifiers().contains(Modifier.NATIVE)))
   4.344 +                        longName = true;
   4.345 +
   4.346 +                }
   4.347 +                println(out, "/*");
   4.348 +                println(out, " * Class:     " + cname);
   4.349 +                println(out, " * Method:    " +
   4.350 +                           mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
   4.351 +                println(out, " * Signature: " + newtypesig.getTypeSignature(sig, mtr));
   4.352 +                println(out, " */");
   4.353 +                println(out, "JNIEXPORT " + jniType(mtr) +
   4.354 +                           " JNICALL " +
   4.355 +                           mangler.mangleMethod(md, sym,
   4.356 +                                               (longName) ?
   4.357 +                                               Mangle.Type.METHOD_JNI_LONG :
   4.358 +                                               Mangle.Type.METHOD_JNI_SHORT));
   4.359 +                print(out, "  (JNIEnv *, ");
   4.360 +                List<? extends VariableElement> paramargs = md.getParameters();
   4.361 +                List<TypeMirror> args = new ArrayList<TypeMirror>();
   4.362 +                for (VariableElement p: paramargs) {
   4.363 +                    args.add(types.erasure(p.asType()));
   4.364 +                }
   4.365 +                if (md.getModifiers().contains(Modifier.STATIC))
   4.366 +                    print(out, "jclass");
   4.367 +                else
   4.368 +                    print(out, "jobject");
   4.369 +
   4.370 +                for (TypeMirror arg: args) {
   4.371 +                    print(out, ", ");
   4.372 +                    print(out, jniType(arg));
   4.373 +                }
   4.374 +                println(out, ");"
   4.375 +                        + lineSep);
   4.376 +            }
   4.377 +        }
   4.378 +    }
   4.379 +
   4.380 +    // c.f. MethodDoc.signature
   4.381 +    String signature(ExecutableElement e) {
   4.382 +        StringBuilder sb = new StringBuilder("(");
   4.383 +        String sep = "";
   4.384 +        for (VariableElement p: e.getParameters()) {
   4.385 +            sb.append(sep);
   4.386 +            sb.append(types.erasure(p.asType()).toString());
   4.387 +            sep = ",";
   4.388 +        }
   4.389 +        sb.append(")");
   4.390 +        return sb.toString();
   4.391 +    }
   4.392 +
   4.393 +    protected final String jniType(TypeMirror t) {
   4.394 +        TypeElement throwable = elements.getTypeElement("java.lang.Throwable");
   4.395 +        TypeElement jClass = elements.getTypeElement("java.lang.Class");
   4.396 +        TypeElement jString = elements.getTypeElement("java.lang.String");
   4.397 +        Element tclassDoc = types.asElement(t);
   4.398 +
   4.399 +
   4.400 +        switch (t.getKind()) {
   4.401 +            case ARRAY: {
   4.402 +                TypeMirror ct = ((ArrayType) t).getComponentType();
   4.403 +                switch (ct.getKind()) {
   4.404 +                    case BOOLEAN:  return "jbooleanArray";
   4.405 +                    case BYTE:     return "jbyteArray";
   4.406 +                    case CHAR:     return "jcharArray";
   4.407 +                    case SHORT:    return "jshortArray";
   4.408 +                    case INT:      return "jintArray";
   4.409 +                    case LONG:     return "jlongArray";
   4.410 +                    case FLOAT:    return "jfloatArray";
   4.411 +                    case DOUBLE:   return "jdoubleArray";
   4.412 +                    case ARRAY:
   4.413 +                    case DECLARED: return "jobjectArray";
   4.414 +                    default: throw new Error(ct.toString());
   4.415 +                }
   4.416 +            }
   4.417 +
   4.418 +            case VOID:     return "void";
   4.419 +            case BOOLEAN:  return "jboolean";
   4.420 +            case BYTE:     return "jbyte";
   4.421 +            case CHAR:     return "jchar";
   4.422 +            case SHORT:    return "jshort";
   4.423 +            case INT:      return "jint";
   4.424 +            case LONG:     return "jlong";
   4.425 +            case FLOAT:    return "jfloat";
   4.426 +            case DOUBLE:   return "jdouble";
   4.427 +
   4.428 +            case DECLARED: {
   4.429 +                if (tclassDoc.equals(jString))
   4.430 +                    return "jstring";
   4.431 +                else if (types.isAssignable(t, throwable.asType()))
   4.432 +                    return "jthrowable";
   4.433 +                else if (types.isAssignable(t, jClass.asType()))
   4.434 +                    return "jclass";
   4.435 +                else
   4.436 +                    return "jobject";
   4.437 +            }
   4.438 +        }
   4.439 +
   4.440 +        Assert.check(false, "jni unknown type");
   4.441 +        return null; /* dead code. */
   4.442 +    }
   4.443 +
   4.444 +    protected String fileTop() {
   4.445 +        return "/* DO NOT EDIT THIS FILE - it is machine generated */";
   4.446 +    }
   4.447 +
   4.448 +    protected String includes() {
   4.449 +        return "#include <jni.h>";
   4.450 +    }
   4.451 +
   4.452 +    /*
   4.453 +     * Deal with the C pre-processor.
   4.454 +     */
   4.455 +    protected String cppGuardBegin() {
   4.456 +        return "#ifdef __cplusplus" + lineSep
   4.457 +                + "extern \"C\" {" + lineSep
   4.458 +                + "#endif";
   4.459 +    }
   4.460 +
   4.461 +    protected String cppGuardEnd() {
   4.462 +        return "#ifdef __cplusplus" + lineSep
   4.463 +                + "}" + lineSep
   4.464 +                + "#endif";
   4.465 +    }
   4.466 +
   4.467 +    protected String guardBegin(String cname) {
   4.468 +        return "/* Header for class " + cname + " */" + lineSep
   4.469 +                + lineSep
   4.470 +                + "#ifndef _Included_" + cname + lineSep
   4.471 +                + "#define _Included_" + cname;
   4.472 +    }
   4.473 +
   4.474 +    protected String guardEnd(String cname) {
   4.475 +        return "#endif";
   4.476 +    }
   4.477 +
   4.478 +    protected void print(Writer out, String text) throws IOException {
   4.479 +        out.write(text);
   4.480 +    }
   4.481 +
   4.482 +    protected void println(Writer out, String text) throws IOException {
   4.483 +        out.write(text);
   4.484 +        out.write(lineSep);
   4.485 +    }
   4.486 +
   4.487 +
   4.488 +    private static class Mangle {
   4.489 +
   4.490 +        public static class Type {
   4.491 +            public static final int CLASS            = 1;
   4.492 +            public static final int FIELDSTUB        = 2;
   4.493 +            public static final int FIELD            = 3;
   4.494 +            public static final int JNI              = 4;
   4.495 +            public static final int SIGNATURE        = 5;
   4.496 +            public static final int METHOD_JDK_1     = 6;
   4.497 +            public static final int METHOD_JNI_SHORT = 7;
   4.498 +            public static final int METHOD_JNI_LONG  = 8;
   4.499 +        };
   4.500 +
   4.501 +        private Elements elems;
   4.502 +        private Types types;
   4.503 +
   4.504 +        Mangle(Elements elems, Types types) {
   4.505 +            this.elems = elems;
   4.506 +            this.types = types;
   4.507 +        }
   4.508 +
   4.509 +        public final String mangle(CharSequence name, int mtype) {
   4.510 +            StringBuilder result = new StringBuilder(100);
   4.511 +            int length = name.length();
   4.512 +
   4.513 +            for (int i = 0; i < length; i++) {
   4.514 +                char ch = name.charAt(i);
   4.515 +                if (isalnum(ch)) {
   4.516 +                    result.append(ch);
   4.517 +                } else if ((ch == '.') &&
   4.518 +                           mtype == Mangle.Type.CLASS) {
   4.519 +                    result.append('_');
   4.520 +                } else if (( ch == '$') &&
   4.521 +                           mtype == Mangle.Type.CLASS) {
   4.522 +                    result.append('_');
   4.523 +                    result.append('_');
   4.524 +                } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) {
   4.525 +                    result.append('_');
   4.526 +                } else if (ch == '_' && mtype == Mangle.Type.CLASS) {
   4.527 +                    result.append('_');
   4.528 +                } else if (mtype == Mangle.Type.JNI) {
   4.529 +                    String esc = null;
   4.530 +                    if (ch == '_')
   4.531 +                        esc = "_1";
   4.532 +                    else if (ch == '.')
   4.533 +                        esc = "_";
   4.534 +                    else if (ch == ';')
   4.535 +                        esc = "_2";
   4.536 +                    else if (ch == '[')
   4.537 +                        esc = "_3";
   4.538 +                    if (esc != null) {
   4.539 +                        result.append(esc);
   4.540 +                    } else {
   4.541 +                        result.append(mangleChar(ch));
   4.542 +                    }
   4.543 +                } else if (mtype == Mangle.Type.SIGNATURE) {
   4.544 +                    if (isprint(ch)) {
   4.545 +                        result.append(ch);
   4.546 +                    } else {
   4.547 +                        result.append(mangleChar(ch));
   4.548 +                    }
   4.549 +                } else {
   4.550 +                    result.append(mangleChar(ch));
   4.551 +                }
   4.552 +            }
   4.553 +
   4.554 +            return result.toString();
   4.555 +        }
   4.556 +
   4.557 +        public String mangleMethod(ExecutableElement method, TypeElement clazz,
   4.558 +                                          int mtype) throws TypeSignature.SignatureException {
   4.559 +            StringBuilder result = new StringBuilder(100);
   4.560 +            result.append("Java_");
   4.561 +
   4.562 +            if (mtype == Mangle.Type.METHOD_JDK_1) {
   4.563 +                result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS));
   4.564 +                result.append('_');
   4.565 +                result.append(mangle(method.getSimpleName(),
   4.566 +                                     Mangle.Type.FIELD));
   4.567 +                result.append("_stub");
   4.568 +                return result.toString();
   4.569 +            }
   4.570 +
   4.571 +            /* JNI */
   4.572 +            result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
   4.573 +            result.append('_');
   4.574 +            result.append(mangle(method.getSimpleName(),
   4.575 +                                 Mangle.Type.JNI));
   4.576 +            if (mtype == Mangle.Type.METHOD_JNI_LONG) {
   4.577 +                result.append("__");
   4.578 +                String typesig = signature(method);
   4.579 +                TypeSignature newTypeSig = new TypeSignature(elems);
   4.580 +                String sig = newTypeSig.getTypeSignature(typesig,  method.getReturnType());
   4.581 +                sig = sig.substring(1);
   4.582 +                sig = sig.substring(0, sig.lastIndexOf(')'));
   4.583 +                sig = sig.replace('/', '.');
   4.584 +                result.append(mangle(sig, Mangle.Type.JNI));
   4.585 +            }
   4.586 +
   4.587 +            return result.toString();
   4.588 +        }
   4.589 +        //where
   4.590 +            private String getInnerQualifiedName(TypeElement clazz) {
   4.591 +                return elems.getBinaryName(clazz).toString();
   4.592 +            }
   4.593 +
   4.594 +        public final String mangleChar(char ch) {
   4.595 +            String s = Integer.toHexString(ch);
   4.596 +            int nzeros = 5 - s.length();
   4.597 +            char[] result = new char[6];
   4.598 +            result[0] = '_';
   4.599 +            for (int i = 1; i <= nzeros; i++)
   4.600 +                result[i] = '0';
   4.601 +            for (int i = nzeros+1, j = 0; i < 6; i++, j++)
   4.602 +                result[i] = s.charAt(j);
   4.603 +            return new String(result);
   4.604 +        }
   4.605 +
   4.606 +        // Warning: duplicated in Gen
   4.607 +        private String signature(ExecutableElement e) {
   4.608 +            StringBuilder sb = new StringBuilder();
   4.609 +            String sep = "(";
   4.610 +            for (VariableElement p: e.getParameters()) {
   4.611 +                sb.append(sep);
   4.612 +                sb.append(types.erasure(p.asType()).toString());
   4.613 +                sep = ",";
   4.614 +            }
   4.615 +            sb.append(")");
   4.616 +            return sb.toString();
   4.617 +        }
   4.618 +
   4.619 +        /* Warning: Intentional ASCII operation. */
   4.620 +        private static boolean isalnum(char ch) {
   4.621 +            return ch <= 0x7f && /* quick test */
   4.622 +                ((ch >= 'A' && ch <= 'Z') ||
   4.623 +                 (ch >= 'a' && ch <= 'z') ||
   4.624 +                 (ch >= '0' && ch <= '9'));
   4.625 +        }
   4.626 +
   4.627 +        /* Warning: Intentional ASCII operation. */
   4.628 +        private static boolean isprint(char ch) {
   4.629 +            return ch >= 32 && ch <= 126;
   4.630 +        }
   4.631 +    }
   4.632 +
   4.633 +    private static class TypeSignature {
   4.634 +        static class SignatureException extends Exception {
   4.635 +            private static final long serialVersionUID = 1L;
   4.636 +            SignatureException(String reason) {
   4.637 +                super(reason);
   4.638 +            }
   4.639 +        }
   4.640 +
   4.641 +        Elements elems;
   4.642 +
   4.643 +        /* Signature Characters */
   4.644 +
   4.645 +        private static final String SIG_VOID                   = "V";
   4.646 +        private static final String SIG_BOOLEAN                = "Z";
   4.647 +        private static final String SIG_BYTE                   = "B";
   4.648 +        private static final String SIG_CHAR                   = "C";
   4.649 +        private static final String SIG_SHORT                  = "S";
   4.650 +        private static final String SIG_INT                    = "I";
   4.651 +        private static final String SIG_LONG                   = "J";
   4.652 +        private static final String SIG_FLOAT                  = "F";
   4.653 +        private static final String SIG_DOUBLE                 = "D";
   4.654 +        private static final String SIG_ARRAY                  = "[";
   4.655 +        private static final String SIG_CLASS                  = "L";
   4.656 +
   4.657 +
   4.658 +
   4.659 +        public TypeSignature(Elements elems){
   4.660 +            this.elems = elems;
   4.661 +        }
   4.662 +
   4.663 +        /*
   4.664 +         * Returns the type signature of a field according to JVM specs
   4.665 +         */
   4.666 +        public String getTypeSignature(String javasignature) throws SignatureException {
   4.667 +            return getParamJVMSignature(javasignature);
   4.668 +        }
   4.669 +
   4.670 +        /*
   4.671 +         * Returns the type signature of a method according to JVM specs
   4.672 +         */
   4.673 +        public String getTypeSignature(String javasignature, TypeMirror returnType)
   4.674 +                throws SignatureException {
   4.675 +            String signature = null; //Java type signature.
   4.676 +            String typeSignature = null; //Internal type signature.
   4.677 +            List<String> params = new ArrayList<String>(); //List of parameters.
   4.678 +            String paramsig = null; //Java parameter signature.
   4.679 +            String paramJVMSig = null; //Internal parameter signature.
   4.680 +            String returnSig = null; //Java return type signature.
   4.681 +            String returnJVMType = null; //Internal return type signature.
   4.682 +            int dimensions = 0; //Array dimension.
   4.683 +
   4.684 +            int startIndex = -1;
   4.685 +            int endIndex = -1;
   4.686 +            StringTokenizer st = null;
   4.687 +            int i = 0;
   4.688 +
   4.689 +            // Gets the actual java signature without parentheses.
   4.690 +            if (javasignature != null) {
   4.691 +                startIndex = javasignature.indexOf("(");
   4.692 +                endIndex = javasignature.indexOf(")");
   4.693 +            }
   4.694 +
   4.695 +            if (((startIndex != -1) && (endIndex != -1))
   4.696 +                &&(startIndex+1 < javasignature.length())
   4.697 +                &&(endIndex < javasignature.length())) {
   4.698 +                signature = javasignature.substring(startIndex+1, endIndex);
   4.699 +            }
   4.700 +
   4.701 +            // Separates parameters.
   4.702 +            if (signature != null) {
   4.703 +                if (signature.indexOf(",") != -1) {
   4.704 +                    st = new StringTokenizer(signature, ",");
   4.705 +                    if (st != null) {
   4.706 +                        while (st.hasMoreTokens()) {
   4.707 +                            params.add(st.nextToken());
   4.708 +                        }
   4.709 +                    }
   4.710 +                } else {
   4.711 +                    params.add(signature);
   4.712 +                }
   4.713 +            }
   4.714 +
   4.715 +            /* JVM type signature. */
   4.716 +            typeSignature = "(";
   4.717 +
   4.718 +            // Gets indivisual internal parameter signature.
   4.719 +            while (params.isEmpty() != true) {
   4.720 +                paramsig = params.remove(i).trim();
   4.721 +                paramJVMSig  = getParamJVMSignature(paramsig);
   4.722 +                if (paramJVMSig != null) {
   4.723 +                    typeSignature += paramJVMSig;
   4.724 +                }
   4.725 +            }
   4.726 +
   4.727 +            typeSignature += ")";
   4.728 +
   4.729 +            // Get internal return type signature.
   4.730 +
   4.731 +            returnJVMType = "";
   4.732 +            if (returnType != null) {
   4.733 +                dimensions = dimensions(returnType);
   4.734 +            }
   4.735 +
   4.736 +            //Gets array dimension of return type.
   4.737 +            while (dimensions-- > 0) {
   4.738 +                returnJVMType += "[";
   4.739 +            }
   4.740 +            if (returnType != null) {
   4.741 +                returnSig = qualifiedTypeName(returnType);
   4.742 +                returnJVMType += getComponentType(returnSig);
   4.743 +            } else {
   4.744 +                System.out.println("Invalid return type.");
   4.745 +            }
   4.746 +
   4.747 +            typeSignature += returnJVMType;
   4.748 +
   4.749 +            return typeSignature;
   4.750 +        }
   4.751 +
   4.752 +        /*
   4.753 +         * Returns internal signature of a parameter.
   4.754 +         */
   4.755 +        private String getParamJVMSignature(String paramsig) throws SignatureException {
   4.756 +            String paramJVMSig = "";
   4.757 +            String componentType ="";
   4.758 +
   4.759 +            if(paramsig != null){
   4.760 +
   4.761 +                if(paramsig.indexOf("[]") != -1) {
   4.762 +                    // Gets array dimension.
   4.763 +                    int endindex = paramsig.indexOf("[]");
   4.764 +                    componentType = paramsig.substring(0, endindex);
   4.765 +                    String dimensionString =  paramsig.substring(endindex);
   4.766 +                    if(dimensionString != null){
   4.767 +                        while(dimensionString.indexOf("[]") != -1){
   4.768 +                            paramJVMSig += "[";
   4.769 +                            int beginindex = dimensionString.indexOf("]") + 1;
   4.770 +                            if(beginindex < dimensionString.length()){
   4.771 +                                dimensionString = dimensionString.substring(beginindex);
   4.772 +                            }else
   4.773 +                                dimensionString = "";
   4.774 +                        }
   4.775 +                    }
   4.776 +                } else componentType = paramsig;
   4.777 +
   4.778 +                paramJVMSig += getComponentType(componentType);
   4.779 +            }
   4.780 +            return paramJVMSig;
   4.781 +        }
   4.782 +
   4.783 +        /*
   4.784 +         * Returns internal signature of a component.
   4.785 +         */
   4.786 +        private String getComponentType(String componentType) throws SignatureException {
   4.787 +
   4.788 +            String JVMSig = "";
   4.789 +
   4.790 +            if(componentType != null){
   4.791 +                if(componentType.equals("void")) JVMSig += SIG_VOID ;
   4.792 +                else if(componentType.equals("boolean"))  JVMSig += SIG_BOOLEAN ;
   4.793 +                else if(componentType.equals("byte")) JVMSig += SIG_BYTE ;
   4.794 +                else if(componentType.equals("char"))  JVMSig += SIG_CHAR ;
   4.795 +                else if(componentType.equals("short"))  JVMSig += SIG_SHORT ;
   4.796 +                else if(componentType.equals("int"))  JVMSig += SIG_INT ;
   4.797 +                else if(componentType.equals("long"))  JVMSig += SIG_LONG ;
   4.798 +                else if(componentType.equals("float")) JVMSig += SIG_FLOAT ;
   4.799 +                else if(componentType.equals("double"))  JVMSig += SIG_DOUBLE ;
   4.800 +                else {
   4.801 +                    if(!componentType.equals("")){
   4.802 +                        TypeElement classNameDoc = elems.getTypeElement(componentType);
   4.803 +
   4.804 +                        if(classNameDoc == null){
   4.805 +                            throw new SignatureException(componentType);
   4.806 +                        }else {
   4.807 +                            String classname = classNameDoc.getQualifiedName().toString();
   4.808 +                            String newclassname = classname.replace('.', '/');
   4.809 +                            JVMSig += "L";
   4.810 +                            JVMSig += newclassname;
   4.811 +                            JVMSig += ";";
   4.812 +                        }
   4.813 +                    }
   4.814 +                }
   4.815 +            }
   4.816 +            return JVMSig;
   4.817 +        }
   4.818 +
   4.819 +        int dimensions(TypeMirror t) {
   4.820 +            if (t.getKind() != TypeKind.ARRAY)
   4.821 +                return 0;
   4.822 +            return 1 + dimensions(((ArrayType) t).getComponentType());
   4.823 +        }
   4.824 +
   4.825 +
   4.826 +        String qualifiedTypeName(TypeMirror type) {
   4.827 +            TypeVisitor<Name, Void> v = new SimpleTypeVisitor8<Name, Void>() {
   4.828 +                @Override
   4.829 +                public Name visitArray(ArrayType t, Void p) {
   4.830 +                    return t.getComponentType().accept(this, p);
   4.831 +                }
   4.832 +
   4.833 +                @Override
   4.834 +                public Name visitDeclared(DeclaredType t, Void p) {
   4.835 +                    return ((TypeElement) t.asElement()).getQualifiedName();
   4.836 +                }
   4.837 +
   4.838 +                @Override
   4.839 +                public Name visitPrimitive(PrimitiveType t, Void p) {
   4.840 +                    return elems.getName(t.toString());
   4.841 +                }
   4.842 +
   4.843 +                @Override
   4.844 +                public Name visitNoType(NoType t, Void p) {
   4.845 +                    if (t.getKind() == TypeKind.VOID)
   4.846 +                        return elems.getName("void");
   4.847 +                    return defaultAction(t, p);
   4.848 +                }
   4.849 +
   4.850 +                @Override
   4.851 +                public Name visitTypeVariable(TypeVariable t, Void p) {
   4.852 +                    return t.getUpperBound().accept(this, p);
   4.853 +                }
   4.854 +            };
   4.855 +            return v.visit(type).toString();
   4.856 +        }
   4.857 +    }
   4.858 +
   4.859 +}
     5.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Mar 22 12:41:36 2012 -0700
     5.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Mar 26 17:32:17 2012 -0700
     5.3 @@ -44,6 +44,8 @@
     5.4  import javax.tools.DiagnosticListener;
     5.5  import javax.tools.JavaFileManager;
     5.6  import javax.tools.JavaFileObject;
     5.7 +import javax.tools.StandardLocation;
     5.8 +
     5.9  import static javax.tools.StandardLocation.CLASS_OUTPUT;
    5.10  
    5.11  import com.sun.source.util.TaskEvent;
    5.12 @@ -60,6 +62,7 @@
    5.13  import com.sun.tools.javac.tree.JCTree.*;
    5.14  import com.sun.tools.javac.util.*;
    5.15  import com.sun.tools.javac.util.Log.WriterKind;
    5.16 +
    5.17  import static com.sun.tools.javac.main.Option.*;
    5.18  import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
    5.19  import static com.sun.tools.javac.util.ListBuffer.lb;
    5.20 @@ -227,6 +230,10 @@
    5.21       */
    5.22      protected ClassWriter writer;
    5.23  
    5.24 +    /** The native header writer.
    5.25 +     */
    5.26 +    protected JNIWriter jniWriter;
    5.27 +
    5.28      /** The module for the symbol table entry phases.
    5.29       */
    5.30      protected Enter enter;
    5.31 @@ -330,6 +337,7 @@
    5.32          reader = ClassReader.instance(context);
    5.33          make = TreeMaker.instance(context);
    5.34          writer = ClassWriter.instance(context);
    5.35 +        jniWriter = JNIWriter.instance(context);
    5.36          enter = Enter.instance(context);
    5.37          todo = Todo.instance(context);
    5.38  
    5.39 @@ -1450,8 +1458,13 @@
    5.40                  JavaFileObject file;
    5.41                  if (usePrintSource)
    5.42                      file = printSource(env, cdef);
    5.43 -                else
    5.44 +                else {
    5.45 +                    if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT)
    5.46 +                            && jniWriter.needsHeader(cdef.sym)) {
    5.47 +                        jniWriter.write(cdef.sym);
    5.48 +                    }
    5.49                      file = genCode(env, cdef);
    5.50 +                }
    5.51                  if (results != null && file != null)
    5.52                      results.add(file);
    5.53              } catch (IOException ex) {
     6.1 --- a/src/share/classes/com/sun/tools/javac/main/Option.java	Thu Mar 22 12:41:36 2012 -0700
     6.2 +++ b/src/share/classes/com/sun/tools/javac/main/Option.java	Mon Mar 26 17:32:17 2012 -0700
     6.3 @@ -1,5 +1,5 @@
     6.4  /*
     6.5 - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
     6.6 + * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
     6.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.8   *
     6.9   * This code is free software; you can redistribute it and/or modify it
    6.10 @@ -160,6 +160,8 @@
    6.11  
    6.12      S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER),
    6.13  
    6.14 +    H("-h", "opt.arg.directory", "opt.headerDest", STANDARD, FILEMANAGER),
    6.15 +
    6.16      IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"),
    6.17  
    6.18      ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) {
     7.1 --- a/src/share/classes/com/sun/tools/javac/resources/javac.properties	Thu Mar 22 12:41:36 2012 -0700
     7.2 +++ b/src/share/classes/com/sun/tools/javac/resources/javac.properties	Mon Mar 26 17:32:17 2012 -0700
     7.3 @@ -1,5 +1,5 @@
     7.4  #
     7.5 -# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     7.6 +# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     7.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.8  #
     7.9  # This code is free software; you can redistribute it and/or modify it
    7.10 @@ -61,6 +61,8 @@
    7.11      Specify where to place generated class files
    7.12  javac.opt.sourceDest=\
    7.13      Specify where to place generated source files
    7.14 +javac.opt.headerDest=\
    7.15 +    Specify where to place generated native header files
    7.16  javac.opt.J=\
    7.17      Pass <flag> directly to the runtime system
    7.18  javac.opt.encoding=\
     8.1 --- a/src/share/classes/javax/tools/StandardLocation.java	Thu Mar 22 12:41:36 2012 -0700
     8.2 +++ b/src/share/classes/javax/tools/StandardLocation.java	Mon Mar 26 17:32:17 2012 -0700
     8.3 @@ -1,5 +1,5 @@
     8.4  /*
     8.5 - * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
     8.6 + * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
     8.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.8   *
     8.9   * This code is free software; you can redistribute it and/or modify it
    8.10 @@ -66,7 +66,13 @@
    8.11       * Location to search for platform classes.  Sometimes called
    8.12       * the boot class path.
    8.13       */
    8.14 -    PLATFORM_CLASS_PATH;
    8.15 +    PLATFORM_CLASS_PATH,
    8.16 +
    8.17 +    /**
    8.18 +     * Location of new native header files.
    8.19 +     * @since 1.8
    8.20 +     */
    8.21 +    NATIVE_HEADER_OUTPUT;
    8.22  
    8.23      /**
    8.24       * Gets a location object with the given name.  The following
    8.25 @@ -97,6 +103,13 @@
    8.26      public String getName() { return name(); }
    8.27  
    8.28      public boolean isOutputLocation() {
    8.29 -        return this == CLASS_OUTPUT || this == SOURCE_OUTPUT;
    8.30 +        switch (this) {
    8.31 +            case CLASS_OUTPUT:
    8.32 +            case SOURCE_OUTPUT:
    8.33 +            case NATIVE_HEADER_OUTPUT:
    8.34 +                return true;
    8.35 +            default:
    8.36 +                return false;
    8.37 +        }
    8.38      }
    8.39  }
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/share/classes/javax/tools/annotation/GenerateNativeHeader.java	Mon Mar 26 17:32:17 2012 -0700
     9.3 @@ -0,0 +1,47 @@
     9.4 +/*
     9.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.  Oracle designates this
    9.11 + * particular file as subject to the "Classpath" exception as provided
    9.12 + * by Oracle in the LICENSE file that accompanied this code.
    9.13 + *
    9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.17 + * version 2 for more details (a copy is included in the LICENSE file that
    9.18 + * accompanied this code).
    9.19 + *
    9.20 + * You should have received a copy of the GNU General Public License version
    9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.23 + *
    9.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.25 + * or visit www.oracle.com if you need additional information or have any
    9.26 + * questions.
    9.27 + */
    9.28 +
    9.29 +package javax.tools.annotation;
    9.30 +
    9.31 +import java.lang.annotation.*;
    9.32 +import static java.lang.annotation.RetentionPolicy.*;
    9.33 +import static java.lang.annotation.ElementType.*;
    9.34 +
    9.35 +/**
    9.36 + * An annotation used to indicate that a native header file
    9.37 + * should be generated for this class.
    9.38 + *
    9.39 + * Normally, the presence of native methods is a sufficient
    9.40 + * indication of the need for a native header file.  However,
    9.41 + * in some cases, a class may contain constants of interest to
    9.42 + * native code, without containing any native methods.
    9.43 + *
    9.44 + * @since 1.8
    9.45 + */
    9.46 +@Documented
    9.47 +@Target(TYPE)
    9.48 +@Retention(SOURCE)
    9.49 +public @interface GenerateNativeHeader {
    9.50 +}
    10.1 --- a/test/tools/javac/api/7086261/T7086261.java	Thu Mar 22 12:41:36 2012 -0700
    10.2 +++ b/test/tools/javac/api/7086261/T7086261.java	Mon Mar 26 17:32:17 2012 -0700
    10.3 @@ -1,5 +1,5 @@
    10.4  /*
    10.5 - * Copyright (c) 20011, Oracle and/or its affiliates. All rights reserved.
    10.6 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
    10.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.8   *
    10.9   * This code is free software; you can redistribute it and/or modify it
    11.1 --- a/test/tools/javac/diags/CheckResourceKeys.java	Thu Mar 22 12:41:36 2012 -0700
    11.2 +++ b/test/tools/javac/diags/CheckResourceKeys.java	Mon Mar 26 17:32:17 2012 -0700
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
    11.6 + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
    11.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.8   *
    11.9   * This code is free software; you can redistribute it and/or modify it
   11.10 @@ -259,6 +259,7 @@
   11.11              "application.home", // in Paths.java
   11.12              "env.class.path",
   11.13              "line.separator",
   11.14 +            "os.name",
   11.15              "user.dir",
   11.16              // file names
   11.17              "ct.sym",
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/tools/javac/nativeHeaders/NativeHeaderTest.java	Mon Mar 26 17:32:17 2012 -0700
    12.3 @@ -0,0 +1,274 @@
    12.4 +/*
    12.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.
   12.11 + *
   12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.15 + * version 2 for more details (a copy is included in the LICENSE file that
   12.16 + * accompanied this code).
   12.17 + *
   12.18 + * You should have received a copy of the GNU General Public License version
   12.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.21 + *
   12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   12.23 + * or visit www.oracle.com if you need additional information or have any
   12.24 + * questions.
   12.25 + */
   12.26 +
   12.27 +/*
   12.28 + * @test
   12.29 + * @bug 7150368
   12.30 + * @summary javac should include basic ability to generate native headers
   12.31 + */
   12.32 +
   12.33 +import java.io.File;
   12.34 +import java.io.FileWriter;
   12.35 +import java.io.IOException;
   12.36 +import java.lang.annotation.Annotation;
   12.37 +import java.lang.annotation.Retention;
   12.38 +import java.lang.annotation.RetentionPolicy;
   12.39 +import java.lang.reflect.InvocationTargetException;
   12.40 +import java.lang.reflect.Method;
   12.41 +import java.util.ArrayList;
   12.42 +import java.util.Arrays;
   12.43 +import java.util.HashSet;
   12.44 +import java.util.List;
   12.45 +import java.util.Set;
   12.46 +
   12.47 +import javax.tools.StandardJavaFileManager;
   12.48 +import javax.tools.StandardLocation;
   12.49 +
   12.50 +import com.sun.source.util.JavacTask;
   12.51 +import com.sun.tools.javac.api.JavacTool;
   12.52 +
   12.53 +public class NativeHeaderTest {
   12.54 +    public static void main(String... args) throws Exception {
   12.55 +        new NativeHeaderTest().run();
   12.56 +    }
   12.57 +
   12.58 +    /** How to invoke javac. */
   12.59 +    enum RunKind {
   12.60 +        /** Use the command line entry point. */
   12.61 +        CMD,
   12.62 +        /** Use the JavaCompiler API. */
   12.63 +        API
   12.64 +    };
   12.65 +
   12.66 +    /** Which classes for which to generate headers. */
   12.67 +    enum GenKind {
   12.68 +        /** Just classes with native methods or the marker annotation. */
   12.69 +        SIMPLE,
   12.70 +        /** All appropriate classes within the top level class. */
   12.71 +        FULL
   12.72 +    };
   12.73 +
   12.74 +    // ---------- Test cases, invoked reflectively via run. ----------
   12.75 +
   12.76 +    @Test
   12.77 +    void simpleTest(RunKind rk, GenKind gk) throws Exception {
   12.78 +        List<File> files = new ArrayList<File>();
   12.79 +        files.add(createFile("p/C.java",
   12.80 +                "class C { native void m(); }"));
   12.81 +
   12.82 +        Set<String> expect = createSet("C.h");
   12.83 +
   12.84 +        test(rk, gk, files, expect);
   12.85 +    }
   12.86 +
   12.87 +    @Test
   12.88 +    void nestedClassTest(RunKind rk, GenKind gk) throws Exception {
   12.89 +        List<File> files = new ArrayList<File>();
   12.90 +        files.add(createFile("p/C.java",
   12.91 +                "class C { static class Inner { native void m(); } }"));
   12.92 +
   12.93 +        Set<String> expect = createSet("C_Inner.h");
   12.94 +        if (gk == GenKind.FULL) expect.add("C.h");
   12.95 +
   12.96 +        test(rk, gk, files, expect);
   12.97 +    }
   12.98 +
   12.99 +    @Test
  12.100 +    void localClassTest(RunKind rk, GenKind gk) throws Exception {
  12.101 +        List<File> files = new ArrayList<File>();
  12.102 +        files.add(createFile("p/C.java",
  12.103 +                "class C { native void m(); void m2() { class Local { } } }"));
  12.104 +
  12.105 +        Set<String> expect = createSet("C.h");
  12.106 +
  12.107 +        test(rk, gk, files, expect);
  12.108 +    }
  12.109 +
  12.110 +    @Test
  12.111 +    void syntheticClassTest(RunKind rk, GenKind gk) throws Exception {
  12.112 +        List<File> files = new ArrayList<File>();
  12.113 +        files.add(createFile("p/C.java",
  12.114 +                "class C {\n"
  12.115 +                + "    private C() { }\n"
  12.116 +                + "    class Inner extends C { native void m(); }\n"
  12.117 +                + "}"));
  12.118 +
  12.119 +        Set<String> expect = createSet("C_Inner.h");
  12.120 +        if (gk == GenKind.FULL) expect.add("C.h");
  12.121 +
  12.122 +        test(rk, gk, files, expect);
  12.123 +
  12.124 +        // double check the synthetic class was generated
  12.125 +        checkEqual("generatedClasses",
  12.126 +                createSet("C.class", "C$1.class", "C$Inner.class"),
  12.127 +                createSet(classesDir.list()));
  12.128 +    }
  12.129 +
  12.130 +    @Test
  12.131 +    void annoTest(RunKind rk, GenKind gk) throws Exception {
  12.132 +        List<File> files = new ArrayList<File>();
  12.133 +        files.add(createFile("p/C.java",
  12.134 +                "@javax.tools.annotation.GenerateNativeHeader class C { }"));
  12.135 +
  12.136 +        Set<String> expect = createSet("C.h");
  12.137 +
  12.138 +        test(rk, gk, files, expect);
  12.139 +    }
  12.140 +
  12.141 +    @Test
  12.142 +    void annoNestedClassTest(RunKind rk, GenKind gk) throws Exception {
  12.143 +        List<File> files = new ArrayList<File>();
  12.144 +        files.add(createFile("p/C.java",
  12.145 +                "class C { @javax.tools.annotation.GenerateNativeHeader class Inner { } }"));
  12.146 +
  12.147 +        Set<String> expect = createSet("C_Inner.h");
  12.148 +        if (gk == GenKind.FULL) expect.add("C.h");
  12.149 +
  12.150 +        test(rk, gk, files, expect);
  12.151 +    }
  12.152 +
  12.153 +    /**
  12.154 +     * The worker method for each test case.
  12.155 +     * Compile the files and verify that exactly the expected set of header files
  12.156 +     * is generated.
  12.157 +     */
  12.158 +    void test(RunKind rk, GenKind gk, List<File> files, Set<String> expect) throws Exception {
  12.159 +        List<String> args = new ArrayList<String>();
  12.160 +        if (gk == GenKind.FULL)
  12.161 +            args.add("-XDjavah:full");
  12.162 +
  12.163 +        switch (rk) {
  12.164 +            case CMD:
  12.165 +                args.add("-d");
  12.166 +                args.add(classesDir.getPath());
  12.167 +                args.add("-h");
  12.168 +                args.add(headersDir.getPath());
  12.169 +                for (File f: files)
  12.170 +                    args.add(f.getPath());
  12.171 +                int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]));
  12.172 +                if (rc != 0)
  12.173 +                    throw new Exception("compilation failed, rc=" + rc);
  12.174 +                break;
  12.175 +
  12.176 +            case API:
  12.177 +                fm.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir));
  12.178 +                fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(classesDir));
  12.179 +                fm.setLocation(StandardLocation.NATIVE_HEADER_OUTPUT, Arrays.asList(headersDir));
  12.180 +                JavacTask task = javac.getTask(null, fm, null, args, null,
  12.181 +                        fm.getJavaFileObjectsFromFiles(files));
  12.182 +                if (!task.call())
  12.183 +                    throw new Exception("compilation failed");
  12.184 +                break;
  12.185 +        }
  12.186 +
  12.187 +        Set<String> found = createSet(headersDir.list());
  12.188 +        checkEqual("header files", expect, found);
  12.189 +    }
  12.190 +
  12.191 +    /** Marker annotation for test cases. */
  12.192 +    @Retention(RetentionPolicy.RUNTIME)
  12.193 +    @interface Test { }
  12.194 +
  12.195 +    /** Combo test to run all test cases in all modes. */
  12.196 +    void run() throws Exception {
  12.197 +        javac = JavacTool.create();
  12.198 +        fm = javac.getStandardFileManager(null, null, null);
  12.199 +
  12.200 +        for (RunKind rk: RunKind.values()) {
  12.201 +            for (GenKind gk: GenKind.values()) {
  12.202 +                for (Method m: getClass().getDeclaredMethods()) {
  12.203 +                    Annotation a = m.getAnnotation(Test.class);
  12.204 +                    if (a != null) {
  12.205 +                        init(rk, gk, m.getName());
  12.206 +                        try {
  12.207 +                            m.invoke(this, new Object[] { rk, gk });
  12.208 +                        } catch (InvocationTargetException e) {
  12.209 +                            Throwable cause = e.getCause();
  12.210 +                            throw (cause instanceof Exception) ? ((Exception) cause) : e;
  12.211 +                        }
  12.212 +                        System.err.println();
  12.213 +                    }
  12.214 +                }
  12.215 +            }
  12.216 +        }
  12.217 +        System.err.println(testCount + " tests" + ((errorCount == 0) ? "" : ", " + errorCount + " errors"));
  12.218 +        if (errorCount > 0)
  12.219 +            throw new Exception(errorCount + " errors found");
  12.220 +    }
  12.221 +
  12.222 +    /**
  12.223 +     * Init directories for a test case.
  12.224 +     */
  12.225 +    void init(RunKind rk, GenKind gk, String name) throws IOException {
  12.226 +        System.err.println("Test " + rk + " " + gk + " " + name);
  12.227 +        testCount++;
  12.228 +
  12.229 +        testDir = new File(rk.toString().toLowerCase() + "_" + gk.toString().toLowerCase() + "-" + name);
  12.230 +        srcDir = new File(testDir, "src");
  12.231 +        srcDir.mkdirs();
  12.232 +        classesDir = new File(testDir, "classes");
  12.233 +        classesDir.mkdirs();
  12.234 +        headersDir = new File(testDir, "headers");
  12.235 +        headersDir.mkdirs();
  12.236 +    }
  12.237 +
  12.238 +    /** Create a source file with given body text. */
  12.239 +    File createFile(String path, final String body) throws IOException {
  12.240 +        File f = new File(srcDir, path);
  12.241 +        f.getParentFile().mkdirs();
  12.242 +        try (FileWriter out = new FileWriter(f)) {
  12.243 +            out.write(body);
  12.244 +        }
  12.245 +        return f;
  12.246 +    }
  12.247 +
  12.248 +    /** Convenience method to create a set of items. */
  12.249 +    <T> Set<T> createSet(T... items) {
  12.250 +        return new HashSet<T>(Arrays.asList(items));
  12.251 +    }
  12.252 +
  12.253 +    /** Convenience method to check two values are equal, and report an error if not. */
  12.254 +    <T> void checkEqual(String label, T expect, T found) {
  12.255 +        if ((found == null) ? (expect == null) : found.equals(expect))
  12.256 +            return;
  12.257 +        System.err.println("Error: mismatch");
  12.258 +        System.err.println("  expected: " + expect);
  12.259 +        System.err.println("     found: " + found);
  12.260 +        errorCount++;
  12.261 +    }
  12.262 +
  12.263 +    // Shared across API test cases
  12.264 +    JavacTool javac;
  12.265 +    StandardJavaFileManager fm;
  12.266 +
  12.267 +    // Directories set up by init
  12.268 +    File testDir;
  12.269 +    File srcDir;
  12.270 +    File classesDir;
  12.271 +    File headersDir;
  12.272 +
  12.273 +    // Statistics
  12.274 +    int testCount;
  12.275 +    int errorCount;
  12.276 +}
  12.277 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java	Mon Mar 26 17:32:17 2012 -0700
    13.3 @@ -0,0 +1,169 @@
    13.4 +/*
    13.5 + * Copyright (c) 2007,2012 Oracle and/or its affiliates. All rights reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.
   13.11 + *
   13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.15 + * version 2 for more details (a copy is included in the LICENSE file that
   13.16 + * accompanied this code).
   13.17 + *
   13.18 + * You should have received a copy of the GNU General Public License version
   13.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.21 + *
   13.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.23 + * or visit www.oracle.com if you need additional information or have any
   13.24 + * questions.
   13.25 + */
   13.26 +
   13.27 +/*
   13.28 + * @test
   13.29 + * @bug 7150368
   13.30 + * @summary javac should include basic ability to generate native headers
   13.31 + */
   13.32 +
   13.33 +import java.io.File;
   13.34 +import java.io.IOException;
   13.35 +import java.io.PrintWriter;
   13.36 +import java.nio.file.Files;
   13.37 +import java.util.ArrayList;
   13.38 +import java.util.Arrays;
   13.39 +import java.util.HashSet;
   13.40 +import java.util.List;
   13.41 +import java.util.Set;
   13.42 +
   13.43 +public class CompareTest {
   13.44 +    public static void main(String... args) throws Exception {
   13.45 +        new CompareTest().run();
   13.46 +    }
   13.47 +
   13.48 +    void run() throws Exception {
   13.49 +        File srcDir = new File(System.getProperty("test.src"));
   13.50 +        File classesDir = new File("classes");
   13.51 +        classesDir.mkdirs();
   13.52 +        File javacHeaders = new File("headers.javac");
   13.53 +        javacHeaders.mkdirs();
   13.54 +        File javahHeaders = new File("headers.javah");
   13.55 +        javahHeaders.mkdirs();
   13.56 +
   13.57 +        List<String> javacArgs = new ArrayList<String>();
   13.58 +        javacArgs.add("-d");
   13.59 +        javacArgs.add(classesDir.getPath());
   13.60 +        javacArgs.add("-h");
   13.61 +        javacArgs.add(javacHeaders.getPath());
   13.62 +        javacArgs.add("-XDjavah:full");
   13.63 +
   13.64 +        for (File f: srcDir.listFiles()) {
   13.65 +            if (f.getName().matches("TestClass[0-9]+\\.java")) {
   13.66 +                sourceFileCount++;
   13.67 +                javacArgs.add(f.getPath());
   13.68 +            }
   13.69 +        }
   13.70 +
   13.71 +        int rc = com.sun.tools.javac.Main.compile(javacArgs.toArray(new String[javacArgs.size()]));
   13.72 +        if (rc != 0)
   13.73 +            throw new Exception("javac failed; rc=" + rc);
   13.74 +
   13.75 +        List<String> javahArgs = new ArrayList<String>();
   13.76 +        javahArgs.add("-d");
   13.77 +        javahArgs.add(javahHeaders.getPath());
   13.78 +
   13.79 +        for (File f: classesDir.listFiles()) {
   13.80 +            if (f.getName().endsWith(".class")) {
   13.81 +                javahArgs.add(inferBinaryName(f));
   13.82 +            }
   13.83 +        }
   13.84 +
   13.85 +        PrintWriter pw = new PrintWriter(System.out, true);
   13.86 +        rc = com.sun.tools.javah.Main.run(javahArgs.toArray(new String[javahArgs.size()]), pw);
   13.87 +        if (rc != 0)
   13.88 +            throw new Exception("javah failed; rc=" + rc);
   13.89 +
   13.90 +        compare(javahHeaders, javacHeaders);
   13.91 +
   13.92 +        int javahHeaderCount = javahHeaders.list().length;
   13.93 +        int javacHeaderCount = javacHeaders.list().length;
   13.94 +
   13.95 +        System.out.println(sourceFileCount + " .java files found");
   13.96 +        System.out.println(javacHeaderCount + " .h files generated by javac");
   13.97 +        System.out.println(javahHeaderCount + " .h files generated by javah");
   13.98 +        System.out.println(compareCount + " header files compared");
   13.99 +
  13.100 +        if (javacHeaderCount != javahHeaderCount || javacHeaderCount != compareCount)
  13.101 +            error("inconsistent counts");
  13.102 +
  13.103 +        if (errors > 0)
  13.104 +            throw new Exception(errors + " errors occurred");
  13.105 +    }
  13.106 +
  13.107 +    String inferBinaryName(File file) {
  13.108 +        String name = file.getName();
  13.109 +        return name.substring(0, name.length() - ".class".length()).replace("$", ".");
  13.110 +    }
  13.111 +
  13.112 +    /** Compare two directories.
  13.113 +     *  @param f1 The golden directory
  13.114 +     *  @param f2 The directory to be compared
  13.115 +     */
  13.116 +    void compare(File f1, File f2) {
  13.117 +        compare(f1, f2, null);
  13.118 +    }
  13.119 +
  13.120 +    /** Compare two files or directories
  13.121 +     *  @param f1 The golden directory
  13.122 +     *  @param f2 The directory to be compared
  13.123 +     *  @param p An optional path identifying a file within the two directories
  13.124 +     */
  13.125 +    void compare(File f1, File f2, String p) {
  13.126 +        File f1p = (p == null ? f1 : new File(f1, p));
  13.127 +        File f2p = (p == null ? f2 : new File(f2, p));
  13.128 +        if (f1p.isDirectory() && f2p.isDirectory()) {
  13.129 +            Set<String> children = new HashSet<String>();
  13.130 +            children.addAll(Arrays.asList(f1p.list()));
  13.131 +            children.addAll(Arrays.asList(f2p.list()));
  13.132 +            for (String c: children) {
  13.133 +                compare(f1, f2, new File(p, c).getPath()); // null-safe for p
  13.134 +            }
  13.135 +        }
  13.136 +        else if (f1p.isFile() && f2p.isFile()) {
  13.137 +            System.out.println("checking " + p);
  13.138 +            compareCount++;
  13.139 +            String s1 = read(f1p);
  13.140 +            String s2 = read(f2p);
  13.141 +            if (!s1.equals(s2)) {
  13.142 +                System.out.println("File: " + f1p + "\n" + s1);
  13.143 +                System.out.println("File: " + f2p + "\n" + s2);
  13.144 +                error("Files differ: " + f1p + " " + f2p);
  13.145 +            }
  13.146 +        }
  13.147 +        else if (f1p.exists() && !f2p.exists())
  13.148 +            error("Only in " + f1 + ": " + p);
  13.149 +        else if (f2p.exists() && !f1p.exists())
  13.150 +            error("Only in " + f2 + ": " + p);
  13.151 +        else
  13.152 +            error("Files differ: " + f1p + " " + f2p);
  13.153 +    }
  13.154 +
  13.155 +    private String read(File f) {
  13.156 +        try {
  13.157 +            return new String(Files.readAllBytes(f.toPath()));
  13.158 +        } catch (IOException e) {
  13.159 +            error("error reading " + f + ": " + e);
  13.160 +            return "";
  13.161 +        }
  13.162 +    }
  13.163 +
  13.164 +    private void error(String msg) {
  13.165 +        System.out.println(msg);
  13.166 +        errors++;
  13.167 +    }
  13.168 +
  13.169 +    private int errors;
  13.170 +    private int compareCount;
  13.171 +    private int sourceFileCount;
  13.172 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java	Mon Mar 26 17:32:17 2012 -0700
    14.3 @@ -0,0 +1,475 @@
    14.4 +/*
    14.5 + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.
   14.11 + *
   14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.15 + * version 2 for more details (a copy is included in the LICENSE file that
   14.16 + * accompanied this code).
   14.17 + *
   14.18 + * You should have received a copy of the GNU General Public License version
   14.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.21 + *
   14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.23 + * or visit www.oracle.com if you need additional information or have any
   14.24 + * questions.
   14.25 + */
   14.26 +
   14.27 +import java.util.List;
   14.28 +
   14.29 +public class TestClass1 {
   14.30 +    // simple types
   14.31 +    byte b;
   14.32 +    short s;
   14.33 +    int i;
   14.34 +    long l;
   14.35 +    float f;
   14.36 +    double d;
   14.37 +    Object o;
   14.38 +    String t;
   14.39 +    List<String> g;
   14.40 +
   14.41 +    // constants
   14.42 +    static final byte bc = 0;
   14.43 +    static final short sc = 0;
   14.44 +    static final int ic = 0;
   14.45 +    static final long lc = 0;
   14.46 +    static final float fc = 0;
   14.47 +    static final double dc = 0;
   14.48 +    static final Object oc = null;
   14.49 +    static final String tc = "";
   14.50 +    static final List<String> gc = null;
   14.51 +
   14.52 +    // simple arrays
   14.53 +    byte[] ba;
   14.54 +    short[] sa; // not handled corrected by javah v6
   14.55 +    int[] ia;
   14.56 +    long[] la;
   14.57 +    float[] fa;
   14.58 +    double[] da;
   14.59 +    Object[] oa;
   14.60 +    String[] ta;
   14.61 +    List<String>[] ga;
   14.62 +
   14.63 +    // multidimensional arrays
   14.64 +    byte[][] baa;
   14.65 +    short[][] saa;
   14.66 +    int[][] iaa;
   14.67 +    long[][] laa;
   14.68 +    float[][] faa;
   14.69 +    double[][] daa;
   14.70 +    Object[][] oaa;
   14.71 +    String[][] taa;
   14.72 +    List<String>[] gaa;
   14.73 +
   14.74 +    // simple Java methods
   14.75 +    byte bm() { return 0; }
   14.76 +    short sm() { return 0; }
   14.77 +    int im() { return 0; }
   14.78 +    long lm() { return 0; }
   14.79 +    float fm() { return 0; }
   14.80 +    double dm() { return 0; }
   14.81 +    Object om() { return null; }
   14.82 +    String tm() { return ""; }
   14.83 +    List<String> gm() { return null; }
   14.84 +    void vm() { }
   14.85 +    byte[] bam() { return null; }
   14.86 +    short[] sam() { return null; }
   14.87 +    int[] iam() { return null; }
   14.88 +    long[] lam() { return null; }
   14.89 +    float[] fam() { return null; }
   14.90 +    double[] dam() { return null; }
   14.91 +    Object[] oam() { return null; }
   14.92 +    String[] tam() { return null; }
   14.93 +    List<String>[] gam() { return null; }
   14.94 +    byte[][] baam() { return null; }
   14.95 +    short[][] saam() { return null; }
   14.96 +    int[][] iaam() { return null; }
   14.97 +    long[][] laam() { return null; }
   14.98 +    float[][] faam() { return null; }
   14.99 +    double[][] daam() { return null; }
  14.100 +    Object[][] oaam() { return null; }
  14.101 +    String[][] taam() { return null; }
  14.102 +    List<String>[] gaam() { return null; }
  14.103 +
  14.104 +    // simple native methods
  14.105 +    native byte bmn();
  14.106 +    native short smn();
  14.107 +    native int imn();
  14.108 +    native long lmn();
  14.109 +    native float fmn();
  14.110 +    native double dmn();
  14.111 +    native Object omn();
  14.112 +    native String tmn();
  14.113 +    native List<String> gmn();
  14.114 +    native void vmn();
  14.115 +    native byte[] bamn();
  14.116 +    native short[] samn();
  14.117 +    native int[] iamn();
  14.118 +    native long[] lamn();
  14.119 +    native float[] famn();
  14.120 +    native double[] damn();
  14.121 +    native Object[] oamn();
  14.122 +    native String[] tamn();
  14.123 +    native List<String>[] gamn();
  14.124 +    native byte[][] baamn();
  14.125 +    native short[][] saamn();
  14.126 +    native int[][] iaamn();
  14.127 +    native long[][] laamn();
  14.128 +    native float[][] faamn();
  14.129 +    native double[][] daamn();
  14.130 +    native Object[][] oaamn();
  14.131 +    native String[][] taamn();
  14.132 +    native List<String>[] gaamn();
  14.133 +
  14.134 +    // overloaded Java methods
  14.135 +    byte bm1() { return 0; }
  14.136 +    short sm1() { return 0; }
  14.137 +    int im1() { return 0; }
  14.138 +    long lm1() { return 0; }
  14.139 +    float fm1() { return 0; }
  14.140 +    double dm1() { return 0; }
  14.141 +    Object om1() { return null; }
  14.142 +    String tm1() { return ""; }
  14.143 +    List<String> gm1() { return null; }
  14.144 +    void vm1() { }
  14.145 +
  14.146 +    byte bm2(int i) { return 0; }
  14.147 +    short sm2(int i) { return 0; }
  14.148 +    int im2(int i) { return 0; }
  14.149 +    long lm2(int i) { return 0; }
  14.150 +    float fm2(int i) { return 0; }
  14.151 +    double dm2(int i) { return 0; }
  14.152 +    Object om2(int i) { return null; }
  14.153 +    String tm2(int i) { return ""; }
  14.154 +    List<String> gm2(int i) { return null; }
  14.155 +    void vm2(int i) { }
  14.156 +
  14.157 +    // overloaded native methods
  14.158 +    native byte bmn1();
  14.159 +    native short smn1();
  14.160 +    native int imn1();
  14.161 +    native long lmn1();
  14.162 +    native float fmn1();
  14.163 +    native double dmn1();
  14.164 +    native Object omn1();
  14.165 +    native String tmn1();
  14.166 +    native List<String> gmn1();
  14.167 +    native void vmn1();
  14.168 +
  14.169 +    native byte bmn2(int i);
  14.170 +    native short smn2(int i);
  14.171 +    native int imn2(int i);
  14.172 +    native long lmn2(int i);
  14.173 +    native float fmn2(int i);
  14.174 +    native double dmn2(int i);
  14.175 +    native Object omn2(int i);
  14.176 +    native String tmn2(int i);
  14.177 +    native List<String> gmn2(int i);
  14.178 +    native void vmn2(int i);
  14.179 +
  14.180 +    // arg types for Java methods
  14.181 +    void mb(byte b) { }
  14.182 +    void ms(short s) { }
  14.183 +    void mi(int i) { }
  14.184 +    void ml(long l) { }
  14.185 +    void mf(float f) { }
  14.186 +    void md(double d) { }
  14.187 +    void mo(Object o) { }
  14.188 +    void mt(String t) { }
  14.189 +    void mg(List<String> g) { }
  14.190 +
  14.191 +    // arg types for native methods
  14.192 +    native void mbn(byte b);
  14.193 +    native void msn(short s);
  14.194 +    native void min(int i);
  14.195 +    native void mln(long l);
  14.196 +    native void mfn(float f);
  14.197 +    native void mdn(double d);
  14.198 +    native void mon(Object o);
  14.199 +    native void mtn(String t);
  14.200 +    native void mgn(List<String> g);
  14.201 +
  14.202 +    static class Inner1 {
  14.203 +        // simple types
  14.204 +        byte b;
  14.205 +        short s;
  14.206 +        int i;
  14.207 +        long l;
  14.208 +        float f;
  14.209 +        double d;
  14.210 +        Object o;
  14.211 +        String t;
  14.212 +        List<String> g;
  14.213 +
  14.214 +        // constants
  14.215 +        static final byte bc = 0;
  14.216 +        static final short sc = 0;
  14.217 +        static final int ic = 0;
  14.218 +        static final long lc = 0;
  14.219 +        static final float fc = 0;
  14.220 +        static final double dc = 0;
  14.221 +        static final Object oc = null;
  14.222 +        static final String tc = "";
  14.223 +        static final List<String> gc = null;
  14.224 +
  14.225 +        // simple arrays
  14.226 +        byte[] ba;
  14.227 +        // short[] sa; // not handled corrected by javah v6
  14.228 +        int[] ia;
  14.229 +        long[] la;
  14.230 +        float[] fa;
  14.231 +        double[] da;
  14.232 +        Object[] oa;
  14.233 +        String[] ta;
  14.234 +        List<String>[] ga;
  14.235 +
  14.236 +        // multidimensional arrays
  14.237 +        byte[][] baa;
  14.238 +        short[][] saa;
  14.239 +        int[][] iaa;
  14.240 +        long[][] laa;
  14.241 +        float[][] faa;
  14.242 +        double[][] daa;
  14.243 +        Object[][] oaa;
  14.244 +        String[][] taa;
  14.245 +        List<String>[] gaa;
  14.246 +
  14.247 +        // simple Java methods
  14.248 +        byte bm() { return 0; }
  14.249 +        short sm() { return 0; }
  14.250 +        int im() { return 0; }
  14.251 +        long lm() { return 0; }
  14.252 +        float fm() { return 0; }
  14.253 +        double dm() { return 0; }
  14.254 +        Object om() { return null; }
  14.255 +        String tm() { return ""; }
  14.256 +        List<String> gm() { return null; }
  14.257 +        void vm() { }
  14.258 +
  14.259 +        // simple native methods
  14.260 +        native byte bmn();
  14.261 +        native short smn();
  14.262 +        native int imn();
  14.263 +        native long lmn();
  14.264 +        native float fmn();
  14.265 +        native double dmn();
  14.266 +        native Object omn();
  14.267 +        native String tmn();
  14.268 +        native List<String> gmn();
  14.269 +        native void vmn();
  14.270 +
  14.271 +        // overloaded Java methods
  14.272 +        byte bm1() { return 0; }
  14.273 +        short sm1() { return 0; }
  14.274 +        int im1() { return 0; }
  14.275 +        long lm1() { return 0; }
  14.276 +        float fm1() { return 0; }
  14.277 +        double dm1() { return 0; }
  14.278 +        Object om1() { return null; }
  14.279 +        String tm1() { return ""; }
  14.280 +        List<String> gm1() { return null; }
  14.281 +        void vm1() { }
  14.282 +
  14.283 +        byte bm2(int i) { return 0; }
  14.284 +        short sm2(int i) { return 0; }
  14.285 +        int im2(int i) { return 0; }
  14.286 +        long lm2(int i) { return 0; }
  14.287 +        float fm2(int i) { return 0; }
  14.288 +        double dm2(int i) { return 0; }
  14.289 +        Object om2(int i) { return null; }
  14.290 +        String tm2(int i) { return ""; }
  14.291 +        List<String> gm2(int i) { return null; }
  14.292 +        void vm2(int i) { }
  14.293 +
  14.294 +        // overloaded native methods
  14.295 +        native byte bmn1();
  14.296 +        native short smn1();
  14.297 +        native int imn1();
  14.298 +        native long lmn1();
  14.299 +        native float fmn1();
  14.300 +        native double dmn1();
  14.301 +        native Object omn1();
  14.302 +        native String tmn1();
  14.303 +        native List<String> gmn1();
  14.304 +        native void vmn1();
  14.305 +
  14.306 +        native byte bmn2(int i);
  14.307 +        native short smn2(int i);
  14.308 +        native int imn2(int i);
  14.309 +        native long lmn2(int i);
  14.310 +        native float fmn2(int i);
  14.311 +        native double dmn2(int i);
  14.312 +        native Object omn2(int i);
  14.313 +        native String tmn2(int i);
  14.314 +        native List<String> gmn2(int i);
  14.315 +        native void vmn2(int i);
  14.316 +
  14.317 +        // arg types for Java methods
  14.318 +        void mb(byte b) { }
  14.319 +        void ms(short s) { }
  14.320 +        void mi(int i) { }
  14.321 +        void ml(long l) { }
  14.322 +        void mf(float f) { }
  14.323 +        void md(double d) { }
  14.324 +        void mo(Object o) { }
  14.325 +        void mt(String t) { }
  14.326 +        void mg(List<String> g) { }
  14.327 +
  14.328 +        // arg types for native methods
  14.329 +        native void mbn(byte b);
  14.330 +        native void msn(short s);
  14.331 +        native void min(int i);
  14.332 +        native void mln(long l);
  14.333 +        native void mfn(float f);
  14.334 +        native void mdn(double d);
  14.335 +        native void mon(Object o);
  14.336 +        native void mtn(String t);
  14.337 +        native void mgn(List<String> g);
  14.338 +    }
  14.339 +
  14.340 +    class Inner2 {
  14.341 +        // simple types
  14.342 +        byte b;
  14.343 +        short s;
  14.344 +        int i;
  14.345 +        long l;
  14.346 +        float f;
  14.347 +        double d;
  14.348 +        Object o;
  14.349 +        String t;
  14.350 +        List<String> g;
  14.351 +
  14.352 +        // constants
  14.353 +        static final byte bc = 0;
  14.354 +        static final short sc = 0;
  14.355 +        static final int ic = 0;
  14.356 +        static final long lc = 0;
  14.357 +        static final float fc = 0;
  14.358 +        static final double dc = 0;
  14.359 +        //static final Object oc = null;
  14.360 +        static final String tc = "";
  14.361 +        //static final List<String> gc = null;
  14.362 +
  14.363 +        // simple arrays
  14.364 +        byte[] ba;
  14.365 +        // short[] sa; // not handled corrected by javah v6
  14.366 +        int[] ia;
  14.367 +        long[] la;
  14.368 +        float[] fa;
  14.369 +        double[] da;
  14.370 +        Object[] oa;
  14.371 +        String[] ta;
  14.372 +        List<String>[] ga;
  14.373 +
  14.374 +        // multidimensional arrays
  14.375 +        byte[][] baa;
  14.376 +        short[][] saa;
  14.377 +        int[][] iaa;
  14.378 +        long[][] laa;
  14.379 +        float[][] faa;
  14.380 +        double[][] daa;
  14.381 +        Object[][] oaa;
  14.382 +        String[][] taa;
  14.383 +        List<String>[] gaa;
  14.384 +
  14.385 +        // simple Java methods
  14.386 +        byte bm() { return 0; }
  14.387 +        short sm() { return 0; }
  14.388 +        int im() { return 0; }
  14.389 +        long lm() { return 0; }
  14.390 +        float fm() { return 0; }
  14.391 +        double dm() { return 0; }
  14.392 +        Object om() { return null; }
  14.393 +        String tm() { return ""; }
  14.394 +        List<String> gm() { return null; }
  14.395 +        void vm() { }
  14.396 +
  14.397 +        // simple native methods
  14.398 +        native byte bmn();
  14.399 +        native short smn();
  14.400 +        native int imn();
  14.401 +        native long lmn();
  14.402 +        native float fmn();
  14.403 +        native double dmn();
  14.404 +        native Object omn();
  14.405 +        native String tmn();
  14.406 +        native List<String> gmn();
  14.407 +        native void vmn();
  14.408 +
  14.409 +        // overloaded Java methods
  14.410 +        byte bm1() { return 0; }
  14.411 +        short sm1() { return 0; }
  14.412 +        int im1() { return 0; }
  14.413 +        long lm1() { return 0; }
  14.414 +        float fm1() { return 0; }
  14.415 +        double dm1() { return 0; }
  14.416 +        Object om1() { return null; }
  14.417 +        String tm1() { return ""; }
  14.418 +        List<String> gm1() { return null; }
  14.419 +        void vm1() { }
  14.420 +
  14.421 +        byte bm2(int i) { return 0; }
  14.422 +        short sm2(int i) { return 0; }
  14.423 +        int im2(int i) { return 0; }
  14.424 +        long lm2(int i) { return 0; }
  14.425 +        float fm2(int i) { return 0; }
  14.426 +        double dm2(int i) { return 0; }
  14.427 +        Object om2(int i) { return null; }
  14.428 +        String tm2(int i) { return ""; }
  14.429 +        List<String> gm2(int i) { return null; }
  14.430 +        void vm2(int i) { }
  14.431 +
  14.432 +        // overloaded native methods
  14.433 +        native byte bmn1();
  14.434 +        native short smn1();
  14.435 +        native int imn1();
  14.436 +        native long lmn1();
  14.437 +        native float fmn1();
  14.438 +        native double dmn1();
  14.439 +        native Object omn1();
  14.440 +        native String tmn1();
  14.441 +        native List<String> gmn1();
  14.442 +        native void vmn1();
  14.443 +
  14.444 +        native byte bmn2(int i);
  14.445 +        native short smn2(int i);
  14.446 +        native int imn2(int i);
  14.447 +        native long lmn2(int i);
  14.448 +        native float fmn2(int i);
  14.449 +        native double dmn2(int i);
  14.450 +        native Object omn2(int i);
  14.451 +        native String tmn2(int i);
  14.452 +        native List<String> gmn2(int i);
  14.453 +        native void vmn2(int i);
  14.454 +
  14.455 +        // arg types for Java methods
  14.456 +        void mb(byte b) { }
  14.457 +        void ms(short s) { }
  14.458 +        void mi(int i) { }
  14.459 +        void ml(long l) { }
  14.460 +        void mf(float f) { }
  14.461 +        void md(double d) { }
  14.462 +        void mo(Object o) { }
  14.463 +        void mt(String t) { }
  14.464 +        void mg(List<String> g) { }
  14.465 +
  14.466 +        // arg types for native methods
  14.467 +        native void mbn(byte b);
  14.468 +        native void msn(short s);
  14.469 +        native void min(int i);
  14.470 +        native void mln(long l);
  14.471 +        native void mfn(float f);
  14.472 +        native void mdn(double d);
  14.473 +        native void mon(Object o);
  14.474 +        native void mtn(String t);
  14.475 +        native void mgn(List<String> g);
  14.476 +    }
  14.477 +
  14.478 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/tools/javac/nativeHeaders/javahComparison/TestClass2.java	Mon Mar 26 17:32:17 2012 -0700
    15.3 @@ -0,0 +1,36 @@
    15.4 +/*
    15.5 + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
    15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.7 + *
    15.8 + * This code is free software; you can redistribute it and/or modify it
    15.9 + * under the terms of the GNU General Public License version 2 only, as
   15.10 + * published by the Free Software Foundation.
   15.11 + *
   15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   15.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15.15 + * version 2 for more details (a copy is included in the LICENSE file that
   15.16 + * accompanied this code).
   15.17 + *
   15.18 + * You should have received a copy of the GNU General Public License version
   15.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   15.21 + *
   15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   15.23 + * or visit www.oracle.com if you need additional information or have any
   15.24 + * questions.
   15.25 + */
   15.26 +
   15.27 +import javax.tools.annotation.GenerateNativeHeader;
   15.28 +
   15.29 +@GenerateNativeHeader
   15.30 +public class TestClass2 {
   15.31 +    byte b;
   15.32 +    short s;
   15.33 +    int i;
   15.34 +    long l;
   15.35 +    float f;
   15.36 +    double d;
   15.37 +    Object o;
   15.38 +    String t;
   15.39 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/tools/javac/nativeHeaders/javahComparison/TestClass3.java	Mon Mar 26 17:32:17 2012 -0700
    16.3 @@ -0,0 +1,54 @@
    16.4 +/*
    16.5 + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.
   16.11 + *
   16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.15 + * version 2 for more details (a copy is included in the LICENSE file that
   16.16 + * accompanied this code).
   16.17 + *
   16.18 + * You should have received a copy of the GNU General Public License version
   16.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.21 + *
   16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.23 + * or visit www.oracle.com if you need additional information or have any
   16.24 + * questions.
   16.25 + */
   16.26 +
   16.27 +import javax.tools.annotation.GenerateNativeHeader;
   16.28 +
   16.29 +@GenerateNativeHeader
   16.30 +public class TestClass3 {
   16.31 +    public int tc3;
   16.32 +
   16.33 +    public class Inner1 {
   16.34 +        public int tc3i1;
   16.35 +
   16.36 +        public class Inner1A {
   16.37 +            public int tc3i1i1a;
   16.38 +        }
   16.39 +
   16.40 +        public class Inner1B {
   16.41 +            public int tc3i1i1b;
   16.42 +        }
   16.43 +    }
   16.44 +
   16.45 +    public class Inner2 {
   16.46 +        public int tc321;
   16.47 +
   16.48 +        public class Inner2A {
   16.49 +            public int tc3i2i2a;
   16.50 +        }
   16.51 +
   16.52 +        public class Inner2B {
   16.53 +            public int tc3i2i2b;
   16.54 +        }
   16.55 +    }
   16.56 +}
   16.57 +

mercurial