Package httl.spi.translators

Source Code of httl.spi.translators.CompiledTranslator

/*
* Copyright 2011-2013 HTTL Team.
* Licensed 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 httl.spi.translators;

import httl.Engine;
import httl.Node;
import httl.Resource;
import httl.Template;
import httl.spi.Compiler;
import httl.spi.Converter;
import httl.spi.Filter;
import httl.spi.Formatter;
import httl.spi.Interceptor;
import httl.spi.Logger;
import httl.spi.Switcher;
import httl.spi.Translator;
import httl.spi.translators.templates.AdaptiveTemplate;
import httl.spi.translators.templates.CompiledTemplate;
import httl.spi.translators.templates.CompiledVisitor;
import httl.util.ClassUtils;
import httl.util.StringSequence;
import httl.util.StringUtils;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
* CompiledTranslator. (SPI, Singleton, ThreadSafe)
*
* @see httl.spi.engines.DefaultEngine#setTranslator(Translator)
*
* @author @author Liang Fei (liangfei0201 AT gmail DOT com)
*/
public class CompiledTranslator implements Translator {

  private String[] forVariable;

  private String filterVariable;

  private String formatterVariable;

  private String defaultFilterVariable;
 
  private String defaultFormatterVariable;

  private Engine engine;

  private Compiler compiler;
 
  private Interceptor interceptor;
 
  private Logger logger;
 
  public void setLogger(Logger logger) {
    this.logger = logger;
  }

  private Switcher<Filter> textFilterSwitcher;

  private Switcher<Filter> valueFilterSwitcher;

  private Switcher<Formatter<Object>> formatterSwitcher;

  private Filter textFilter;

  private Filter valueFilter;
 
  private Converter<Object, Object> mapConverter;

  private Converter<Object, Object> outConverter;

  private Formatter<Object> formatter;

  private String[] importMacros;
  
  private final Map<String, Template> importMacroTemplates = new ConcurrentHashMap<String, Template>();

  private String[] importPackages;

  private Set<String> importPackageSet;

  private String[] importVariables;

  private Map<String, Class<?>> importTypes;

  private final Map<Class<?>, Object> functions = new ConcurrentHashMap<Class<?>, Object>();

  private final List<StringSequence> sequences = new CopyOnWriteArrayList<StringSequence>();

  private static final String TEMPLATE_CLASS_PREFIX = CompiledTemplate.class.getPackage().getName() + ".Template_";
 
  private boolean isOutputStream;

  private boolean isOutputWriter;

  private boolean sourceInClass;

  private boolean textInClass;
 
  private String outputEncoding;
 
  private Class<?> defaultVariableType;

  private String engineName;

  private String[] importSizers;

  private String[] importGetters;

  /**
   * httl.properties: import.sizers=size,length,getSize,getLength
   */
  public void setImportSizers(String[] importSizers) {
    this.importSizers = importSizers;
  }

  /**
   * httl.properties: import.getters=get,getProperty,getAttribute
   */
  public void setImportGetters(String[] importGetters) {
    this.importGetters = importGetters;
  }

  /**
   * httl.properties: default.variable.type=java.lang.Object
   */
  public void setDefaultVariableType(String defaultVariableType) {
    this.defaultVariableType = ClassUtils.forName(defaultVariableType);
  }

  /**
   * httl.properties: import.macros=common.httl
   */
  public void setImportMacros(String[] importMacros) {
    this.importMacros = importMacros;
  }

  /**
   * httl.properties: output.encoding=UTF-8
   */
  public void setOutputEncoding(String outputEncoding) {
    this.outputEncoding = outputEncoding;
  }

  private static final String HTTL_DEFAULT = "httl.properties";

  private static final String HTTL_PREFIX = "httl-";

  private static final String PROPERTIES_SUFFIX = ".properties";

  /**
   * httl.properties: engine=httl.spi.engines.DefaultEngine
   */
  public void setEngine(Engine engine) {
    this.engine = engine;
  }

  /**
   * httl.properties: engine.name=httl.properties
   */
  public void setEngineName(String name) {
    if (HTTL_DEFAULT.equals(name)) {
      name = "";
    } else {
      if (name.startsWith(HTTL_PREFIX)) {
        name = name.substring(HTTL_PREFIX.length());
      }
      if (name.endsWith(PROPERTIES_SUFFIX)) {
        name = name.substring(0, name.length() - PROPERTIES_SUFFIX.length());
      }
    }
    this.engineName = name;
  }

  /**
   * httl.properties: compiler=httl.spi.compilers.JdkCompiler
   */
  public void setCompiler(Compiler compiler) {
    this.compiler = compiler;
  }

  /**
   * httl.properties: interceptors=httl.spi.interceptors.ExtendsInterceptor
   */
  public void setInterceptor(Interceptor interceptor) {
    this.interceptor = interceptor;
  }

