Package org.zkoss.cdi.weld.spi

Source Code of org.zkoss.cdi.weld.spi.ZKWeldExtension

/* ZKWeldExtension.java
{{IS_NOTE
  Purpose:
   
  Description:
   
  History:
    Dec 31, 2009 7:53:34 PM, Created by henrichen
}}IS_NOTE

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

*/
package org.zkoss.cdi.weld.spi;

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

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.StringMemberValue;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;

import org.jboss.weld.manager.BeanManagerImpl;
import org.reflections.Reflections;
import org.reflections.ReflectionsException;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.util.ConfigurationBuilder;
import org.zkoss.cdi.inject.ComponentId;
import org.zkoss.cdi.weld.Version;
import org.zkoss.cdi.weld.context.ComponentContext;
import org.zkoss.cdi.weld.context.DesktopContext;
import org.zkoss.cdi.weld.context.ExecutionContext;
import org.zkoss.cdi.weld.context.IdSpaceContext;
import org.zkoss.cdi.weld.context.PageContext;
import org.zkoss.util.logging.Log;
import org.zkoss.zk.ui.Component;

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

/**
* ZK Weld Extension service provider.
* @author henrichen
*
*/
public class ZKWeldExtension implements Extension {
 
  private static final Log log = Log.lookup(ZKWeldExtension.class);
 
  /* Map holding auto generated producer method ids (method return type + injection point member name */
  private static Set<String> producerMethodKeys = new HashSet<String>();
 
  /**
   * Container lifecycle callback method to pre-process Composer classes to auto generate
   * producer methods for ZK components injected in Composer classes.
   * @param event
   * @param manager
   */
  @SuppressWarnings({ "deprecation", "unchecked" })
  public void beforeBeanDiscovery(@Observes BeforeBeanDiscovery event, BeanManager manager) throws RuntimeException {
    try {
      ClassPool cp = ClassPool.getDefault();
      cp.insertClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
      cp.importPackage("org.zkoss.zul");
      cp.importPackage("org.zkoss.zk.ui");
      cp.importPackage("org.zkoss.cdi.util");
     
      CtClass mainclas = cp.makeClass("org.zkoss.zkplus.cdi.ZKComponentProducerMethods");
      final List<URL> l = getUrlsForCurrentClasspath();
     
      Reflections reflections = new Reflections(
          new ConfigurationBuilder().setUrls(l)
          .setScanners(new FieldAnnotationsScanner()));
     
      Set<Field> fields = reflections.getFieldsAnnotatedWith(ComponentId.class);
      for (Iterator iterator2 = fields.iterator(); iterator2
          .hasNext();) {
        Field field = (Field) iterator2.next();
        CtClass cls = cp.get(field.getType().getName());
        String pckgName = cls.getPackageName();
        if (Component.class.isAssignableFrom(field.getType()) || !pckgName.endsWith("zul.api")) {
          addProducerMethod(field, mainclas);
        }
      }
      Class c = mainclas.toClass(Thread.currentThread().getContextClassLoader(), this.getClass().getProtectionDomain());

      // This will register dynamically generated ZKComponentProducerMethods class as a bean in turn all producer methods
      // inside this class will be used for resolving injection points
      event.addAnnotatedType(((BeanManagerImpl)manager).createAnnotatedType(c));

    } catch (NotFoundException e) {
      log.debug("Unexpected error in ZK Extension: " + e.getMessage());
      throw new RuntimeException(e);
    } catch (ClassNotFoundException e) {
      log.debug("Unexpected error in ZK Extension: " + e.getMessage());
      throw new RuntimeException(e);
    } catch (CannotCompileException e) {
      log.debug("Unexpected error in ZK Extension: " + e.getMessage());
      e.printStackTrace();
      throw new RuntimeException(new Exception("Error while pre-processing ZK component injection point(s)"));
    } catch (IOException e) {
      log.debug("Unexpected error in ZK Extension: " + e.getMessage());
      throw new RuntimeException(e);
    } catch(Exception e) {
      log.debug("Unexpected error in ZK Extension: " + e.getMessage());
      throw new RuntimeException(e);
    }
  }
 
