Package org.ajax4jsf.builder.generator

Source Code of org.ajax4jsf.builder.generator.GetResourceInterceptor

/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/

package org.ajax4jsf.builder.generator;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.ajax4jsf.builder.config.BuilderConfig;
import org.ajax4jsf.builder.config.ComponentBean;
import org.ajax4jsf.builder.config.RendererBean;
import org.ajax4jsf.builder.config.TagBean;
import org.ajax4jsf.builder.config.TagHandlerBean;
import org.ajax4jsf.templatecompiler.builder.CompilationContext;
import org.ajax4jsf.templatecompiler.builder.CompilationException;
import org.ajax4jsf.templatecompiler.builder.TemplateCompiler;
import org.ajax4jsf.templatecompiler.elements.RootElement;
import org.ajax4jsf.templatecompiler.elements.TemplateElement;
import org.ajax4jsf.templatecompiler.elements.vcp.FResourceTemplateElement;
import org.ajax4jsf.templatecompiler.elements.vcp.HeaderResourceElement;
import org.ajax4jsf.templatecompiler.elements.vcp.HeaderScriptsElement;
import org.ajax4jsf.templatecompiler.elements.vcp.HeaderStylesElement;

/**
* @author Nick Belaevski
* @since 3.3.0
*/
public class ResourcesConfigParser {

  private JSFGeneratorConfiguration config;

  private Logger log;

  private File templates;
 
  private ResourcesConfigGeneratorBean resourcesConfigGeneratorBean;
 
  private Map<String, ResourcesConfigGeneratorBean> componentResourcesMap;
 
  public ResourcesConfigParser(JSFGeneratorConfiguration config, Logger log) {
    super();

    this.config = config;
    this.log = log;
    this.resourcesConfigGeneratorBean = new ResourcesConfigGeneratorBean();
    this.componentResourcesMap = new HashMap<String, ResourcesConfigGeneratorBean>();
  }

  public File getTemplates() {
    return templates;
  }
 
  public void setTemplates(File templates) {
    this.templates = templates;
  }
 
  private void addResources(ResourcesConfigGeneratorBean configBean,
      TemplateElement templateElement, String packageName,
      RendererBean renderer, BuilderConfig builderConfig)
      throws ClassNotFoundException {
    if (templateElement instanceof FResourceTemplateElement) {
      FResourceTemplateElement resourceTemplateElement = (FResourceTemplateElement) templateElement;
      String name = resourceTemplateElement.getName();

      configBean.addResource(name, packageName, null, true);
    } else if (templateElement instanceof RootElement) {
      RootElement rootElement = (RootElement) templateElement;

      CompilationContext compilationContext = rootElement
          .getComponentBean();

      addResource(configBean, renderer, builderConfig, compilationContext);
    } else if (templateElement instanceof HeaderResourceElement) {
      HeaderResourceElement resourceElement = (HeaderResourceElement) templateElement;

      ResourceType type = null;
      if (templateElement instanceof HeaderScriptsElement) {
        type = ResourceType.SCRIPT;
      } else if (templateElement instanceof HeaderStylesElement) {
        type = ResourceType.STYLE;
      }

      String[] paths = resourceElement.getResourcePaths();
      if (paths != null) {
        for (int i = 0; i < paths.length; i++) {
          String string = paths[i];

          configBean.addResource(string, packageName, type, false);
        }
      }
    }

    ArrayList<TemplateElement> subElements = templateElement
        .getSubElements();
    for (TemplateElement element : subElements) {
      addResources(configBean, element, packageName, renderer,
          builderConfig);
    }
  }

  private String getResourceKey(String packageName, Object resource) {
    try {
      Class<? extends Object> resourceClass = resource.getClass();
      Method method = resourceClass.getMethod("getKey");
      String resourceKey = (String) method.invoke(resource);
     
      if (resourceKey != null && !resourceKey.equals(resourceClass.getName())) {
        ClassLoader loader = config.getClassLoader();

        if (loader.getResource(resourceKey) == null) {
          String packagePath = packageName.replace('.', '/');
          if (packagePath.length() != 0) {
            packagePath += "/";
          }
         
          if (loader.getResource(packagePath + resourceKey) == null) {
            resourceKey = null;
          }
        } else {
          if (!resourceKey.startsWith("/")) {
            resourceKey = "/" + resourceKey;
          }
        }
      }
     
      return resourceKey;
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }

    return null;
  }
 