  /**
   * httl.properties: text.filter.switchers=httl.spi.switchers.JavaScriptFilterSwitcher
   */
  public void setTextFilterSwitcher(Switcher<Filter> textFilterSwitcher) {
    this.textFilterSwitcher = textFilterSwitcher;
  }

  /**
   * httl.properties: value.filter.switchers=httl.spi.switchers.JavaScriptFilterSwitcher
   */
  public void setValueFilterSwitcher(Switcher<Filter> valueFilterSwitcher) {
    this.valueFilterSwitcher = valueFilterSwitcher;
  }

  /**
   * httl.properties: formatter.switchers=httl.spi.switchers.NumberFormatterSwitcher
   */
  public void setFormatterSwitcher(Switcher<Formatter<Object>> formatterSwitcher) {
    this.formatterSwitcher = formatterSwitcher;
  }

  /**
   * httl.properties: text.filters=httl.spi.filters.CompressBlankFilter
   */
  public void setTextFilter(Filter filter) {
    this.textFilter = filter;
  }

  /**
   * httl.properties: value.filters=httl.spi.filters.EscapeXmlFilter
   */
  public void setValueFilter(Filter filter) {
    this.valueFilter = filter;
  }

  /**
   * httl.properties: map.converters=httl.spi.converters.BeanMapConverter
   */
  public void setMapConverter(Converter<Object, Object> mapConverter) {
    this.mapConverter = mapConverter;
  }

  /**
   * httl.properties: out.converters=httl.spi.converters.ResponseOutConverter
   */
  public void setOutConverter(Converter<Object, Object> outConverter) {
    this.outConverter = outConverter;
  }

  /**
   * httl.properties: formatters=httl.spi.formatters.DateFormatter
   */
  public void setFormatter(Formatter<Object> formatter) {
    this.formatter = formatter;
  }

  /**
   * httl.properties: output.stream=true
   */
  public void setOutputStream(boolean outputStream) {
    this.isOutputStream = outputStream;
  }

  /**
   * httl.properties: output.writer=true
   */
  public void setOutputWriter(boolean outputWriter) {
    this.isOutputWriter = outputWriter;
  }

  /**
   * httl.properties: source.in.class=false
   */
  public void setSourceInClass(boolean sourceInClass) {
    this.sourceInClass = sourceInClass;
  }

  /**
   * httl.properties: text.in.class=false
   */
  public void setTextInClass(boolean textInClass) {
    this.textInClass = textInClass;
  }

  /**
   * httl.properties: for.variable=for
   */
  public void setForVariable(String[] forVariable) {
    this.forVariable = forVariable;
  }
 
  /**
   * httl.properties: filter.variable=filter
   */
  public void setFilterVariable(String filterVariable) {
    this.filterVariable = filterVariable;
  }

  /**
   * httl.properties: formatter.variable=formatter
   */
  public void setFormatterVariable(String formatterVariable) {
    this.formatterVariable = formatterVariable;
  }

  /**
   * httl.properties: import.packages=java.util
   */
  public void setImportPackages(String[] importPackages) {
    this.importPackages = importPackages;
    this.importPackageSet = new HashSet<String>(Arrays.asList(importPackages));
  }

  /**
   * httl.properties: import.setVariables=javax.servlet.http.HttpServletRequest request
   */
  public void setImportVariables(String[] importVariables) {
    this.importVariables = importVariables;
  }

  /**
   * httl.properties: import.methods=java.lang.Math
   */
  public void setImportMethods(Object[] importMethods) {
    for (Object function : importMethods) {
      if (function instanceof Class) {
        this.functions.put((Class<?>) function, function);
      } else {
        this.functions.put(function.getClass(), function);
      }
    }
  }

  /**
   * httl.properties: import.sequences=Mon Tue Wed Thu Fri Sat Sun Mon
   */
  public void setImportSequences(String[] sequences) {
    for (String s : sequences) {
      s = s.trim();
      if (s.length() > 0) {
        String[] ts = s.split("\\s+");
        List<String> sequence = new ArrayList<String>();
        for (String t : ts) {
          t = t.trim();
          if (t.length() > 0) {
            sequence.add(t);
          }
        }
        this.sequences.add(new StringSequence(sequence));
      }
    }
  }

  /**
   * init.
   */
  public void init() {
    defaultFilterVariable = "$" + filterVariable;
    defaultFormatterVariable = "$" + formatterVariable;
    if (importVariables != null && importVariables.length > 0) {
      this.importTypes = new HashMap<String, Class<?>>();
      for (String var : importVariables) {
        int i = var.lastIndexOf(' ');
        if (i < 0) {
          throw new IllegalArgumentException("Illegal config import.setVariables");
        }
        this.importTypes.put(var.substring(i + 1), ClassUtils.forName(importPackages, var.substring(0, i)));
      }
    }
  }

  /**
   * inited.
   */
  public void inited() {
    if (importMacros != null && importMacros.length > 0) {
      for (String importMacro : importMacros) {
        try {
          Template importMacroTemplate = engine.getTemplate(importMacro);
          importMacroTemplates.putAll(importMacroTemplate.getMacros());
        } catch (Exception e) {
          throw new IllegalStateException(e.getMessage(), e);
        }
      }
    }
  }

