Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2014 Trillian Mobile 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.plugin.objc;
 
 import static org.objectweb.asm.Opcodes.*;
 
 import java.io.File;
 import java.util.List;
 import java.util.Set;
 
 
 import soot.SootClass;
org.robovm.compiler.plugin.CompilerPlugin which generates proxy classes for Objective-C protocol interfaces. The proxy class implements all

Method:
and @Property methods of an interface and all its superinterfaces. We need these proxy classes as peers for Objective-C protocols which don't have a dedicated Java peer class (e.g. when the class implementing the Objective-C protocol isn't exposed).
 
     public static final String OBJC_PROTOCOL = "org.robovm.objc.ObjCProtocol";
     public static final String PROXY_CLASS_NAME_SUFFIX = "$ObjCProxy";
 
     private SootClass org_robovm_objc_ObjCProtocol = null;
 
     private boolean initialized = false;
 
     private void init() {
         if () {
             return;
         }
         SootResolver r = SootResolver.v();
          = true;
     }
     
     public static boolean isObjCProxy(SootClass cls) {
         return (cls.getModifiers() & .) > 0
             && cls.getName().endsWith();
     }
     
     private boolean isObjCProtocol(SootClass cls) {
         if (.isPhantom() || !cls.isInterface()) {
             return false;
         }
         for (SootClass interfaze : cls.getInterfaces()) {
             if (interfaze ==  || isObjCProtocol(interfaze)) {
                 return true;
             }
         }
         return false;
     }
    
    
Returns the class the proxy should have as superclass, either org.robovm.apple.foundation.NSObject, org.robovm.cocoatouch.foundation.NSObject or org.robovm.objc.ObjCObject.
 
         if (cls.getName().equals("org.robovm.apple.foundation.NSObjectProtocol")) {
             return "org/robovm/apple/foundation/NSObject";
         }
         if (cls.getName().equals("org.robovm.cocoatouch.foundation.NSObjectProtocol")) {
             return "org/robovm/cocoatouch/foundation/NSObject";
        }
        if (cls == ) {
            return "org/robovm/objc/ObjCObject";
        }
        for (SootClass interfaze : cls.getInterfaces()) {
            String name = getProxySuperclassInternalName(interfaze);
            if (name != null) {
                return name;
            }
        }
        return null;
    }
    
    private void collectProxyInterfaceInternalNames(SootClass clsList<Stringresult) {
        if (result.isEmpty()) {
            result.add(cls.getName().replace('.''/'));
        }
        for (SootClass interfaze : cls.getInterfaces()) {
            String internalName = interfaze.getName().replace('.''/');
            if (!result.contains(internalName)) {
                result.add(internalName);
            }
        }
        for (SootClass interfaze : cls.getInterfaces()) {
            collectProxyInterfaceInternalNames(interfazeresult);
        }
    }
    
    private void generateProxyMethods(Config configList<Stringinterfazes
            ClassWriter cwthrows IOException {
        
        Clazzes clazzes = config.getClazzes();
        
        final Set<StringaddedMethods = new HashSet<>();
        for (String interfaze : interfazes) {
            Clazz clazz = clazzes.load(interfaze);
            if (clazz == null) {
                continue;
            }
            
            // Copy all abstract method (we skip default methods) to the proxy 
            // and make them native instead of abstract.
            
            ClassReader classReader = new ClassReader(clazz.getBytes());
            classReader.accept(new ClassVisitor(cw) {
                @Override
                public MethodVisitor visitMethod(int accessString nameString descString signature,
                        String[] exceptions) {
                    
                    String key = name + desc;
                    if ((access & ) > 0 && !addedMethods.contains(key)) {
                        access &= ~;
                        access |= ;
                        addedMethods.add(key);
                        return super.visitMethod(accessnamedescsignatureexceptions);
                    }
                    return null;
                }
                @Override
                public void visit(int versionint accessString nameString signatureString superName,
                        String[] interfaces) {
                    // Ignored
                }
                @Override
                public void visitEnd() {
                    // Ignored
                }
                @Override
                public AnnotationVisitor visitAnnotation(String descboolean visible) {
                    // Ignored
                    return null;
                }
                @Override
                public void visitAttribute(Attribute attr) {
                    // Ignored
                }
                @Override
                public FieldVisitor visitField(int accessString nameString descString signatureObject value) {
                    // Ignored
                    return null;
                }
                @Override
                public void visitInnerClass(String nameString outerNameString innerNameint access) {
                    // Ignored
                }
                @Override
                public void visitOuterClass(String ownerString nameString desc) {
                    // Ignored
                }
                @Override
                public void visitSource(String sourceString debug) {
                    // Ignored
                }
            }, 0);
        }
    }
    
    @Override
    public void beforeClass(Config configClazz clazz) {
        init();
        SootClass sootClass = clazz.getSootClass();
        if (isObjCProtocol(sootClass)) {
            
            try {
                String proxyInternalName = clazz.getInternalName() + ;
                ArrayList<Stringinterfazes = new ArrayList<>();
                collectProxyInterfaceInternalNames(sootClassinterfazes);
                ClassWriter cw = new ClassWriter(.);
                cw.visit(51,  +  +  + ,
                        proxyInternalNamenull,
                        getProxySuperclassInternalName(sootClass), 
                        new String[] {clazz.getInternalName()});
                generateProxyMethods(configinterfazescw);
                cw.visitEnd();
                
                File f = clazz.getPath().getGeneratedClassFile(proxyInternalName);
                FileUtils.writeByteArrayToFile(fcw.toByteArray());
                // The proxy class is created after the interface is compiled.
                // This prevents the triggering of a recompile of the interface.
                f.setLastModified(clazz.lastModified());
                // Add the proxy class as a dependency for the protocol interface.
                // Important! This must be done AFTER the class file has been written.
                clazz.getClazzInfo().addDependency(proxyInternalName);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
New to GrepCode? Check out our FAQ X