  /**
   * returns list of URL paths to application jar files in WEB-INF/lib and WEB-INF/classes
   * @return List
   */
    public 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;
    }

  /**
   * Adds ZK custom contexts such as Desktop, Page, IdSpace, Component and Execution
   * @param event
   * @param manager
   */
  public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager manager) {
    //register ZK contexts
    event.addContext(new DesktopContext());
    event.addContext(new PageContext());
    event.addContext(new IdSpaceContext());
    event.addContext(new ComponentContext());
    event.addContext(new ExecutionContext());
    log.info("ZK Weld Extension "+Version.UID);
  }
 
  /**
   * Adds new producer method for deployment time resolution of ZK component injection points
   * @param field
   * @param mainClass
   * @param beanclas
   * @throws ClassNotFoundException
   * @throws CannotCompileException
   * @throws IOException
   * @throws NotFoundException
   */
  private void addProducerMethod(Field field, CtClass mainClass) throws ClassNotFoundException,
      CannotCompileException, NotFoundException, IOException {

    CtMethod mnew = null;
    String injectedFieldType = field.getType().getName();
    String injectedFieldName = field.getName();
    if (producerMethodKeys.contains(injectedFieldType + injectedFieldName)) {
      return;
    } else {
      producerMethodKeys.add(injectedFieldType + injectedFieldName);
    }
    // construct producer method body
    StringBuilder sb = new StringBuilder();
    sb.append("public ");
    sb.append(injectedFieldType);
    sb.append(" get");
    sb.append(injectedFieldName);
    sb.append("() {");
    sb.append(injectedFieldType + " f = null;");
    sb.append("Component c = ZkCDIIntegrationContext.getContextComponent();");
//    sb.append("System.out.println(\"Current thread id = \" + Thread.currentThread().getId());");
    sb.append("if(c == null) {");
//    sb.append("System.out.println(\"returning dummy instance of " + injectedFieldType + "\");");
    sb.append("return new " + injectedFieldType + "();} else {");
//    sb.append("System.out.println(\"returning component retrieved from component tree\" + c);");
   
    sb.append("try {");   
   
    sb.append("f = (" + injectedFieldType + ")c.getFellow(\""
        + injectedFieldName + "\");");
//     sb.append("System.out.println(\"returning component retrieved from component tree\" + f);");
   
    sb.append("}catch(ComponentNotFoundException e) {e.printStackTrace(); throw new RuntimeException(e.getMessage());}}");
   
    sb.append("return f;");
    sb.append("}");
    mnew = CtNewMethod.make(sb.toString(), mainClass);

    ConstPool cp = mnew.getMethodInfo().getConstPool();
    AnnotationsAttribute attr = new AnnotationsAttribute(cp,
        AnnotationsAttribute.visibleTag);

    javassist.bytecode.annotation.Annotation producesAnnotation = new javassist.bytecode.annotation.Annotation(
        "javax.enterprise.inject.Produces", cp);
    javassist.bytecode.annotation.Annotation zkScopedAnnotation = new javassist.bytecode.annotation.Annotation(
        "org.zkoss.cdi.context.IdSpaceScoped", cp);
    javassist.bytecode.annotation.Annotation zkCompAnnotation = new javassist.bytecode.annotation.Annotation(
        "org.zkoss.cdi.inject.ComponentId", cp);
    zkCompAnnotation.addMemberValue("value", new StringMemberValue(field
        .getName(), cp));
   
    attr.addAnnotation(producesAnnotation);
    attr.addAnnotation(zkScopedAnnotation);
    attr.addAnnotation(zkCompAnnotation);
    mnew.getMethodInfo().addAttribute(attr);
   
    mainClass.addMethod(mnew);
  }

 
}
TOP

Related Classes of org.zkoss.cdi.weld.spi.ZKWeldExtension

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.