Package org.zkoss.spring.web.context

Source Code of org.zkoss.spring.web.context.CoreContextListener

/* CoreContextListener.java

{{IS_NOTE
  Purpose:
   
  Description:
   
  History:
    Feb 26, 2011 2:57:10 PM, Created by ashish
}}IS_NOTE

Copyright (C) 2009 Potix Corporation. All Rights Reserved.

{{IS_RIGHT
  This program is distributed under GPL Version 2.0 in the hope that
  it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/

package org.zkoss.spring.web.context;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.ArrayMemberValue;
import javassist.bytecode.annotation.BooleanMemberValue;
import javassist.bytecode.annotation.EnumMemberValue;
import javassist.bytecode.annotation.MemberValue;
import javassist.bytecode.annotation.StringMemberValue;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.reflections.Reflections;
import org.reflections.ReflectionsException;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.zkoss.zk.ui.Component;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

/**
* @deprecated Please use GenericForwardComposer or SelectorComposer.
* Pre-processes Spring beans for possible auto-wiring of ZK components.<br/>
* If initial parameter 'use-urlclassloader' is true, it uses {@link java.net.URLClassLoader} to find classpath.
* Otherwise, it searches them by resource containing MANIFEST.MF.
* @author ashish, Hawk
*
*/
public class CoreContextListener implements ServletContextListener {

  private static Logger logger = Logger.getLogger(CoreContextListener.class.getName());
  /* (non-Javadoc)
   * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
   */
  public void contextInitialized(ServletContextEvent sce) {
    preprocessSpringBeansForZKComponentinjection(sce);

  }

  /* (non-Javadoc)
   * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
   */
  public void contextDestroyed(ServletContextEvent sce) {

  }
  /**
   * Scan all @Component annotations skip org.zkoss.* org.springframework.*
   * java.* pkgs Generate @Configuration classes per @Component class
   * containing methods for each ZK component injection point
   * @param sce
   */
  private void preprocessSpringBeansForZKComponentinjection(ServletContextEvent sce) {
    try {
      String webInf = sce.getServletContext().getRealPath("/WEB-INF/classes");
 
      ClassPool cp = ClassPool.getDefault();
      cp.insertClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
      cp.importPackage("java.lang");
      cp.importPackage("org.zkoss.zul");
      cp.importPackage("org.zkoss.zk.ui");
      cp.importPackage("org.zkoss.spring.util");
      cp.importPackage("org.springframework.context.annotation");
      CtClass mainClass = getZKComponentBeanMethodsClass(cp);
     
      final Set<URL> urlSet = new HashSet<URL>();
      if ("true".equalsIgnoreCase(sce.getServletContext().getInitParameter("use-urlclassloader"))){
        urlSet.addAll(getUrlsForCurrentClasspath());
      }else{
        urlSet.addAll(getClasspathUrlsByManifest());
        //above procedure doesn't ensure to obtain 'WEB-INF/classes'
        urlSet.add(ClasspathHelper.getUrlForServletContextClasses(sce.getServletContext()));
      }
      Reflections reflections = new Reflections(
          new ConfigurationBuilder().setUrls(urlSet)
          .setScanners(new FieldAnnotationsScanner()));
     
      Set<Field> fields = reflections.getFieldsAnnotatedWith(Autowired.class);
      int methodCounter = 0;
      for (Iterator<Field> iterator2 = fields.iterator(); iterator2.hasNext();) {
        Field mField = (Field) iterator2.next();
        CtClass cls = cp.get(mField.getType().getName());
        String pckgName = cls.getPackageName();
        if (Component.class.isAssignableFrom(mField.getType()) && !pckgName.endsWith("zul.api")) {
//          System.out.println("Adding @Bean method for " + mField.getName() + " of type:" + mField.getType().getName());
          // add a unique method name with @Bean("componentid")
          methodCounter = addBeanMethod(mainClass, mField, methodCounter);
        }
      }
      mainClass.writeFile(webInf);
      mainClass.toClass(Thread.currentThread().getContextClassLoader(),this.getClass().getProtectionDomain());
     
    } catch(Throwable e) {
      logger.severe(this.getClass().getName()+" is deprecated after zkspring 3.1. "+
          "Please use GenericForwardComposer or SelectorComposer.");
    }
  }
 
