Package com.bj58.spat.gaea.server.deploy.bytecode

Source Code of com.bj58.spat.gaea.server.deploy.bytecode.ScanClass

/*
*  Copyright Beijing 58 Information Technology Co.,Ltd.
*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you under the Apache License, Version 2.0 (the
*  "License"); you may not use this file except in compliance
*  with the License.  You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*/
package com.bj58.spat.gaea.server.deploy.bytecode;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.bj58.spat.gaea.server.contract.annotation.AnnotationUtil;
import com.bj58.spat.gaea.server.contract.annotation.HttpPathParameter;
import com.bj58.spat.gaea.server.contract.annotation.HttpRequestMapping;
import com.bj58.spat.gaea.server.contract.annotation.OperationContract;
import com.bj58.spat.gaea.server.contract.annotation.ServiceBehavior;
import com.bj58.spat.gaea.server.contract.annotation.ServiceContract;
import com.bj58.spat.gaea.server.contract.log.ILog;
import com.bj58.spat.gaea.server.contract.log.LogFactory;
import com.bj58.spat.gaea.server.deploy.bytecode.ContractInfo.SessionBean;
import com.bj58.spat.gaea.server.deploy.hotdeploy.DynamicClassLoader;
import com.bj58.spat.gaea.server.util.ClassHelper;
import com.bj58.spat.gaea.server.util.FileHelper;

/**
* GaeaBinaryConvert
*
* @author Service Platform Architecture Team (spat@58.com)
*/
public class ScanClass {
 
  /**
   * logger
   */
  private static ILog logger = LogFactory.getLogger(ScanClass.class);
 
 
  /**
   * ContractInfo for create proxy
   */
  private static ContractInfo contractInfo = null;
 
  /**
   * contract ClassInfo
   */
  private static List<ClassInfo> contractClassInfos = null;
 
  /**
   * behavior ClassInfo
   */
  private static List<ClassInfo> behaviorClassInfos = null;
 
  private static Object lockHelper = new Object();
 
 
  /**
   *
   * @param path
   * @param classLoader
   * @return
   * @throws Exception
   */
  public static ContractInfo getContractInfo(String path, DynamicClassLoader classLoader) throws Exception {
    if(contractInfo == null) {
      synchronized (lockHelper) {
        if(contractInfo == null) {
          scan(path, classLoader);
        }
      }
    }
   
    return contractInfo;
  }
 
  /**
   *
   * @param path
   * @param classLoader
   * @return
   * @throws Exception
   */
  public static List<ClassInfo> getContractClassInfos(String path, DynamicClassLoader classLoader) throws Exception {
    if(contractInfo == null) {
      synchronized (lockHelper) {
        if(contractInfo == null) {
          scan(path, classLoader);
        }
      }
    }
   
    return contractClassInfos;
  }
 