  private String addResource(ResourcesConfigGeneratorBean configBean,
      RendererBean renderer, BuilderConfig builderConfig,
      CompilationContext compilationContext)
      throws ClassNotFoundException {
    String packageName;
    String classname = renderer.getClassname();
    int idx = classname.lastIndexOf('.');
    if (idx != -1) {
      packageName = classname.substring(0, idx);
    } else {
      packageName = "";
    }

    ClassLoader loader = builderConfig.getLoader();
    Class<?> cl = null;

    try {
      cl = loader.loadClass(classname);
    } catch (ClassNotFoundException e) {
      String superclass = compilationContext.getBaseclassPackageName()
          + "." + compilationContext.getBaseclassName();
      if (superclass != null) {
        cl = loader.loadClass(superclass);
      }
    }

    if (cl != null) {
      try {
        GetResourceInterceptor interceptor = new GetResourceInterceptor(builderConfig.getLoader());

        Object instance = AbstractClassStubBuilder.buildStub(cl,
            interceptor, builderConfig.getLoader());

        //clear list - some resources could be requested during class/instance initialization
        Object[] result = null;
        Method method = null;
        Set<String> locatedResources = new HashSet<String>();
       
        Class<?> cl1 = instance.getClass();
        while (cl1 != null && method == null) {
          try {
            method = cl1.getDeclaredMethod("getStyles");
          } catch (NoSuchMethodException e) {
            cl1 = cl1.getSuperclass();
          }
        }

        if (method != null) {
          method.setAccessible(true);
          result = (Object[]) method.invoke(instance);
          if (result instanceof Object[]) {
            for (Object object : result) {
              String resourceName = interceptor.getResourceName(object);

              if (resourceName == null) {
                resourceName = getResourceKey(packageName, object);
              }
             
              if (resourceName != null) {
                locatedResources.add(resourceName);
                configBean.addResource(resourceName, packageName, ResourceType.STYLE,
                    false);
              }
            }
          }
        }

        method = null;
        cl1 = instance.getClass();
        while (cl1 != null && method == null) {
          try {
            method = cl1.getDeclaredMethod("getScripts");
          } catch (NoSuchMethodException e) {
            cl1 = cl1.getSuperclass();
          }
        }

        if (method != null) {
          method.setAccessible(true);
          result = (Object[]) method.invoke(instance);
          if (result instanceof Object[]) {
            for (Object object : result) {
              String resourceName = interceptor.getResourceName(object);

              if (resourceName == null) {
                resourceName = getResourceKey(packageName, object);
              }
             
              if (resourceName != null) {
                locatedResources.add(resourceName);
                configBean.addResource(resourceName, packageName, ResourceType.SCRIPT,
                    false);
              }
            }
          }

          List<String> list = interceptor.getList();
          if (list != null) {
            list.removeAll(locatedResources);
            for (String resourceName : list) {
              log.warn("Error detecting resource type: " + resourceName);
              configBean.addResource(resourceName, packageName, null,
                  false);
            }
          }
        }
      } catch (SecurityException e) {
        builderConfig.getLog().error(e.getMessage(), e);
      } catch (IllegalArgumentException e) {
        builderConfig.getLog().error(e.getMessage(), e);
      } catch (IllegalAccessException e) {
        builderConfig.getLog().error(e.getMessage(), e);
      } catch (InvocationTargetException e) {
        builderConfig.getLog().error(e.getMessage(), e);
      }
    }
    return packageName;
  }

