Java tutorial
/** * 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.templatecompiler.builder; import java.beans.PropertyDescriptor; import java.io.StringWriter; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.ajax4jsf.builder.config.ClassVisitor; import org.ajax4jsf.builder.config.ClassWalkingLogic; import org.ajax4jsf.builder.model.JavaPrimitive; import org.ajax4jsf.templatecompiler.elements.A4JRendererElementsFactory; import org.ajax4jsf.templatecompiler.elements.ElementsFactory; import org.ajax4jsf.templatecompiler.elements.TemplateElement; import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.velocity.VelocityContext; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; import org.w3c.dom.Node; /** * Component Beam. * * @author ayukhovich@exadel.com (latest modification by $Author: alexsmirnov $) * @version $Revision: 1.1.2.2 $ $Date: 2007/02/26 20:48:42 $ * */ public abstract class AbstractCompilationContext implements CompilationContext { private static final Log log = LogFactory.getLog(AbstractCompilationContext.class); final private static String VCPBODY = "VCPBODY"; final private static String regexComponent = "(.*)" + VCPBODY + "(.*)" + VCPBODY + "(.*)"; final private static Pattern patternComponent = Pattern.compile(regexComponent, Pattern.UNIX_LINES + Pattern.DOTALL); private final static String DEFAULT_BASE_CLASS = "org.ajax4jsf.renderkit.RendererBase"; private String packageName; private String className; private String baseClassName; private ArrayList<String> declarations; private ArrayList<String> imports; private String[] EncodeBegin; private String[] EncodeEnd; private String[] EncodeChildren; private Map<String, Map<String, PropertyDescriptor>> resolvedProperties = new HashMap<String, Map<String, PropertyDescriptor>>(); private HashMap<String, Class<?>> variables = new HashMap<String, Class<?>>(); private static String[] defaultImports = new String[] { "java.util.Iterator", "java.util.Collection", "java.util.Map", "java.io.IOException", "javax.faces.component.UIComponent", "javax.faces.context.FacesContext", "javax.faces.context.ResponseWriter", "org.ajax4jsf.renderkit.ComponentsVariableResolver", "org.ajax4jsf.renderkit.ComponentVariables" }; private TemplateElement tree; private List<ElementsFactory> elementFactories = new ArrayList<ElementsFactory>(); /** * Name of UIComponent class for this template - can be used for get properties and methods by introspection. */ private String componentClass; /** * Ant Task related classloader for loat UIComponent and Renderer classes for introspection. */ private ClassLoader classLoader; public AbstractCompilationContext() { this.baseClassName = DEFAULT_BASE_CLASS; this.declarations = new ArrayList<String>(); this.imports = new ArrayList<String>(); this.imports.addAll(Arrays.asList(defaultImports)); // Init default elements factory. this.elementFactories.add(new A4JRendererElementsFactory()); } /** * @param loader * @throws CompilationException */ public AbstractCompilationContext(ClassLoader loader) throws CompilationException { this(); this.classLoader = loader; setDefaultVariables(); } public void addElementsFactory(ElementsFactory factory) { elementFactories.add(0, factory); } /** * @param componentClass * The componentClass to set. * @throws CompilationException */ public void setComponentClass(String componentClass) throws CompilationException { this.componentClass = componentClass; addVariable("component", componentClass); } /** * set a package name */ public void setPackageName(final String packageName) { this.packageName = packageName; } /** * set a class name */ public void setClassName(final String className) { this.className = className; } /** * * @param fullClassName */ public void setFullClassName(final String fullClassName) { int dotIndex = fullClassName.lastIndexOf("."); String tempPackageName = ""; String tempClassName = fullClassName; if (dotIndex != -1) { tempPackageName = fullClassName.substring(0, dotIndex); tempClassName = fullClassName.substring(dotIndex + 1); } // if setPackageName(tempPackageName); setClassName(tempClassName); } public void setBaseclass(String baseclassName) throws CompilationException { this.baseClassName = baseclassName; addVariable("this", baseclassName); } // ------ /** * @return package name */ public String getPackageName() { return this.packageName; } /** * @return base class package name */ public String getBaseclassPackageName() { String packageName = null; int dotIndex = this.baseClassName.lastIndexOf("."); if (dotIndex != -1) { packageName = this.baseClassName.substring(0, dotIndex); } return packageName; } /** * @return class name */ public String getClassName() { return this.className; } /** * @return base class package name */ public String getBaseclassName() { String className = null; if ((this.baseClassName != null) && (this.baseClassName.length() != 0)) { int dotIndex = this.baseClassName.lastIndexOf("."); if (dotIndex != -1) { className = this.baseClassName.substring(dotIndex + 1); } else { className = this.baseClassName; } } return className; } /** * @return full class name with package name */ public String getFullClassName() { StringBuffer buf = new StringBuffer(); if ((this.packageName != null) && (this.packageName.length() != 0)) { buf.append(this.packageName); buf.append('.'); } buf.append(this.className); return buf.toString(); } /** * @return base class package name */ public String getFullBaseclass() { return this.baseClassName; } /** * @return */ public String getComponentFileName() { return getFullClassName().replace('.', '/'); } /** * @return Returns the componentClass. */ public String getComponentClass() { String returnStr = this.componentClass; // if ( (componentClass != null) && ( ! // componentClass.endsWith(".class")) ) { // returnStr = componentClass + ".class"; // } return returnStr; } /** * return class loader */ public ClassLoader getClassLoader() { return this.classLoader; } /** * @return string array contain declarations */ public String[] getDeclarations() { return this.declarations.toArray(new String[0]); } /** * @return string array contain declarations */ public String[] getImports() { return this.imports.toArray(new String[0]); } public void addToImport(String className) { this.imports.add(className); } public void addToDeclaration(String declaration) { this.declarations.add(declaration); } /** * Add variable with type String * * @param variableName * @throws CompilationException */ public void addVariable(String variableName) throws CompilationException { addVariable(variableName, "java.lang.String"); } public void addVariable(String variableName, Class<?> clazz) { this.variables.put(variableName, clazz); } public void addVariable(String variableName, String typeName) throws CompilationException { try { Class<?> clazz = loadClass(typeName); this.variables.put(variableName, clazz); } catch (ClassNotFoundException e) { // error("Error create variable "+variableName+" with type "+typeName, e); throw new CompilationException( "Error create renderer variable " + variableName + " with type " + typeName, e); } } public boolean containsVariable(String variableName) { return this.variables.containsKey(variableName); } public Class<?> getVariableType(String variableName) { return this.variables.get(variableName); } public Class<?> loadClass(String className) throws ClassNotFoundException { Class<?> clazz = null; try { if (JavaPrimitive.isPrimitive(className)) { clazz = JavaPrimitive.forName(className); } else { clazz = this.classLoader.loadClass(className); } } catch (ClassNotFoundException e) { throw e; } catch (Throwable e) { log.error(e.getLocalizedMessage(), e); } if (null == clazz) { throw new ClassNotFoundException(className); } return clazz; } public void setDefaultVariables() throws CompilationException { addVariable("component", "javax.faces.component.UIComponent"); addVariable("context", "javax.faces.context.FacesContext"); addVariable("writer", "javax.faces.context.ResponseWriter"); // addLocalVariable("component", "javax.faces.component.UIComponent" ); addVariable("variables", "org.ajax4jsf.renderkit.ComponentVariables"); } public Class<?> getMethodReturnedClass(Class<?> clazz, String methodName, Class<?>[] parametersTypes) throws NoSuchMethodException { Class<?> returnedType = null; log.debug("class : " + clazz.getName() + "\n\t method : " + methodName + "\n\t paramTypes : " + Arrays.asList(parametersTypes).toString()); Method method = MethodUtils.getMatchingAccessibleMethod(clazz, methodName, parametersTypes); if (null != method) { returnedType = method.getReturnType(); log.debug("Method found, return type : " + returnedType.getName()); return returnedType; } else { throw new NoSuchMethodException( clazz + "#" + methodName + "(" + Arrays.toString(parametersTypes) + ")"); } } public PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName) { Map<String, PropertyDescriptor> descriptors = resolvedProperties.get(clazz.getName()); if (descriptors == null) { descriptors = resolveProperties(clazz); resolvedProperties.put(clazz.getName(), descriptors); } return descriptors.get(propertyName); } private Map<String, PropertyDescriptor> resolveProperties(Class<?> clazz) { final Map<String, PropertyDescriptor> descriptors = new HashMap<String, PropertyDescriptor>(); new ClassWalkingLogic(clazz).walk(new ClassVisitor() { public void visit(Class<?> clazz) { PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(clazz); for (PropertyDescriptor descriptor : pds) { descriptors.put(descriptor.getName(), descriptor); } } }); return descriptors; } /** * */ public String[] getEncodeBegin() { return this.EncodeBegin; } /** * */ public String[] getEncodeChild() { return this.EncodeChildren; } /** * */ public String[] getEncodeEnd() { return this.EncodeEnd; } public void setCode(String code) { Matcher matcher = patternComponent.matcher(code); String strEncodeBegin; String strEncodeChildren; String strEncodeEnd; if (matcher.find()) { strEncodeBegin = matcher.group(1); strEncodeChildren = matcher.group(2); strEncodeEnd = matcher.group(3); } else { strEncodeBegin = ""; strEncodeChildren = ""; strEncodeEnd = code; } if ((strEncodeBegin != null) && (strEncodeBegin.length() != 0)) { this.EncodeBegin = strEncodeBegin.split(";\n"); } if ((strEncodeChildren != null) && (strEncodeChildren.length() != 0)) { this.EncodeChildren = strEncodeChildren.split(";\n"); } if ((strEncodeEnd != null) && (strEncodeEnd.length() != 0)) { this.EncodeEnd = strEncodeEnd.split(";\n"); } } /** * @return the tree */ public TemplateElement getTree() { return this.tree; } /** * @param tree the tree to set */ public void setTree(TemplateElement tree) { this.tree = tree; } /* (non-Javadoc) * @see org.ajax4jsf.templatecompiler.builder.CompilationContext#getProcessor(org.w3c.dom.Node) */ public TemplateElement getProcessor(Node nodeElement) throws CompilationException { for (Iterator<ElementsFactory> iter = elementFactories.listIterator(); iter.hasNext();) { ElementsFactory factory = iter.next(); TemplateElement processor = factory.getProcessor(nodeElement, this); if (null != processor) { return processor; } } return null; } /* (non-Javadoc) * @see org.ajax4jsf.templatecompiler.builder.CompilationContext#processTemplate(java.lang.String, org.apache.velocity.VelocityContext) */ public String processTemplate(String name, VelocityContext context) throws CompilationException { StringWriter out = new StringWriter(); try { getTemplate(name).merge(context, out); } catch (ResourceNotFoundException e) { throw new CompilationException(e.getLocalizedMessage()); } catch (ParseErrorException e) { throw new CompilationException(e.getLocalizedMessage()); } catch (Exception e) { throw new CompilationException(e.getLocalizedMessage()); } return out.toString(); } public Map<String, Map<String, PropertyDescriptor>> getResolvedProperties() { return resolvedProperties; } }