  /**
   *
   * @param path
   * @param classLoader
   * @return
   * @throws Exception
   */
  public static List<ClassInfo> getBehaviorClassInfos(String path, DynamicClassLoader classLoader) throws Exception {
    if(contractInfo == null) {
      synchronized (lockHelper) {
        if(contractInfo == null) {
          scan(path, classLoader);
        }
      }
    }
   
    return behaviorClassInfos;
  }
 
 
  /**
   * scan jars create ContractInfo
   * @param path
   * @param classLoader
   * @return
   * @throws Exception
   */
  private static void scan(String path, DynamicClassLoader classLoader) throws Exception {
    logger.info("begin scan jar from path:" + path);

    List<String> jarPathList = FileHelper.getUniqueLibPath(path);

    if(jarPathList == null) {
        throw new Exception("no jar fonded from path: " + path);
    }

    contractClassInfos = new ArrayList<ClassInfo>();
    behaviorClassInfos = new ArrayList<ClassInfo>();

    for (String jpath : jarPathList) {
        Set<Class<?>> clsSet = null;
        try {
            clsSet = ClassHelper.getClassFromJar(jpath, classLoader);
        } catch (Exception ex) {
            throw ex;
        }
       
        if (clsSet == null) {
            continue;
        }
       
        for (Class<?> cls : clsSet) {
            try {
              ServiceBehavior behavior = cls.getAnnotation(ServiceBehavior.class);
              ServiceContract contract = cls.getAnnotation(ServiceContract.class);
              if(behavior == null && contract == null) {
                continue;
              }
             
              if(contract != null) {
                ClassInfo ci = contract(cls);
                if(ci != null) {
                  contractClassInfos.add(ci);
                }
              } else if(behavior != null) {
                ClassInfo ci = behavior(cls);
                if(ci != null) {
                  behaviorClassInfos.add(ci);
                }
              }
            } catch (Exception ex) {
              throw ex;
            }
        }
    }

    contractInfo = createContractInfo(contractClassInfos, behaviorClassInfos);
   
    logger.info("finish scan jar");
  }
 
 
  /**
   *
   * @param cls
   * @param ignoreAnnotation
   * @return
   */
  protected static ClassInfo contract(Class<?> cls, boolean ignoreAnnotation) {
    if(ignoreAnnotation) {
      ClassInfo ci = new ClassInfo();
      ci.setCls(cls);
      ci.setClassType(ClassInfo.ClassType.INTERFACE);

      Method[] methods = cls.getDeclaredMethods();
      List<ClassInfo.MethodInfo> methodInfos = new ArrayList<ClassInfo.MethodInfo>();
     
       for(Method m : methods) {
         if(Modifier.isPublic(m.getModifiers()) || Modifier.isProtected(m.getModifiers())) {
           ClassInfo.MethodInfo mi = new ClassInfo.MethodInfo();
           mi.setMethod(m);
           methodInfos.add(mi);
         }
       }
       ci.setMethodList(methodInfos);
      
       return ci;
    } else {
      return contract(cls);
    }
  }
 
  /**
   *
   * @param cls
   * @return
   */
  protected static ClassInfo contract(Class<?> cls) {
    ServiceContract contractAnn = cls.getAnnotation(ServiceContract.class);
   
    ClassInfo ci = new ClassInfo();
    ci.setCls(cls);
    ci.setClassType(ClassInfo.ClassType.INTERFACE);

    List<Class<?>> interfaceList = getInterfaces(cls);
    List<ClassInfo.MethodInfo> methodInfos = new ArrayList<ClassInfo.MethodInfo>();

    for(Class<?> interfaceCls : interfaceList) {
      Method[] methods = interfaceCls.getDeclaredMethods();
      if(contractAnn != null && contractAnn.defaultAll()) {
         for(Method m : methods) {
           if(Modifier.isPublic(m.getModifiers()) || Modifier.isProtected(m.getModifiers())) {
             ClassInfo.MethodInfo mi = new ClassInfo.MethodInfo();
             mi.setMethod(m);
             methodInfos.add(mi);
           }
         }
      } else {
         for(Method m : methods) {
           if(Modifier.isPublic(m.getModifiers()) || Modifier.isProtected(m.getModifiers())) {
             OperationContract oc = m.getAnnotation(OperationContract.class);
             if(oc != null) {
               ClassInfo.MethodInfo mi = new ClassInfo.MethodInfo();
               mi.setMethod(m);
               methodInfos.add(mi);
             }
           }
         }
      }
    }
   
    ci.setMethodList(methodInfos);

    return ci;
   
  }
 
 
  /**
   *
   * @param cls
   * @return
   * @throws Exception
   */
  protected static ClassInfo behavior(Class<?> cls) throws Exception {
    ServiceBehavior behaviorAnn = cls.getAnnotation(ServiceBehavior.class);

    ClassInfo ci = new ClassInfo();
    ci.setCls(cls);
    ci.setClassType(ClassInfo.ClassType.CLASS);

    if(behaviorAnn != null && !behaviorAnn.lookUP().equalsIgnoreCase(AnnotationUtil.DEFAULT_VALUE)) {
      ci.setLookUP(behaviorAnn.lookUP());
    } else {
      ci.setLookUP(cls.getSimpleName());
    }
    Method[] methods = cls.getDeclaredMethods();
    List<ClassInfo.MethodInfo> methodInfos = new ArrayList<ClassInfo.MethodInfo>();

    for(Method m : methods) {
      //only load public or protected method
      if(Modifier.isPublic(m.getModifiers()) || Modifier.isProtected(m.getModifiers())) {
        ClassInfo.MethodInfo mi = new ClassInfo.MethodInfo();
        mi.setMethod(m);
       
        HttpRequestMapping requestMappingAnn = m.getAnnotation(HttpRequestMapping.class);
        mi.setHttpRequestMapping(requestMappingAnn);
       
        Class<?>[] paramAry = m.getParameterTypes();
        Type[] types = m.getGenericParameterTypes();
       
        String[] paramNames = ClassHelper.getParamNames(cls, m);
        String[] mapping = new String[paramAry.length];
        HttpPathParameter[] paramAnnAry = new HttpPathParameter[paramAry.length];

        //load RequestMapping
        if(requestMappingAnn != null) {
          Object[][] annotations = ClassHelper.getParamAnnotations(cls, m);
          for(int i=0; i<annotations.length; i++) {
            for(int j=0; j<annotations[i].length; j++) {
              HttpPathParameter paramAnn = null;
              try {
                paramAnn = (HttpPathParameter)annotations[i][j];
              } catch(Exception ex) {
               
              }
             
              paramAnnAry[i] = paramAnn;
              if(paramAnn != null) {
                mapping[i] = paramAnn.mapping();
                break;
              } else {
                mapping[i] = paramNames[i];
              }
            }
          }
         
          for(int i=0; i<paramAry.length; i++) {
            if(mapping[i] == null) {
              mapping[i] = paramNames[i];
            }
          }
        }
       
        ClassInfo.ParamInfo[] paramInfoAry = new ClassInfo.ParamInfo[paramAry.length];
        for(int i=0; i<paramAry.length; i++) {
          paramInfoAry[i] = new ClassInfo.ParamInfo(i,
              paramAry[i],
              types[i],
              paramNames[i],
              mapping[i],
              paramAnnAry[i]);
        }
        mi.setParamInfoAry(paramInfoAry);
       
        methodInfos.add(mi);
      }
    }
    ci.setMethodList(methodInfos);

    return ci;
  }
 