  /**
   * Adds a @Bean annotated method to ZKComponentBeanMethods @Configuration class
   * @param mainClass
   * @param mField
   * @param methodCounter
   * @return
   * @throws CannotCompileException
   */
  private int addBeanMethod(CtClass mainClass, Field mField, int methodCounter) throws CannotCompileException {

    CtMethod mnew = null;
    String beanType = mField.getType().getName();
    String beanName = mField.getName();
    StringBuilder sb = new StringBuilder();
    sb.append("public ");
    sb.append(beanType);
    sb.append(" m");
    sb.append(methodCounter);
    sb.append("() {");
    sb.append(beanType + " f = null;");
//    sb.append("System.out.println(\"Generating:" + beanName + "\");");
    sb.append("Component c = ZkSpringIntegrationContext.getContextComponent();");
    sb.append("if(c == null) {");
//    sb.append("return new " + beanType + "();} else {");
    sb.append("return null;} else {");
    sb.append("try {");   
   
    sb.append("f = (" + beanType + ")c.getFellow(\""
        + beanName + "\");");
//    sb.append("System.out.println(\"Got fellow:" + beanName + "\");");
    sb.append("}catch(ComponentNotFoundException e) {throw new RuntimeException(e.getMessage());}}");
   
    sb.append("return f;");
    sb.append("}");
    mnew = CtNewMethod.make(sb.toString(), mainClass);

    ConstPool cp = mnew.getMethodInfo().getConstPool();
    AnnotationsAttribute attr1 = new AnnotationsAttribute(cp,
        AnnotationsAttribute.visibleTag);
    javassist.bytecode.annotation.Annotation beanAnnotation = new javassist.bytecode.annotation.Annotation(
        "org.springframework.context.annotation.Bean", cp);
    ArrayMemberValue a = new ArrayMemberValue(cp);
    MemberValue[] m = new MemberValue[]{new StringMemberValue(beanName, cp)};
    a.setValue(m);
    beanAnnotation.addMemberValue("name", a);
    javassist.bytecode.annotation.Annotation lazyAnnotation = new javassist.bytecode.annotation.Annotation(
        "org.springframework.context.annotation.Lazy", cp);
    lazyAnnotation.addMemberValue("value", new BooleanMemberValue(true, cp));
    javassist.bytecode.annotation.Annotation scopeAnnotation = new javassist.bytecode.annotation.Annotation(
        "org.springframework.context.annotation.Scope", cp);
    EnumMemberValue enumValue = new EnumMemberValue(cp);
    enumValue.setType("org.springframework.context.annotation.ScopedProxyMode");
    enumValue.setValue("TARGET_CLASS");
    scopeAnnotation.addMemberValue("proxyMode", enumValue);
    scopeAnnotation.addMemberValue("value", new StringMemberValue("idspace", cp));
    attr1.addAnnotation(beanAnnotation);
    attr1.addAnnotation(lazyAnnotation);
    attr1.addAnnotation(scopeAnnotation);
    mnew.getMethodInfo().addAttribute(attr1);
    mnew.getMethodInfo().addAttribute(attr1);
    mnew.getMethodInfo().addAttribute(attr1);
    mainClass.addMethod(mnew);
    methodCounter += 1;
    return methodCounter;
  }


  private CtClass getZKComponentBeanMethodsClass(ClassPool cp) {
    CtClass mainClass = cp.makeClass("org.zkoss.spring.beans.zkcomponents.ZKComponentBeanMethods");
    ClassFile cFile = mainClass.getClassFile();
    ConstPool cPool = cFile.getConstPool();
    AnnotationsAttribute attr = new AnnotationsAttribute(cPool,
        AnnotationsAttribute.visibleTag);
    javassist.bytecode.annotation.Annotation configurationAnnotation = new javassist.bytecode.annotation.Annotation(
        "org.springframework.context.annotation.Configuration", cPool);
    attr.addAnnotation(configurationAnnotation);
    cFile.addAttribute(attr);
    return mainClass;
  }


  /**
   * returns list of URL paths to application jar files in WEB-INF/lib and WEB-INF/classes
   * @deprecated the class loader provided by the container might not be an instance of URLClassLoader.
   * In that case, we can't obtains those URLs as expected.
   * @return List
   */
    private List<URL> getUrlsForCurrentClasspath() {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        //is URLClassLoader?
        if (loader instanceof URLClassLoader) {
            return ImmutableList.of(((URLClassLoader) loader).getURLs());
        }

        List<URL> urls = Lists.newArrayList();

        //get from java.class.path
        String javaClassPath = System.getProperty("java.class.path");
        if (javaClassPath != null) {

            for (String path : javaClassPath.split(File.pathSeparator)) {
                try {
                    urls.add(new File(path).toURI().toURL());
                } catch (Exception e) {
                    throw new ReflectionsException("could not create url from " + path, e);
                }
            }
        }
        return urls;
    }

    /**
   * returns set of URL paths of all classpath, also considering EAR case.
   * @return Set
   */
    private Set<URL> getClasspathUrlsByManifest(){
      ClassLoader loader = Thread.currentThread().getContextClassLoader();
      Set<URL> urls = new HashSet<URL>();
      try {
      Enumeration<URL> r = loader.getResources("META-INF/MANIFEST.MF");
      while(r.hasMoreElements()){
        URL u = r.nextElement();
        String urlStr = u.toString();
        if("file".equalsIgnoreCase(u.getProtocol())){
          urlStr = urlStr.substring(0,urlStr.length()-20);
        }else if("jar".equalsIgnoreCase(u.getProtocol())){
          urlStr = urlStr.substring(4,urlStr.lastIndexOf("!"));//trim jar: and!
        }else if("zip".equalsIgnoreCase(u.getProtocol())){
          urlStr = urlStr.substring(4,urlStr.lastIndexOf("!"));//trim zip: and!
        }else{
          //ignore
          continue;
        }
       
        u = null;
        try{
          u = new URL(urlStr);
        }catch(MalformedURLException x){
          try{
            u = new URL("file:/"+urlStr);
          }catch(MalformedURLException ex){
            logger.info("Malformed: file:/"+urlStr);
          }
        }
        if(u != null){
          urls.add(u);
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return urls;
    }
}
TOP

Related Classes of org.zkoss.spring.web.context.CoreContextListener

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.