mcimadamore@673: /* jjg@1721: * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. mcimadamore@673: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. mcimadamore@673: * mcimadamore@673: * This code is free software; you can redistribute it and/or modify it mcimadamore@673: * under the terms of the GNU General Public License version 2 only, as mcimadamore@673: * published by the Free Software Foundation. mcimadamore@673: * mcimadamore@673: * This code is distributed in the hope that it will be useful, but WITHOUT mcimadamore@673: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or mcimadamore@673: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mcimadamore@673: * version 2 for more details (a copy is included in the LICENSE file that mcimadamore@673: * accompanied this code). mcimadamore@673: * mcimadamore@673: * You should have received a copy of the GNU General Public License version mcimadamore@673: * 2 along with this work; if not, write to the Free Software Foundation, mcimadamore@673: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. mcimadamore@673: * mcimadamore@673: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA mcimadamore@673: * or visit www.oracle.com if you need additional information or have any mcimadamore@673: * questions. mcimadamore@673: */ mcimadamore@673: mcimadamore@673: /* mcimadamore@673: * @test mcimadamore@730: * @bug 6337171 6996415 jjg@1721: * @ignore 6996758: Investigate better override bridges strategy mcimadamore@673: * @summary javac should create bridge methods when type variable bounds restricted mcimadamore@673: * @run main OverrideBridge mcimadamore@673: */ mcimadamore@673: jjg@1721: // fix, and test, has been disabled as a consequence of 6996415 jjg@1721: mcimadamore@673: import java.io.*; mcimadamore@673: import java.net.URI; mcimadamore@673: import java.util.ArrayList; mcimadamore@673: import java.util.Arrays; mcimadamore@673: import java.util.List; mcimadamore@673: import java.util.Map; mcimadamore@673: import java.util.HashMap; mcimadamore@673: import javax.tools.JavaCompiler; mcimadamore@673: import javax.tools.JavaFileObject; mcimadamore@673: import javax.tools.SimpleJavaFileObject; mcimadamore@673: import javax.tools.ToolProvider; mcimadamore@673: mcimadamore@673: import com.sun.source.util.JavacTask; mcimadamore@673: import com.sun.tools.classfile.ClassFile; mcimadamore@673: import com.sun.tools.classfile.ConstantPoolException; mcimadamore@673: import com.sun.tools.classfile.Descriptor.InvalidDescriptor; mcimadamore@673: import com.sun.tools.classfile.Method; mcimadamore@673: mcimadamore@673: public class OverrideBridge { mcimadamore@673: mcimadamore@673: enum Implementation { mcimadamore@673: IMPLICIT(""), mcimadamore@673: EXPLICIT("@Override public abstract X m(X x);"); mcimadamore@673: mcimadamore@673: String impl; mcimadamore@673: mcimadamore@673: Implementation(String impl) { mcimadamore@673: this.impl = impl; mcimadamore@673: } mcimadamore@673: } mcimadamore@673: mcimadamore@673: static class JavaSource extends SimpleJavaFileObject { mcimadamore@673: mcimadamore@673: final static String sourceStub = mcimadamore@673: "abstract class A {\n" + mcimadamore@673: " public abstract X m(X x);\n" + mcimadamore@673: "}\n" + mcimadamore@673: "interface I {\n" + mcimadamore@673: "X m(X x);\n" + mcimadamore@673: "}\n" + mcimadamore@673: "abstract class B> extends A implements I { #B }\n" + mcimadamore@673: "abstract class C> extends B { #C }\n" + mcimadamore@673: "abstract class D> extends C { #D }\n"; mcimadamore@673: mcimadamore@673: String source; mcimadamore@673: mcimadamore@673: public JavaSource(Implementation implB, Implementation implC, Implementation implD) { mcimadamore@673: super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); mcimadamore@673: source = sourceStub.replace("#B", implB.impl).replace("#C", implC.impl).replace("#D", implD.impl); mcimadamore@673: } mcimadamore@673: mcimadamore@673: @Override mcimadamore@673: public CharSequence getCharContent(boolean ignoreEncodingErrors) { mcimadamore@673: return source; mcimadamore@673: } mcimadamore@673: } mcimadamore@673: mcimadamore@673: public static void main(String... args) throws Exception { mcimadamore@673: Map> refMembers = mcimadamore@673: compile(Implementation.EXPLICIT, Implementation.EXPLICIT, Implementation.EXPLICIT, "ref"); mcimadamore@673: int i = 0; mcimadamore@673: for (Implementation implB : Implementation.values()) { mcimadamore@673: for (Implementation implC : Implementation.values()) { mcimadamore@673: for (Implementation implD : Implementation.values()) { mcimadamore@673: Map> membersToCheck = compile(implB, implC, implD, "out_" + i++); mcimadamore@673: check(refMembers, membersToCheck); mcimadamore@673: } mcimadamore@673: } mcimadamore@673: } mcimadamore@673: } mcimadamore@673: mcimadamore@673: static String workDir = System.getProperty("user.dir"); mcimadamore@673: mcimadamore@673: static Map> compile(Implementation implB, Implementation implC, Implementation implD, String destPath) throws Exception { mcimadamore@673: File destDir = new File(workDir, destPath); destDir.mkdir(); mcimadamore@673: final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); mcimadamore@673: JavaSource source = new JavaSource(implB, implC, implD); mcimadamore@673: JavacTask ct = (JavacTask)tool.getTask(null, null, null, mcimadamore@673: Arrays.asList("-d", destPath), null, Arrays.asList(source)); mcimadamore@673: ct.generate(); mcimadamore@673: Map> members = new HashMap<>(); mcimadamore@673: addMembers(destDir, members); mcimadamore@673: return members; mcimadamore@673: } mcimadamore@673: mcimadamore@673: static void addMembers(File destDir, Map> members) { mcimadamore@673: String[] names = { "B.class", "C.class", "D.class" }; mcimadamore@673: try { mcimadamore@673: for (String name : names) { mcimadamore@673: File f = new File(destDir, name); mcimadamore@673: ClassFile cf = ClassFile.read(f); mcimadamore@673: members.put(cf, readMethod(cf, "m")); mcimadamore@673: } mcimadamore@673: } catch (Exception e) { mcimadamore@673: e.printStackTrace(); mcimadamore@673: throw new Error("error reading classes"); mcimadamore@673: } mcimadamore@673: } mcimadamore@673: mcimadamore@673: static List readMethod(ClassFile cf, String name) throws ConstantPoolException { mcimadamore@673: List buf = new ArrayList<>(); mcimadamore@673: for (Method m : cf.methods) { mcimadamore@673: if (m.getName(cf.constant_pool).equals(name)) { mcimadamore@673: buf.add(m); mcimadamore@673: } mcimadamore@673: } mcimadamore@673: return buf; mcimadamore@673: } mcimadamore@673: mcimadamore@673: static void check(Map> refMembers, Map> membersToCheck) throws ConstantPoolException, InvalidDescriptor { mcimadamore@673: for (Map.Entry> ref : refMembers.entrySet()) { mcimadamore@673: ClassFile cRef = ref.getKey(); mcimadamore@673: for (Method mRef : ref.getValue()) { mcimadamore@673: boolean ok = false; mcimadamore@673: for (Map.Entry> toCheck : membersToCheck.entrySet()) { mcimadamore@673: ClassFile cToCheck = toCheck.getKey(); mcimadamore@673: for (Method mToCheck : toCheck.getValue()) { mcimadamore@673: if (cRef.getName().equals(cToCheck.getName()) && mcimadamore@673: mRef.descriptor.getReturnType(cRef.constant_pool).equals( mcimadamore@673: mToCheck.descriptor.getReturnType(cToCheck.constant_pool)) && mcimadamore@673: mRef.descriptor.getParameterTypes(cRef.constant_pool).equals( mcimadamore@673: mToCheck.descriptor.getParameterTypes(cToCheck.constant_pool))) { mcimadamore@673: ok = true; mcimadamore@673: } mcimadamore@673: } mcimadamore@673: } mcimadamore@673: if (!ok) { mcimadamore@673: throw new AssertionError("Matching method descriptor for " + mRef.descriptor.getParameterTypes(cRef.constant_pool) + "not found"); mcimadamore@673: } mcimadamore@673: } mcimadamore@673: } mcimadamore@673: } mcimadamore@673: }