  private void addResources(ResourcesConfigGeneratorBean configBean,
      RendererBean renderer, BuilderConfig builderConfig)
      throws CompilationException, IOException, ClassNotFoundException {
    if (null != renderer) {
      CompilationContext compilationContext = new RendererCompilationContext(
          log, config.getClassLoader(), config);

      if (renderer.isGenerate()) {
        String templateString = renderer.getTemplate();
        if (templateString != null) {
          File template;
          if (null != getTemplates()) {
            template = new File(getTemplates(), templateString);
          } else {
            template = new File(templateString);
          }

          TemplateCompiler templateCompiler = new TemplateCompiler();
          InputStream templateStream = new FileInputStream(template);
          templateCompiler.processing(templateStream,
              compilationContext);

          TemplateElement root = compilationContext.getTree();

          String classname = renderer.getClassname();
          String packageName;
          int idx = classname.lastIndexOf('.');
          if (idx != -1) {
            packageName = classname.substring(0, idx);
          } else {
            packageName = "";
          }

          addResources(configBean, root, packageName, renderer,
              builderConfig);
        }
      } else {
        addResource(configBean, renderer, builderConfig,
            compilationContext);
      }
    }
  }

  public void parse(BuilderConfig config) throws CompilationException, IOException, ClassNotFoundException {
    List<ComponentBean> components = config.getComponents();
    for (ComponentBean componentBean : components) {
      ResourcesConfigGeneratorBean localBeanInstance = new ResourcesConfigGeneratorBean();
      RendererBean rendererBean = componentBean.getRenderer();

      addResources(localBeanInstance, rendererBean, config);

      String componentName = null;
     
      TagBean tag = componentBean.getTag();
      if (tag != null) {
        componentName = tag.getName();
      }
     
      if (componentName == null) {
        TagHandlerBean taghandler = componentBean.getTaghandler();
        if (taghandler != null) {
          componentName = taghandler.getName();
        }
      }
     
      if (componentName != null) {
        this.componentResourcesMap.put(componentName, localBeanInstance);
      }

      this.resourcesConfigGeneratorBean.merge(localBeanInstance);
    }

    List<RendererBean> renderers = config.getRenderers();
    for (RendererBean rendererBean : renderers) {
      addResources(this.resourcesConfigGeneratorBean, rendererBean, config);
    }
  }
 
  public ResourcesConfigGeneratorBean getResourcesConfigGeneratorBean() {
    return resourcesConfigGeneratorBean;
  }
 
  public Map<String, ResourcesConfigGeneratorBean> getComponentResourcesMap() {
    return componentResourcesMap;
  }
}

class GetResourceInterceptor implements MethodInterceptor {

  private static final Class<?>[] SIGNATURE = new Class<?>[] { String.class };

  private ClassLoader classLoader;
 
  private List<String> list = new ArrayList<String>();

  private Map<String, Object> resources = new HashMap<String, Object>();
 
  private Map<Object, String> resourcesInverse = new IdentityHashMap<Object, String>();

  public GetResourceInterceptor(ClassLoader loader) {
    this.classLoader = loader;
  }

  public List<String> getList() {
    return list;
  }
 
  public String getResourceName(Object resource) {
    return resourcesInverse.get(resource);
  }

  public void clearList() {
    list.clear();
  }

  public Object intercept(Object instance, Method method, Object[] args,
      MethodProxy methodProxy) throws Throwable {

    if ("getResource".equals(method.getName())
        && Arrays.equals(SIGNATURE, method.getParameterTypes())) {

      String resourceName = (String) args[0];
      list.add(resourceName);

      Object resource = resources.get(resourceName);
      if (resource == null) {
        Class<?> returnType = method.getReturnType();
        if (returnType.isInterface()) {
          Object interfaceStub = AbstractClassStubBuilder.buildInterfaceStub(returnType, classLoader);
          resources.put(resourceName, interfaceStub);
          resourcesInverse.put(interfaceStub, resourceName);
       
          return interfaceStub;
        }
      }
     
      return null;
    } else {
      return methodProxy.invokeSuper(instance, args);
    }
  }

}
TOP

Related Classes of org.ajax4jsf.builder.generator.GetResourceInterceptor

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.