  /**
   * create ContractInfo from contracts, behaviors
   * @param contracts
   * @param behaviors
   * @return
   */
  private static ContractInfo createContractInfo(List<ClassInfo> contracts,
                           List<ClassInfo> behaviors) {
   
    ContractInfo contractInfo = new ContractInfo();
    List<SessionBean> sessionBeanList = new ArrayList<SessionBean>();
    for(ClassInfo c : contracts) {
      SessionBean bean = new SessionBean();
      bean.setInterfaceClass(c);
      bean.setInterfaceName(c.getCls().getName());
      Map<String, String> implMap = new HashMap<String, String>();
     
      for(ClassInfo b : behaviors) {
        Class<?>[] interfaceAry = b.getCls().getInterfaces();
        for(Class<?> item : interfaceAry) {
          if(item == c.getCls()) {
            implMap.put(b.getLookUP(), b.getCls().getName());
            break;
          }
        }
      }
      bean.setInstanceMap(implMap);
      sessionBeanList.add(bean);
    }
   
    contractInfo.setSessionBeanList(sessionBeanList);
    return contractInfo;
  }
 
  /**
   * get all interfaces
   * @param cls
   * @return
   */
  private static List<Class<?>> getInterfaces(Class<?> cls) {
    List<Class<?>> clsList = new ArrayList<Class<?>>();
    getInterfaces(cls, clsList);
    return clsList;
  }
 
  /**
   * get all interfaces
   * @param cls
   * @param clsList
   */
  private static void getInterfaces(Class<?> cls, List<Class<?>> clsList) {
    clsList.add(cls);
    Class<?>[] aryCls = cls.getInterfaces();
   
    if(aryCls != null && aryCls.length > 0) {
      for(Class<?> c : aryCls) {
        getInterfaces(c, clsList);
      }
    }
  }
}
TOP

Related Classes of com.bj58.spat.gaea.server.deploy.bytecode.ScanClass

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.