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);