Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2013 Trillian AB
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
  */
 package org.robovm.compiler;
 
 import static org.robovm.compiler.Annotations.*;
 import static org.robovm.compiler.Types.*;
 import static org.robovm.compiler.llvm.Type.*;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 
 import soot.ArrayType;
 import soot.ByteType;
 import soot.CharType;
 import soot.FloatType;
 import soot.IntType;
 import soot.LongType;
 import soot.PrimType;
 import soot.RefType;
 import soot.ShortType;
 import soot.SootClass;
 import soot.VoidType;
Looks up Bro marshalers.
 
 public class MarshalerLookup {
     private final String BUILTIN_MARSHALERS = "org/robovm/rt/bro/BuiltinMarshalers";
     
     private final Config config;
     private final Map<StringList<Marshaler>> cache = new HashMap<>();
     private boolean searchBuiltins = true;
 
     public MarshalerLookup(Config config) {
         this. = config;
     }
    
    
Sets whether a call to findMarshalers(org.robovm.compiler.MarshalerLookup.MarshalSite) should include the builtin marshalers.

Parameters:
b true to include builtins, false otherwise.
Returns:
this MarshalerLookup.
 
     public MarshalerLookup searchBuiltins(boolean b) {
         this. = b;
         return this;
     }
     
     public Marshaler findMarshalers(MarshalSite marshalSite) {
         soot.Type type = marshalSite.getType();
         SootClass sc = null;
         if (type instanceof RefType) {
             sc = ((RefTypetype).getSootClass();
         } else if (type instanceof ArrayType && ((ArrayTypetype). instanceof RefType) {
             sc = ((RefType) ((ArrayTypetype).).getSootClass();
         }
         
         List<Marshalerresult = new ArrayList<>();
         Set<Stringvisited = new HashSet<>();
         Set<Stringseen = new HashSet<>();
         if (sc != null) {
            findMarshalers(scresultvisitedseenfalse);
        }
        findMarshalers(marshalSite.method.getDeclaringClass(), resultvisitedseen);
        
        for (Marshaler marshaler : result) {
            if (marshaler.canMarshal(marshalSite)) {
                return marshaler;
            }
        }
        return null;
    }
    
    public List<MarshalerfindMarshalers(SootClass sc) {
        List<Marshalerresult = new ArrayList<>();
        Set<Stringvisited = new HashSet<>();
        Set<Stringseen = new HashSet<>();
        findMarshalers(scresultvisitedseen);
        return result;
    }
    
    private void findMarshalers(SootClass scList<Marshalerresult
            Set<StringvisitedSet<Stringseenboolean searchBuiltins) {
        
        findMarshalersOnClasses(scresultvisitedseen);
        findMarshalersOnInterfaces(scresultvisitedseen);
        findMarshalersOnOuterClasses(scresultvisitedseen);
        
        if (searchBuiltins) {
            Clazz builtinMarshalersClazz = .getClazzes().load();
            if (builtinMarshalersClazz != null) {
                findMarshalersOnClasses(builtinMarshalersClazz.getSootClass(), 
                        resultvisitedseen);
            }
        }
    }
    public MarshalerMethod findMarshalerMethod(MarshalSite marshalSite) {
        int pidx = marshalSite.paramIdx;
        if (pidx != .) {
            // Use @Marshaler annotation on method or parameter at paramIndex if there is one 
            AnnotationTag anno = pidx == .
                    ? getMarshalerAnnotation(marshalSite.method
                    : getMarshalerAnnotation(marshalSite.methodpidx);
            if (anno != null) {
                AnnotationClassElem elem = (AnnotationClassElemgetElemByName(anno"value");
                String name = getInternalNameFromDescriptor(elem.getDesc());
                Clazz marshalerClazz = .getClazzes().load(name);
                if (marshalerClazz != null) {
                    Marshaler marshaler = new Marshaler(marshalerClazz);
                    if (marshaler.canMarshal(marshalSite)) {
                        return marshaler.getMarshalerMethod(marshalSite);
                    }
                }
                throw new IllegalArgumentException(String.format(
                        "@Marshaler %s specified for %s of %s method %s can " 
                                + "not be used to marshal %s",
                        name.replace('/''.'), 
                        (pidx == . ? "return type" : "parameter " + (pidx + 1)), 
                        marshalSite.callTypeNamemarshalSite.methodmarshalSite.type));
            }
        }
        
        Marshaler marshaler = findMarshalers(marshalSite);
        if (marshaler != null) {
            return marshaler.getMarshalerMethod(marshalSite);
        }
        throw new IllegalArgumentException(String.format(
                "No @Marshaler found for %s of %s method %s",
                (pidx == . ? "receiver" 
                        : (pidx == . ? "return type" 
                                : "parameter " + (pidx + 1))),
                marshalSite.callTypeNamemarshalSite.method));
    }
    
    private void findMarshalersOnClasses(SootClass scList<Marshalerresult
            Set<StringvisitedSet<Stringseen) {
        result.addAll(findMarshalersOn(scvisitedseen));
        if (sc.hasSuperclass()) {
            findMarshalersOnClasses(sc.getSuperclass(), resultvisitedseen);
        }
    }
    
    private void findMarshalersOnInterfaces(SootClass scList<Marshalerresult
            Set<StringvisitedSet<Stringseen) {
        
        for (SootClass ifs : sc.getInterfaces()) {
            result.addAll(findMarshalersOn(ifsvisitedseen));
        }
        for (SootClass ifs : sc.getInterfaces()) {
            findMarshalersOnInterfaces(ifsresultvisitedseen);
        }
        
        if (sc.hasSuperclass()) {
            findMarshalersOnInterfaces(sc.getSuperclass(), resultvisitedseen);
        }
    }
    private void findMarshalersOnOuterClasses(SootClass scList<Marshalerresult
            Set<StringvisitedSet<Stringseen) {
        SootClass outer = getOuterClass(sc);
        if (outer != null) {
            findMarshalersOnClasses(outerresultvisitedseen);
            findMarshalersOnInterfaces(outerresultvisitedseen);
            findMarshalersOnOuterClasses(outerresultvisitedseen);
        }
    }
    private List<MarshalerfindMarshalersOn(SootClass scSet<StringvisitedSet<Stringseen) {
        
        String internalName = getInternalName(sc);
        if (visited.contains(getInternalName(sc))) {
            return Collections.emptyList();
        }
        visited.contains(internalName);
        
        List<Marshalerall = .get(sc.getName());
        if (all == null) {
            all = new ArrayList<>();
            for (AnnotationTag tag : getMarshalerAnnotations(sc)) {
                AnnotationClassElem elem = (AnnotationClassElemgetElemByName(tag"value");
                String name = getInternalNameFromDescriptor(elem.getDesc());
                Clazz marshalerClazz = .getClazzes().load(name);
                if (marshalerClazz != null) {
                    all.add(new Marshaler(marshalerClazz));
                }
            }
            .put(sc.getName(), all);
        }
        
        List<Marshalerresult = new ArrayList<>();
        for (Marshaler m : all) {
            String name = m.clazz.getInternalName();
            if (!seen.contains(name)) {
                seen.add(name);
                result.add(m);
            }
        }
        return result;
    }
    
    private SootClass getOuterClass(SootClass clazz) {
        String name = getInternalName(clazz);
        for (Tag tag : clazz.getTags()) {
            if (tag instanceof InnerClassTag) {
                InnerClassTag innerClassTag = (InnerClassTagtag;
                String inner = innerClassTag.getInnerClass();
                String outer = innerClassTag.getOuterClass();
                if (inner != null && outer != null && inner.equals(name)) {
                    return .getClazzes().load(outer).getSootClass();
                }
            }
        }
        return null;
    }
    private Set<LonggetSupportedCallTypes(AnnotationTag anno) {
        AnnotationArrayElem el = 
                (AnnotationArrayElemgetElemByName(anno"supportedCallTypes");
        if (el == null) {
            return new HashSet<Long>(Arrays.asList(
                ..,
                ..,
                ..,
                ..,
                ..
            ));
        }
        ArrayList<AnnotationElemvalues = ((AnnotationArrayElemel).getValues();
        Set<LongcallTypes = new HashSet<>();
        for (AnnotationElem value : values) {
            callTypes.add(((AnnotationLongElemvalue).getValue());
        }
        return callTypes;
    }
    private soot.Type getBaseType(SootMethod mAnnotationTag anno) {
        AnnotationClassElem el = (AnnotationClassElemgetElemByName(anno"baseType");
        if (el != null) {
            switch (el.getDesc().charAt(0)) {
            case 'Z'return BooleanType.v();
            case 'B'return ByteType.v();
            case 'S'return ShortType.v();
            case 'C'return CharType.v();
            case 'I'return IntType.v();
            case 'J'return LongType.v();
            case 'F'return FloatType.v();
            case 'D'return DoubleType.v();
            }
            return null;
        }
        soot.Type t = m.getReturnType();
        if (t == VoidType.v()) {
            t = m.getParameterType(0);
        }
        if (t instanceof RefType) {
            SootClass c = ((RefTypet).getSootClass();
            if (isInstanceOfClass(c"java.nio.ByteBuffer")) {
                return ByteType.v();
            } else if (isInstanceOfClass(c"java.nio.ShortBuffer")) {
                return ShortType.v();
            } else if (isInstanceOfClass(c"java.nio.CharBuffer")) {
                return CharType.v();
            } else if (isInstanceOfClass(c"java.nio.IntBuffer")) {
                return IntType.v();
            } else if (isInstanceOfClass(c"java.nio.LongBuffer")) {
                return LongType.v();
            } else if (isInstanceOfClass(c"java.nio.FloatBuffer")) {
                return FloatType.v();
            } else if (isInstanceOfClass(c"java.nio.DoubleBuffer")) {
                return DoubleType.v();
            } else if (isInstanceOfClass(c"org.robovm.rt.bro.Struct")) {
                return .getClazzes().load("org/robovm/rt/bro/Struct")
                            .getSootClass().getType();
            }
        } else if (t instanceof ArrayType) {
            ArrayType arrayType = (ArrayTypet;
            if (arrayType.baseType instanceof PrimType 
                    || isInstanceOfClass(arrayType.baseType"org.robovm.rt.bro.Struct")) {
                return arrayType.baseType;
            }
        }
        return null;
    }
    
    public static class MarshalSite {
        public static final int RETURN_TYPE = -1;
        public static final int RECEIVER = -2;
        
        private final SootMethod method;
        private final int paramIdx;
        private final long callType;
        private final String callTypeName;
        private final soot.Type type;
        private final boolean array;
        
        public MarshalSite(SootMethod method) {
            this(method);
        }
        
        public MarshalSite(SootMethod methodint paramIdx) {
            this. = method;
            this. = paramIdx;
            this. = paramIdx ==  ? method.getReturnType() :
                    (paramIdx ==  ? method.getDeclaringClass().getType()
                    : method.getParameterType(paramIdx));
            
            if (hasBridgeAnnotation(method)) {
                 = ..;
                 = "@Bridge";
                 = false;
            } else if (hasCallbackAnnotation(method)) {
                 = ..;
                 = "@Callback";
                 = false;
            } else if (hasStructMemberAnnotation(method)) {
                 = ..;
                 = "@StructMember";
                 = paramIdx ==  ? hasArrayAnnotation(method
                        : hasArrayAnnotation(methodparamIdx);
            } else if (hasGlobalValueAnnotation(method)) {
                 = ..;
                 = "@GlobalValue";
                 = paramIdx ==  ? hasArrayAnnotation(method
                        : hasArrayAnnotation(methodparamIdx);
            } else {
                throw new IllegalArgumentException();
            }
        }
        
        public SootMethod getMethod() {
            return ;
        }
        
        public long getCallType() {
            return ;
        }
        
        public soot.Type getType() {
            return ;
        }
        
        public boolean isToNative() {
            if ( == ..) {
                return  == ;
            } else {
                return  != ;
            }
        }
        
        public boolean isArray() {
            return ;
        }
    }
    
    public abstract class MarshalerMethod {
        protected final SootMethod method;
        protected final Set<LongsupportedCallTypes;
        MarshalerMethod(SootMethod methodSet<LongsupportedCallTypes) {
            this. = method;
            this. = supportedCallTypes;
        }
        public SootMethod getMethod() {
            return ;
        }
        public boolean supportsCallType(long callType) {
            return .contains(callType);
        }
        public Invokestatic getInvokeStatic(SootClass caller) {
            return new Invokestatic(
                    getInternalName(caller), 
                    getInternalName(.getDeclaringClass()), 
                    .getName(),
                    getDescriptor());
        }
    }
    public class PointerMarshalerMethod extends MarshalerMethod {
        private boolean hasSearchedForAfterBridgeCallMethod = false;
        private SootMethod afterBridgeCallMethod = null;
        private boolean hasSearchedForAfterCallbackCallMethod = false;
        private SootMethod afterCallbackCallMethod = null;
        PointerMarshalerMethod(SootMethod methodSet<LongsupportedCallTypes) {
            super(methodsupportedCallTypes);
        }
        public SootMethod getAfterBridgeCallMethod() {
            if () {
                return ;
            }
             = true;
            List<soot.TypeparamTypes = Arrays.asList(.getParameterType(0), LongType.v(), LongType.v());
            for (SootMethod m : .getDeclaringClass().getMethods()) {
                if (hasAfterBridgeCallAnnotation(m)) {
                    if (m.getReturnType() == VoidType.v() 
                            && m.getParameterTypes().equals(paramTypes)) {
                         = m;
                        break;
                    }
                }
            }
            return ;
        }
        public SootMethod getAfterCallbackCallMethod() {
            if () {
                return ;
            }
             = true;
            List<soot.TypeparamTypes = Arrays.asList(LongType.v(), .getReturnType(), LongType.v());
            for (SootMethod m : .getDeclaringClass().getMethods()) {
                if (hasAfterCallbackCallAnnotation(m)) {
                    if (m.getReturnType() == VoidType.v() 
                            && m.getParameterTypes().equals(paramTypes)) {
                         = m;
                        break;
                    }
                }
            }
            return ;
        }
    }
    public class ValueMarshalerMethod extends MarshalerMethod {
        ValueMarshalerMethod(SootMethod methodSet<LongsupportedCallTypes) {
            super(methodsupportedCallTypes);
        }
        public Type getNativeType(Arch arch) {
            if (.getReturnType() instanceof PrimType) {
                if (hasPointerAnnotation()) {
                    return ;
                }
                if (arch.is32Bit() && (hasMachineSizedSIntAnnotation(
                        || hasMachineSizedUIntAnnotation())) {
                    return ;
                }
                if (arch.is32Bit() && (hasMachineSizedFloatAnnotation())) {
                    return ;
                }
                if (!arch.is32Bit() && (hasMachineSizedFloatAnnotation())) {
                    return ;
                }
                return Types.getType(.getReturnType());
            } else {
                if (hasPointerAnnotation(, 1)) {
                    return ;
                }
                if (arch.is32Bit() && (hasMachineSizedSIntAnnotation(, 1) 
                        || hasMachineSizedUIntAnnotation(, 1))) {
                    return ;
                }
                if (arch.is32Bit() && (hasMachineSizedFloatAnnotation(, 1))) {
                    return ;
                }
                if (!arch.is32Bit() && (hasMachineSizedFloatAnnotation(, 1))) {
                    return ;
                }
                return Types.getType(.getParameterType(1));
            }
        }
    }
    public class ArrayMarshalerMethod extends MarshalerMethod {
        private final soot.Type baseType;
        ArrayMarshalerMethod(SootMethod methodSet<LongsupportedCallTypessoot.Type baseType) {
            super(methodsupportedCallTypes);
            this. = baseType;
        }
        public soot.Type getBaseType() {
            return ;
        }
    }
    
    public class Marshaler {
        private final Clazz clazz;
        private Map<StringMarshalerMethodtoObjectMethods = null;
        private Map<StringMarshalerMethodtoNativeMethods = null;
        private Map<IntegerMap<StringArrayMarshalerMethod>> toArrayObjectMethods = null;
        private Map<IntegerMap<StringArrayMarshalerMethod>> toNativeArrayMethods = null;
        
        private Marshaler(Clazz clazz) {
            this. = clazz;
        }
        private boolean isToObject(SootMethod mAnnotationTag pointerAnno
                AnnotationTag valueAnnoAnnotationTag arrayAnno) {
            // The method must be annotated
            if (pointerAnno == null && valueAnno == null && arrayAnno == null) {
                return false;
            }
            // Fail if there are several annotations
            if (pointerAnno != null && (valueAnno != null || arrayAnno != null
                    || (valueAnno != null && arrayAnno != null)) {
                return false;
            }
            
            // All toObject(...) methods take at least 3 parameters
            @SuppressWarnings("unchecked")
            List<soot.TypeparamTypes = m.getParameterTypes();
            if (paramTypes.size() < 3) {
                return false;
            }
            
            // All toObject(...) methods take a Class as first parameter
            if (!(paramTypes.get(0) instanceof RefType)) {
                return false;
            }
            SootClass sc = ((RefTypeparamTypes.get(0)).getSootClass();
            if (!sc.getName().equals("java.lang.Class")) {
                return false;
            }
            
            soot.Type returnType = m.getReturnType();
            
            if (pointerAnno != null) {
                // T toObject(Class<?> cls, long handle, long flags)
                if (!(returnType instanceof RefLikeType)) {
                    return false;
                }
                if (paramTypes.size() == 3) {
                    if (paramTypes.get(1) == LongType.v() 
                            && paramTypes.get(2) == LongType.v()) {
                        return true;
                    }
                }
            } else if (valueAnno != null) {
                // T toObject(Class<?> cls, <primitive> value, long flags)
                if (!(returnType instanceof RefLikeType)) {
                    return false;
                }
                if (paramTypes.size() == 3) {
                    if (paramTypes.get(1) instanceof PrimType 
                            && paramTypes.get(2) == LongType.v()) {
                        if (hasPointerAnnotation(m, 1)) {
                            return paramTypes.get(1).equals(LongType.v());
                        }
                        if (hasMachineSizedFloatAnnotation(m, 1)) {
                            return paramTypes.get(1).equals(FloatType.v()) 
                                || paramTypes.get(1).equals(DoubleType.v());
                        }
                        if (hasMachineSizedSIntAnnotation(m, 1)) {
                            return paramTypes.get(1).equals(LongType.v());
                        }
                        if (hasMachineSizedUIntAnnotation(m, 1)) {
                            return paramTypes.get(1).equals(LongType.v());
                        }
                        return true;
                    }
                }
            } else if (arrayAnno != null) {
                // T toObject(Class<?> cls, long handle, long flags, int d1[, int d2[, int d3]])
                if (!(returnType instanceof RefLikeType)) {
                    return false;
                }
                if (getBaseType(marrayAnno) == null) {
                    return false;
                }
                if (paramTypes.size() > 3) {
                    if (paramTypes.get(1) == LongType.v() 
                            && paramTypes.get(2) == LongType.v()) {
                        for (int i = 3; i < paramTypes.size(); i++) {
                            if (paramTypes.get(i) != IntType.v()) {
                                return false;
                            }
                        }
                        return true;
                    }
                }
            }
            
            return false;
        }
        private boolean isToNative(SootMethod mAnnotationTag pointerAnno
                AnnotationTag valueAnnoAnnotationTag arrayAnno) {
            // The method must be annotated
            if (pointerAnno == null && valueAnno == null && arrayAnno == null) {
                return false;
            }
            // Fail if there are several annotations
            if (pointerAnno != null && (valueAnno != null || arrayAnno != null
                    || (valueAnno != null && arrayAnno != null)) {
                return false;
            }
            
            // All toNative(...) methods take at least 2 parameters
            @SuppressWarnings("unchecked")
            List<soot.TypeparamTypes = m.getParameterTypes();
            if (paramTypes.size() < 2) {
                return false;
            }
            
            // All toNative(...) methods take a reference as first parameter
            if (!(paramTypes.get(0) instanceof RefLikeType)) {
                return false;
            }
            
            soot.Type returnType = m.getReturnType();
            
            if (pointerAnno != null) {
                // long toNative(T t, long flags)
                if (returnType != LongType.v()) {
                    return false;
                }
                if (paramTypes.size() == 2) {
                    if (paramTypes.get(1) == LongType.v()) {
                        return true;
                    }
                }
            } else if (valueAnno != null) {
                // <primitive> toNative(T value, long flags)
                if (!(returnType instanceof PrimType)) {
                    return false;
                }
                if (paramTypes.size() == 2) {
                    if (paramTypes.get(1) == LongType.v()) {
                        if (hasPointerAnnotation(m)) {
                            return returnType.equals(LongType.v());
                        }
                        if (hasMachineSizedFloatAnnotation(m)) {
                            return returnType.equals(FloatType.v()) 
                                || returnType.equals(DoubleType.v());
                        }
                        if (hasMachineSizedSIntAnnotation(m)) {
                            return returnType.equals(LongType.v());
                        }
                        if (hasMachineSizedUIntAnnotation(m)) {
                            return returnType.equals(LongType.v());
                        }
                        return true;
                    }
                }
            } else if (arrayAnno != null) {
                // void toNative(T t, long handle, long flags, int d1[, int d2[, int d3]])
                if (returnType != VoidType.v()) {
                    return false;
                }
                if (getBaseType(marrayAnno) == null) {
                    return false;
                }
                if (paramTypes.size() > 3) {
                    if (paramTypes.get(1) == LongType.v() 
                            && paramTypes.get(2) == LongType.v()) {
                        for (int i = 3; i < paramTypes.size(); i++) {
                            if (paramTypes.get(i) != IntType.v()) {
                                return false;
                            }
                        }
                        return true;
                    }
                }
            }
            
            return false;
        }
        
        private void buildMaps() {
            if ( == null &&  == null 
                    &&  == null &&  == null) {
                
                 = new HashMap<>();
                 = new HashMap<>();
                 = new HashMap<>();
                 = new HashMap<>();
                
                for (SootMethod m : .getSootClass().getMethods()) {
                    if (m.isStatic() && m.isPublic()) {
                        AnnotationTag pointerAnno = getMarshalsPointerAnnotation(m);
                        AnnotationTag valueAnno = getMarshalsValueAnnotation(m);
                        AnnotationTag arrayAnno = getMarshalsArrayAnnotation(m);
                        if (isToObject(mpointerAnnovalueAnnoarrayAnno)) {
                            AnnotationTag anno = pointerAnno != null ? pointerAnno 
                                    : (valueAnno != null ? valueAnno : arrayAnno);
                            Set<LongsupportedCallTypes = getSupportedCallTypes(anno);
                            if (pointerAnno != null) {
                                .put(getDescriptor(m.getReturnType()), 
                                        new PointerMarshalerMethod(msupportedCallTypes));
                            } else if (valueAnno != null) {
                                .put(getDescriptor(m.getReturnType()), 
                                        new ValueMarshalerMethod(msupportedCallTypes));
                            } else {
                                int dimCount = m.getParameterCount() - 3;
                                Map<StringArrayMarshalerMethodmap = .get(dimCount);
                                if (map == null) {
                                    map = new HashMap<>();
                                    .put(dimCountmap);
                                }
                                map.put(getDescriptor(m.getReturnType()), 
                                        new ArrayMarshalerMethod(msupportedCallTypes
                                                getBaseType(marrayAnno)));
                            }
                        } else if (isToNative(mpointerAnnovalueAnnoarrayAnno)) {
                            AnnotationTag anno = pointerAnno != null ? pointerAnno 
                                    : (valueAnno != null ? valueAnno : arrayAnno);
                            Set<LongsupportedCallTypes = getSupportedCallTypes(anno);
                            if (pointerAnno != null) {
                                .put(getDescriptor(m.getParameterType(0)), 
                                        new PointerMarshalerMethod(msupportedCallTypes));
                            } else if (valueAnno != null) {
                                .put(getDescriptor(m.getParameterType(0)), 
                                        new ValueMarshalerMethod(msupportedCallTypes));
                            } else {
                                int dimCount = m.getParameterCount() - 3;
                                Map<StringArrayMarshalerMethodmap = .get(dimCount);
                                if (map == null) {
                                    map = new HashMap<>();
                                    .put(dimCountmap);
                                }
                                map.put(getDescriptor(m.getParameterType(0)), 
                                        new ArrayMarshalerMethod(msupportedCallTypes
                                                getBaseType(marrayAnno)));
                            }
                        } else if (pointerAnno != null || valueAnno != null || arrayAnno != null) {
                            .getLogger().warn("Ignoring invalid marshaler method %s"m);
                        }
                    }
                }
            }
        }
        
        private soot.Type makeArrayType(soot.Type baseTypeint numDimensions) {
            soot.Type newType = baseType;
            for (int i = 0; i < numDimensionsi++) {
                newType = newType.makeArrayType();
            }
            return newType;
        }
        
        private MarshalerMethod findMarshalerMethod(soot.Type typeMap<String, ? extends MarshalerMethodmap) {
            MarshalerMethod m = map.get(getDescriptor(type));
            if (m != null) {
                return m;
            }
            
            if (type instanceof RefType) {
                SootClass sc = ((RefTypetype).getSootClass();
                if (sc.hasSuperclass()) {
                    m = findMarshalerMethod(sc.getSuperclass().getType(), map);
                    if (m != null) {
                        return m;
                    }
                }
                for (SootClass ifs : sc.getInterfaces()) {
                    m = findMarshalerMethod(ifs.getType(), map);
                    if (m != null) {
                        return m;
                    }                    
                }
            } else if (type instanceof ArrayType) {
                ArrayType arrayType = (ArrayTypetype;
                if (arrayType.baseType instanceof RefType) {
                    SootClass sc = ((RefTypearrayType.baseType).getSootClass();
                    if (sc.hasSuperclass()) {
                        m = findMarshalerMethod(makeArrayType(sc.getSuperclass().getType(), 
                                arrayType.numDimensions), map);
                        if (m != null) {
                            return m;
                        }                    
                    }
                    for (SootClass ifs : sc.getInterfaces()) {
                        m = findMarshalerMethod(makeArrayType(ifs.getType(), 
                                arrayType.numDimensions), map);
                        if (m != null) {
                            return m;
                        }                    
                    }
                }
            }
            return null;
        }
        
        public Clazz getClazz() {
            return ;
        }
        
        public boolean canMarshal(MarshalSite marshalSite) {
            return getMarshalerMethod(marshalSite) != null;
        }
        public MarshalerMethod getMarshalerMethod(MarshalSite marshalSite) {
            buildMaps();
            Map<String, ? extends MarshalerMethodmap = null;
            if (marshalSite.isArray()) {
                int dimCount = Bro.getArrayDimensions(marshalSite.methodmarshalSite.paramIdx).length;
                map = marshalSite.isToNative() ? .get(dimCount
                        : .get(dimCount);
                if (map == null) {
                    return null;
                }
            } else {
                map = marshalSite.isToNative() ?  : ;
            }
            MarshalerMethod m = findMarshalerMethod(marshalSite.getType(), map);
            if (m != null) {
                if (m.supportsCallType(marshalSite.getCallType())) {
                    return m;
                }
            }
            return null;
        }
    }
New to GrepCode? Check out our FAQ X