Exported annotation needs to be inherited for virtual methods closure
authorLubomir Nerad <lubomir.nerad@oracle.com>
Wed, 08 May 2013 17:47:47 +0200
branchclosure
changeset 1087d868b5a67b9b
parent 1086 2ac4283ee209
child 1094 36961c9a009f
Exported annotation needs to be inherited for virtual methods
rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassDataCache.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
     1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassDataCache.java	Wed May 08 14:54:32 2013 +0200
     1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassDataCache.java	Wed May 08 17:47:47 2013 +0200
     1.3 @@ -67,44 +67,143 @@
     1.4          return findField(getClassData(startingClass), name, signature);
     1.5      }
     1.6  
     1.7 -    MethodData findMethod(ClassData currentClass,
     1.8 +    MethodData findMethod(final ClassData startingClass,
     1.9                            final String name,
    1.10                            final String signature) throws IOException {
    1.11 +        final FindFirstTraversalCallback<MethodData> ffTraversalCallback =
    1.12 +                new FindFirstTraversalCallback<MethodData>();
    1.13 +
    1.14 +        findMethods(startingClass, name, signature, ffTraversalCallback);
    1.15 +        return ffTraversalCallback.getFirst();
    1.16 +    }
    1.17 +
    1.18 +    FieldData findField(final ClassData startingClass,
    1.19 +                        final String name,
    1.20 +                        final String signature) throws IOException {
    1.21 +        final FindFirstTraversalCallback<FieldData> ffTraversalCallback =
    1.22 +                new FindFirstTraversalCallback<FieldData>();
    1.23 +
    1.24 +        findFields(startingClass, name, signature, ffTraversalCallback);
    1.25 +        return ffTraversalCallback.getFirst();
    1.26 +    }
    1.27 +
    1.28 +    void findMethods(final ClassData startingClass,
    1.29 +                     final String methodName,
    1.30 +                     final String methodSignature,
    1.31 +                     final TraversalCallback<MethodData> mdTraversalCallback)
    1.32 +                             throws IOException {
    1.33 +        traverseHierarchy(
    1.34 +                startingClass,
    1.35 +                new FindMethodsTraversalCallback(methodName, methodSignature,
    1.36 +                                                 mdTraversalCallback));
    1.37 +    }
    1.38 +
    1.39 +    void findFields(final ClassData startingClass,
    1.40 +                    final String fieldName,
    1.41 +                    final String fieldSignature,
    1.42 +                    final TraversalCallback<FieldData> fdTraversalCallback)
    1.43 +                            throws IOException {
    1.44 +        traverseHierarchy(
    1.45 +                startingClass,
    1.46 +                new FindFieldsTraversalCallback(fieldName, fieldSignature,
    1.47 +                                                fdTraversalCallback));
    1.48 +    }
    1.49 +
    1.50 +    private boolean traverseHierarchy(
    1.51 +            ClassData currentClass,
    1.52 +            final TraversalCallback<ClassData> cdTraversalCallback)
    1.53 +                throws IOException {
    1.54          while (currentClass != null) {
    1.55 -            final MethodData methodData =
    1.56 -                    currentClass.findMethod(name, signature);
    1.57 -            if (methodData != null) {
    1.58 -                return methodData;
    1.59 +            if (!cdTraversalCallback.traverse(currentClass)) {
    1.60 +                return false;
    1.61 +            }
    1.62 +
    1.63 +            for (final String superIfaceName:
    1.64 +                    currentClass.getSuperInterfaces()) {
    1.65 +                if (!traverseHierarchy(getClassData(superIfaceName),
    1.66 +                                       cdTraversalCallback)) {
    1.67 +                    return false;
    1.68 +                }
    1.69              }
    1.70  
    1.71              final String superClassName = currentClass.getSuperClassName();
    1.72              if (superClassName == null) {
    1.73                  break;
    1.74              }
    1.75 +
    1.76              currentClass = getClassData(superClassName);
    1.77          }
    1.78  
    1.79 -        return null;
    1.80 +        return true;
    1.81      }
    1.82  
    1.83 -    FieldData findField(ClassData currentClass,
    1.84 -                        final String name,
    1.85 -                        final String signature) throws IOException {
    1.86 -        while (currentClass != null) {
    1.87 -            final FieldData fieldData =
    1.88 -                    currentClass.findField(name, signature);
    1.89 -            if (fieldData != null) {
    1.90 -                return fieldData;
    1.91 -            }
    1.92 +    interface TraversalCallback<T> {
    1.93 +        boolean traverse(T object);
    1.94 +    }
    1.95  
    1.96 -            final String superClassName = currentClass.getSuperClassName();
    1.97 -            if (superClassName == null) {
    1.98 -                break;
    1.99 -            }
   1.100 -            currentClass = getClassData(superClassName);
   1.101 +    private final class FindFirstTraversalCallback<T>
   1.102 +            implements TraversalCallback<T> {
   1.103 +        private T firstObject;
   1.104 +
   1.105 +        @Override
   1.106 +        public boolean traverse(final T object) {
   1.107 +            firstObject = object;
   1.108 +            return false;
   1.109          }
   1.110  
   1.111 -        return null;
   1.112 +        public T getFirst() {
   1.113 +            return firstObject;
   1.114 +        }
   1.115 +    }
   1.116 +
   1.117 +    private final class FindMethodsTraversalCallback
   1.118 +            implements TraversalCallback<ClassData> {
   1.119 +        private final String methodName;
   1.120 +        private final String methodSignature;
   1.121 +        private final TraversalCallback<MethodData> mdTraversalCallback;
   1.122 +
   1.123 +        public FindMethodsTraversalCallback(
   1.124 +                final String methodName,
   1.125 +                final String methodSignature,
   1.126 +                final TraversalCallback<MethodData> mdTraversalCallback) {
   1.127 +            this.methodName = methodName;
   1.128 +            this.methodSignature = methodSignature;
   1.129 +            this.mdTraversalCallback = mdTraversalCallback;
   1.130 +        }
   1.131 +
   1.132 +        @Override
   1.133 +        public boolean traverse(final ClassData classData) {
   1.134 +            final MethodData methodData =
   1.135 +                    classData.findMethod(methodName, methodSignature);
   1.136 +            return (methodData != null)
   1.137 +                       ? mdTraversalCallback.traverse(methodData)
   1.138 +                       : true;
   1.139 +        }
   1.140 +    }
   1.141 +
   1.142 +    private final class FindFieldsTraversalCallback
   1.143 +            implements TraversalCallback<ClassData> {
   1.144 +        private final String fieldName;
   1.145 +        private final String fieldSignature;
   1.146 +        private final TraversalCallback<FieldData> fdTraversalCallback;
   1.147 +
   1.148 +        public FindFieldsTraversalCallback(
   1.149 +                final String fieldName,
   1.150 +                final String fieldSignature,
   1.151 +                final TraversalCallback<FieldData> fdTraversalCallback) {
   1.152 +            this.fieldName = fieldName;
   1.153 +            this.fieldSignature = fieldSignature;
   1.154 +            this.fdTraversalCallback = fdTraversalCallback;
   1.155 +        }
   1.156 +
   1.157 +        @Override
   1.158 +        public boolean traverse(final ClassData classData) {
   1.159 +            final FieldData fieldData =
   1.160 +                    classData.findField(fieldName, fieldSignature);
   1.161 +            return (fieldData != null)
   1.162 +                       ? fdTraversalCallback.traverse(fieldData)
   1.163 +                       : true;
   1.164 +        }
   1.165      }
   1.166  
   1.167      private static InputStream loadClass(Bck2Brwsr.Resources l, String name)
     2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Wed May 08 14:54:32 2013 +0200
     2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Wed May 08 17:47:47 2013 +0200
     2.3 @@ -115,7 +115,7 @@
     2.4      protected void declaredMethod(MethodData methodData,
     2.5                                    String destObject,
     2.6                                    String mangledName) throws IOException {
     2.7 -        if (exportedSymbols.isExported(methodData)) {
     2.8 +        if (isHierarchyExported(methodData)) {
     2.9              exportMember(destObject, mangledName);
    2.10          }
    2.11      }
    2.12 @@ -317,7 +317,7 @@
    2.13                  && (((method.access & ByteCodeParser.ACC_FINAL) != 0)
    2.14                          || ((referencedClass.getAccessFlags()
    2.15                                   & ByteCodeParser.ACC_FINAL) != 0)
    2.16 -                        || !exportedSymbols.isExported(method))) {
    2.17 +                        || !isHierarchyExported(method))) {
    2.18              return object + "." + mangledName;
    2.19          }
    2.20  
    2.21 @@ -331,6 +331,28 @@
    2.22          return "invoker." + mangledName + '(' + object + ')';
    2.23      }
    2.24  
    2.25 +    private boolean isHierarchyExported(final MethodData methodData)
    2.26 +            throws IOException {
    2.27 +        if (exportedSymbols.isExported(methodData)) {
    2.28 +            return true;
    2.29 +        }
    2.30 +        if ((methodData.access & (ByteCodeParser.ACC_PRIVATE
    2.31 +                                      | ByteCodeParser.ACC_STATIC)) != 0) {
    2.32 +            return false;
    2.33 +        }
    2.34 +
    2.35 +        final ExportedMethodFinder exportedMethodFinder =
    2.36 +                new ExportedMethodFinder(exportedSymbols);
    2.37 +
    2.38 +        classDataCache.findMethods(
    2.39 +                methodData.cls,
    2.40 +                methodData.getName(),
    2.41 +                methodData.getInternalSig(),
    2.42 +                exportedMethodFinder);
    2.43 +
    2.44 +        return (exportedMethodFinder.getFound() != null);
    2.45 +    }
    2.46 +
    2.47      private static String accessNonVirtualMember(String object,
    2.48                                                   String mangledName,
    2.49                                                   ClassData declaringClass) {
    2.50 @@ -338,6 +360,33 @@
    2.51                                          : object + "['" + mangledName + "']";
    2.52      }
    2.53  
    2.54 +    private static final class ExportedMethodFinder
    2.55 +            implements ClassDataCache.TraversalCallback<MethodData> {
    2.56 +        private final ExportedSymbols exportedSymbols;
    2.57 +        private MethodData found;
    2.58 +
    2.59 +        public ExportedMethodFinder(final ExportedSymbols exportedSymbols) {
    2.60 +            this.exportedSymbols = exportedSymbols;
    2.61 +        }
    2.62 +
    2.63 +        @Override
    2.64 +        public boolean traverse(final MethodData methodData) {
    2.65 +            try {
    2.66 +                if (exportedSymbols.isExported(methodData)) {
    2.67 +                    found = methodData;
    2.68 +                    return false;
    2.69 +                }
    2.70 +            } catch (final IOException e) {
    2.71 +            }
    2.72 +
    2.73 +            return true;
    2.74 +        }
    2.75 +
    2.76 +        public MethodData getFound() {
    2.77 +            return found;
    2.78 +        }
    2.79 +    }
    2.80 +
    2.81      private static final class Standalone extends VM {
    2.82          private Standalone(Appendable out, Bck2Brwsr.Resources resources) {
    2.83              super(out, resources);