  public Template translate(Resource resource, Node root, Map<String, Class<?>> defVariableTypes) throws IOException, ParseException {
    if (logger != null && logger.isDebugEnabled()) {
      logger.debug("Compile template " + resource.getName());
    }
    try {
      Template writerTemplate = null;
      Template streamTemplate = null;
      if (isOutputWriter || ! isOutputStream) {
        Class<?> clazz = parseClass(resource, root, defVariableTypes, false, 0);
        writerTemplate = (Template) clazz.getConstructor(Engine.class, Interceptor.class, Compiler.class, Switcher.class, Switcher.class, Filter.class, Formatter.class, Converter.class, Converter.class, Map.class, Map.class, Resource.class, Template.class, Node.class)
            .newInstance(engine, interceptor, compiler, valueFilterSwitcher, formatterSwitcher, valueFilter, formatter, mapConverter, outConverter, functions, importMacroTemplates, resource, null, root);
      }
      if (isOutputStream) {
        Class<?> clazz = parseClass(resource, root, defVariableTypes, true, 0);
        streamTemplate = (Template) clazz.getConstructor(Engine.class, Interceptor.class, Compiler.class, Switcher.class, Switcher.class, Filter.class, Formatter.class, Converter.class, Converter.class, Map.class, Map.class, Resource.class, Template.class, Node.class)
            .newInstance(engine, interceptor, compiler, valueFilterSwitcher, formatterSwitcher, valueFilter, formatter, mapConverter, outConverter, functions, importMacroTemplates, resource, null, root);
      }
      if (writerTemplate != null && streamTemplate != null) {
        return new AdaptiveTemplate(writerTemplate, streamTemplate, outConverter);
      } else if (streamTemplate != null) {
        return streamTemplate;
      } else {
        return writerTemplate;
      }
    } catch (IOException e) {
      throw e;
    } catch (ParseException e) {
      throw e;
    } catch (Exception e) {
      throw new ParseException("Failed to translate template: " + resource.getName() + ", cause: " + ClassUtils.toString(e), 0);
    }
  }
 
  private String getTemplateClassName(Resource resource, boolean stream) {
    String name = resource.getName();
    String encoding = resource.getEncoding();
    Locale locale = resource.getLocale();
    long lastModified = resource.getLastModified();
    StringBuilder buf = new StringBuilder(name.length() + 40);
    buf.append(name);
    if (engineName != null) {
      buf.append("_");
      buf.append(engineName);
    }
    if (encoding != null) {
      buf.append("_");
      buf.append(encoding);
    }
    if (locale != null) {
      buf.append("_");
      buf.append(locale);
    }
    if (lastModified > 0) {
      buf.append("_");
      buf.append(lastModified);
    }
    buf.append(stream ? "_stream" : "_writer");
    return TEMPLATE_CLASS_PREFIX + StringUtils.getVaildName(buf.toString());
  }
 
  private Class<?> parseClass(Resource resource, Node root, Map<String, Class<?>> types, boolean stream, int offset) throws IOException, ParseException {
    String name = getTemplateClassName(resource, stream);
    try {
      return Class.forName(name, true, Thread.currentThread().getContextClassLoader());
    } catch (ClassNotFoundException e) {
      if (types == null) {
        types = new HashMap<String, Class<?>>();
      }
      CompiledVisitor visitor = new CompiledVisitor();
      visitor.setResource(resource);
      visitor.setNode(root);
      visitor.setTypes(types);
      visitor.setStream(stream);
      visitor.setOffset(offset);
      visitor.setDefaultFilterVariable(defaultFilterVariable);
      visitor.setDefaultFormatterVariable(defaultFormatterVariable);
      visitor.setDefaultVariableType(defaultVariableType);
      visitor.setEngineName(engineName);
      visitor.setFilterVariable(filterVariable);
      visitor.setFormatterSwitcher(formatterSwitcher);
      visitor.setFormatterVariable(formatterVariable);
      visitor.setForVariable(forVariable);
      visitor.setImportMacroTemplates(importMacroTemplates);
      visitor.setImportPackages(importPackages);
      visitor.setImportPackageSet(importPackageSet);
      visitor.setImportSizers(importSizers);
      visitor.setImportGetters(importGetters);
      visitor.setImportTypes(importTypes);
      visitor.setImportMethods(functions);
      visitor.setOutputEncoding(outputEncoding);
      visitor.setSourceInClass(sourceInClass);
      visitor.setTextFilter(textFilter);
      visitor.setTextFilterSwitcher(textFilterSwitcher);
      visitor.setTextInClass(textInClass);
      visitor.setValueFilterSwitcher(valueFilterSwitcher);
      visitor.setCompiler(compiler);
      visitor.init();
      root.accept(visitor);
      return visitor.compile();
    }
  }

}
TOP

Related Classes of httl.spi.translators.CompiledTranslator

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.