Package org.soybeanMilk.core.config.parser

Source Code of org.soybeanMilk.core.config.parser.ConfigurationParser

/**
* 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 org.soybeanMilk.core.config.parser;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.soybeanMilk.SbmUtils;
import org.soybeanMilk.core.Constants;
import org.soybeanMilk.core.Executable;
import org.soybeanMilk.core.ExecuteException;
import org.soybeanMilk.core.ObjectSource;
import org.soybeanMilk.core.bean.Converter;
import org.soybeanMilk.core.bean.DefaultGenericConverter;
import org.soybeanMilk.core.bean.GenericConverter;
import org.soybeanMilk.core.config.Configuration;
import org.soybeanMilk.core.config.Interceptor;
import org.soybeanMilk.core.exe.Action;
import org.soybeanMilk.core.exe.Invoke;
import org.soybeanMilk.core.exe.Invoke.Arg;
import org.soybeanMilk.core.exe.support.DefaultResolverObjectFactory;
import org.soybeanMilk.core.exe.support.DynamicResolver;
import org.soybeanMilk.core.exe.support.FactoryResolver;
import org.soybeanMilk.core.exe.support.KeyArg;
import org.soybeanMilk.core.exe.support.ObjectResolver;
import org.soybeanMilk.core.exe.support.ObjectSourceResolver;
import org.soybeanMilk.core.exe.support.ResolverObjectFactory;
import org.soybeanMilk.core.exe.support.ValueArg;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
* 配置解析器
* @author earthangry@gmail.com
* @date 2010-10-1
*/
public class ConfigurationParser
{
  private static Log log=LogFactory.getLog(ConfigurationParser.class);
 
  protected static final String TAG_ROOT="soybean-milk";
 
  protected static final String TAG_GLOBAL_CONFIG="global-config";
  protected static final String TAG_GENERIC_CONVERTER="generic-converter";
  protected static final String TAG_GENERIC_CONVERTER_ATTR_CLASS="class";
  protected static final String TAG_CONVERTER="converter";
  protected static final String TAG_CONVERTER_ATTR_SRC="src";
  protected static final String TAG_CONVERTER_ATTR_TARGET="target";
  protected static final String TAG_CONVERTER_ATTR_CLASS=TAG_GENERIC_CONVERTER_ATTR_CLASS;
 
  protected static final String TAG_INTERCEPROT="interceptor";
  protected static final String TAG_INTERCEPROT_ATTR_BEFORE="before";
  protected static final String TAG_INTERCEPROT_ATTR_AFTER="after";
  protected static final String TAG_INTERCEPROT_ATTR_EXCEPTION="exception";
  protected static final String TAG_INTERCEPROT_ATTR_EXECUTION_KEY="execution-key";
 
  protected static final String TAG_INCLUDES="includes";
  protected static final String TAG_LOCATION="location";
 
  protected static final String TAG_RESOLVERS="resolvers";
  protected static final String TAG_RESOLVER="resolver";
  protected static final String TAG_RESOLVER_ATTR_ID="id";
  protected static final String TAG_RESOLVER_ATTR_CLASS="class";
 
  protected static final String TAG_EXECUTABLES="executables";
  protected static final String TAG_EXECUTABLES_ATTR_PREFIX="prefix";
 
  protected static final String TAG_ACTION="action";
  protected static final String TAG_ACTION_ATTR_NAME="name";
 
  protected static final String TAG_INVOKE="invoke";
  protected static final String TAG_INVOKE_ATTR_NAME=TAG_ACTION_ATTR_NAME;
  protected static final String TAG_INVOKE_ATTR_METHOD="method";
  protected static final String TAG_INVOKE_ATTR_RESOLVER="resolver";
  protected static final String TAG_INVOKE_ATTR_RESULT_KEY="result-key";
  protected static final String TAG_INVOKE_ATTR_BREAKER="breaker";
 
  protected static final String TAG_ARG="arg";
  protected static final String TAG_ARG_ATTR_TYPE="type";
 
  protected static final String TAG_REF="ref";
  protected static final String TAG_REF_ATTR_NAME="name";
 
  /**主文档*/
  private Document rootDocument;
 
  /**配置对象*/
  private Configuration configuration;
 
  /**主文档包含的模块文档*/
  private List<Document> modules;
 
  /**当前可执行对象前缀*/
  private String currentExecutablePrefix;
 
  /**
   * 创建解析器,不预设存储配置对象
   */
  public ConfigurationParser()
  {
    this(null);
  }
 
  /**
   * 创建解析器,并预设存储配置对象,所有的解析结果都将保存到这个配置中
   * @param configuration 预设配置对象
   */
  public ConfigurationParser(Configuration configuration)
  {
    setConfiguration(configuration);
  }
 
  /**
   * 取得解析结果
   * @return
   */
  public Configuration getConfiguration() {
    return configuration;
  }
 
  /**
   * 设置解析配置对象,所有的解析结果将保存到该配置中,它应该在解析前调用
   * @param configuration
   */
  public void setConfiguration(Configuration configuration) {
    this.configuration = configuration;
  }
 
  /**
   * 取得解析文档对象
   * @return
   */
  public Document getDocument()
  {
    return this.rootDocument;
  }
 
  /**
   * 设置解析文档对象
   * @param document
   */
  public void setDocument(Document document) {
    this.rootDocument = document;
  }
 
  /**
   * 取得模块文档对象
   * @return
   */
  public List<Document> getModules() {
    return modules;
  }
 
  /**
   * 设置模块文档对象
   * @param modules
   */
  public void setModules(List<Document> modules) {
    this.modules = modules;
  }
 
  /**
   * 从默认配置文件解析
   * @return
   */
  public Configuration parse()
  {
    return parse((String)null);
  }
 
  /**
   * 从给定配置文件解析
   * @param configFile 配置文件,可以类路径资源文件,也可以是文件系统文件
   * @return
   */
  public Configuration parse(String configFile)
  {
    if(configFile==null || configFile.length()==0)
      configFile=getDefaultConfigFile();
   
    setDocument(parseDocument(configFile));
   
    parseAll();
   
    return getConfiguration();
  }
 
  /**
   * 从输入流解析
   * @param in
   * @return
   */
  public Configuration parse(InputStream in)
  {
    setDocument(parseDocument(in));
   
    parseAll();
   
    return getConfiguration();
  }
 
  /**
   * 从文档对象解析
   * @param document
   * @return
   */
  public Configuration parse(Document document)
  {
    setDocument(document);
   
    parseAll();
   
    return getConfiguration();
  }
 
  /**
   * 解析,如果你没有预设配置对象,这个方法将自动创建
   * @return 解析结果
   */
  protected void parseAll()
  {
    if(getConfiguration() == null)
      setConfiguration(createConfigurationInstance());
   
    Element rootDocEle=getDocumentRootElement(rootDocument);
   
    parseGlobalConfigs(rootDocEle);
    parseIncludes(rootDocEle);
    parseResolvers(rootDocEle);
    parseExecutables(rootDocEle);
   
    if(modules != null)
    {
      for(Document doc : modules)
      {
        Element subDoc=getDocumentRootElement(doc);
       
        parseResolvers(subDoc);
        parseExecutables(subDoc);
      }
    }
   
    parseRefs();
  }
 
  /**
   * 解析全局配置
   */
  protected void parseGlobalConfigs(Element docRoot)
  {
    Element parent=getSingleElementByTagName(docRoot, TAG_GLOBAL_CONFIG);
   
    parseGenericConverter(parent);
   
    parseInterceptor(parent);
  }
 
  /**
   * 解析包含的模块配置
   */
  protected void parseIncludes(Element docRoot)
  {
    List<Element> files=getChildrenByTagName(getSingleElementByTagName(docRoot, TAG_INCLUDES), TAG_LOCATION);
   
    if(files == null || files.isEmpty())
      return;
   
    this.modules = new ArrayList<Document>();
   
    for(Element el : files)
    {
      String fileName=getTextContent(el);
      assertNotEmpty(fileName, "<"+TAG_LOCATION+"> content must not be null");
     
      Document[] docs=parseDocuments(fileName);
      if(docs != null)
      {
        for(Document d : docs)
          this.modules.add(d);
      }
    }
  }
 
  /**
   * 解析并构建调用目标对象
   */
  protected void parseResolvers(Element docRoot)
  {
    List<Element> children=getChildrenByTagName(getSingleElementByTagName(docRoot, TAG_RESOLVERS), TAG_RESOLVER);
   
    if(children!=null && !children.isEmpty())
    {
      ResolverObjectFactory rf = configuration.getResolverObjectFactory();
      if(rf == null)
      {
        rf= createResolverObjectFactoryInstance();
        configuration.setResolverObjectFactory(rf);
      }
     
      ResolverObjectFactory drf=(ResolverObjectFactory)rf;
     
      for(Element e : children)
      {
        String id=getAttributeValueIngoreEmpty(e,TAG_RESOLVER_ATTR_ID);
        assertNotEmpty(id,"<"+TAG_RESOLVER+"> attribute ["+TAG_RESOLVER_ATTR_ID+"] must not be null");
        String clazz=getAttributeValueIngoreEmpty(e,TAG_RESOLVER_ATTR_CLASS);
        assertNotEmpty(clazz,"<"+TAG_RESOLVER+"> of id "+SbmUtils.toString(id)+" attribute ["+TAG_RESOLVER_ATTR_CLASS+"] must not be null");
       
        Object resolver=createClassInstance(clazz);
       
        drf.addResolverObject(id,resolver);
      }
    }
  }
 
  /**
   * 解析并构建可执行对象
   */
  protected void parseExecutables(Element docRoot)
  {
    List<Element> executables=getChildrenByTagName(docRoot,TAG_EXECUTABLES);
   
    if(executables != null)
    {
      for(Element ele : executables)
      {
        setCurrentExecutablePrefix(getAttributeValue(ele, TAG_EXECUTABLES_ATTR_PREFIX));
       
        List<Element> children=getChildrenByTagName(ele, null);
       
        if(children != null)
        {
          for(Element e : children)
          {
            Executable executable=createExecutableInstance(e.getTagName());
           
            if(executable instanceof Action)
              setActionProperties((Action)executable,e);
            else
              setInvokeProperties((Invoke)executable,e, true);
           
            configuration.addExecutable(executable);
          }
        }
      }
    }
  }
 
  /**
   * 处理引用
   */
  protected void parseRefs()
  {
    processExecutableRefs();
    processInterceptorInfoRefs();
  }
 
  /**
   * 解析通用转换器
   * @param parent
   */
  protected void parseGenericConverter(Element parent)
  {
    Element cvtEl = getSingleElementByTagName(parent, TAG_GENERIC_CONVERTER);
   
    String clazz = cvtEl==null ? null : getAttributeValueIngoreEmpty(cvtEl, TAG_GENERIC_CONVERTER_ATTR_CLASS);
   
    GenericConverter genericConverter = configuration.getGenericConverter();
    if(genericConverter == null)
    {
      if(clazz==null || clazz.length()==0)
        genericConverter = createGenericConverterInstance();
      else
        genericConverter = (GenericConverter)createClassInstance(clazz);
     
      configuration.setGenericConverter(genericConverter);
    }
   
    parseSupportConverters(genericConverter, cvtEl);
  }
 
  /**
   * 解析父元素下的支持转换器并加入给定的通用转换器中
   * @param genericConverter
   * @param parent
   */
  protected void parseSupportConverters(GenericConverter genericConverter, Element parent)
  {
    List<Element> children=getChildrenByTagName(parent, TAG_CONVERTER);
    if(children==null || children.isEmpty())
      return;
   
    for(Element e : children)
    {
      String src = getAttributeValueIngoreEmpty(e, TAG_CONVERTER_ATTR_SRC);
      String target = getAttributeValueIngoreEmpty(e, TAG_CONVERTER_ATTR_TARGET);
      String clazz = getAttributeValueIngoreEmpty(e, TAG_CONVERTER_ATTR_CLASS);
     
      assertNotEmpty(src, "<"+TAG_CONVERTER+"> attribute ["+TAG_CONVERTER_ATTR_SRC+"] must not be empty");
      assertNotEmpty(target, "<"+TAG_CONVERTER+"> attribute ["+TAG_CONVERTER_ATTR_TARGET+"] must not be empty");
      assertNotEmpty(clazz, "<"+TAG_CONVERTER+"> attribute ["+TAG_CONVERTER_ATTR_CLASS+"] must not be empty");
     
      genericConverter.addConverter(nameToType(src), nameToType(target), (Converter)createClassInstance(clazz));
    }
  }
 
  /**
   * 解析拦截器信息
   * @param element 父元素
   */
  protected void parseInterceptor(Element parent)
  {
    Element el=getSingleElementByTagName(parent, TAG_INTERCEPROT);
    if(el == null)
      return;
   
    String before=getAttributeValueIngoreEmpty(el, TAG_INTERCEPROT_ATTR_BEFORE);
    String after=getAttributeValueIngoreEmpty(el, TAG_INTERCEPROT_ATTR_AFTER);
    String exception=getAttributeValueIngoreEmpty(el, TAG_INTERCEPROT_ATTR_EXCEPTION);
    String executionKey=getAttributeValueIngoreEmpty(el, TAG_INTERCEPROT_ATTR_EXECUTION_KEY);
   
    assertNotEmpty(executionKey, "<"+TAG_INTERCEPROT+"> attribute ["+TAG_INTERCEPROT_ATTR_EXECUTION_KEY+"] must not be empty");
   
    Interceptor ii=createInterceptorInfoInstance();
    ii.setExecutionKey(executionKey);
   
    if(before != null)
      ii.setBefore(new ExecutableRefProxy(before, getCurrentExecutablePrefix()));
    if(after != null)
      ii.setAfter(new ExecutableRefProxy(after, getCurrentExecutablePrefix()));
    if(exception != null)
      ii.setException(new ExecutableRefProxy(exception, getCurrentExecutablePrefix()));
   
    getConfiguration().setInterceptor(ii);
  }
 
  /**
   * 从元素中解析并设置动作的属性。
   * @param action
   * @param element
   */
  protected void setActionProperties(Action action,Element element)
  {
    //动作和调用的名称可以为空字符串"",因为在servlet规范中会有空字符串名的serlvet路径
   
    String name=getAttributeValue(element,TAG_ACTION_ATTR_NAME);
    assertNotNull(name, "<"+TAG_ACTION+"> attribute ["+TAG_ACTION_ATTR_NAME+"] must not be null");
   
    action.setName(formatGlobalExecutableName(name));
   
    List<Element> children=getChildrenByTagName(element, null);
    for(Element e : children)
    {
      String tagName=e.getTagName();
      if(TAG_REF.equals(tagName))
      {
        String refExecutableName=getAttributeValue(e,TAG_REF_ATTR_NAME);
        assertNotNull(refExecutableName, "<"+TAG_REF+"> attribute ["+TAG_REF_ATTR_NAME+"] in <"+TAG_ACTION+"> named "+SbmUtils.toString(action.getName())+" must not be null");
       
        action.addExecutable(new ExecutableRefProxy(refExecutableName, getCurrentExecutablePrefix()));
      }
      else if(TAG_INVOKE.equals(tagName))
      {
        Invoke invoke=createInvokeIntance();
        setInvokeProperties(invoke,e, false);
       
        action.addExecutable(invoke);
      }
    }
  }
 
  /**
   * 从元素中解析并设置调用的属性
   * @param invoke
   * @param element
   * @param global 是否全局调用
   */
  protected void setInvokeProperties(Invoke invoke, Element element, boolean global)
  {
    String methodName=getAttributeValueIngoreEmpty(element, TAG_INVOKE_ATTR_METHOD);
    String breaker=getAttributeValueIngoreEmpty(element, TAG_INVOKE_ATTR_BREAKER);
   
    if(breaker != null)
    {
      Serializable brk=null;
     
      if(Boolean.TRUE.toString().equals(breaker))
        brk=Boolean.TRUE;
      else if(Boolean.FALSE.toString().equals(breaker))
        brk=Boolean.FALSE;
      else
        brk=breaker;
     
      invoke.setBreaker(brk);
    }
   
    if(methodName == null)
      setInvokePropertiesStatement(invoke, element, global);
    else
      setInvokePropertiesXml(invoke, element, global);
  }
 
  /**
   * 设置以表达式方式定义的调用属性
   * @param invoke
   * @param element
   * @param global 是否全局调用
   */
  protected void setInvokePropertiesStatement(Invoke invoke, Element element, boolean global)
  {
    String statement=getTextContent(element);
    assertNotEmpty(statement, "<"+TAG_INVOKE+"> content must not be empty");
   
    String name=getAttributeValue(element,TAG_INVOKE_ATTR_NAME);
    if(global)
      name=formatGlobalExecutableName(name);
   
    InvokeStatementParser isp=new InvokeStatementParser(statement);
    isp.parse();
   
    invoke.setName(name);
    invoke.setResultKey(isp.getResultKey());
    invoke.setMethodName(isp.getMethodName());
    processInvokeResolverInit(invoke, isp.getResolver());
    processInvokeArgsInit(invoke, isp.getArgs(), isp.getArgTypes());
  }
 
  /**
   * 设置以XML方式定义的调用属性
   * @param invoke
   * @param element
   * @param global 是否全局调用
   */
  protected void setInvokePropertiesXml(Invoke invoke,Element element, boolean global)
  {
    String name=getAttributeValue(element,TAG_INVOKE_ATTR_NAME);
    if(global)
      name=formatGlobalExecutableName(name);
    String methodName=getAttributeValueIngoreEmpty(element, TAG_INVOKE_ATTR_METHOD);
    String resolver=getAttributeValueIngoreEmpty(element,TAG_INVOKE_ATTR_RESOLVER);
    String resultKey=getAttributeValueIngoreEmpty(element,TAG_INVOKE_ATTR_RESULT_KEY);
   
    if(methodName == null)
      throw new ParseException("<"+TAG_INVOKE+"> attribute ["+TAG_INVOKE_ATTR_METHOD+"] must not be null");
    if(resolver == null)
      throw new ParseException("<"+TAG_INVOKE+"> attribute ["+TAG_INVOKE_ATTR_RESOLVER+"] must not be null");
   
    invoke.setName(name);
    invoke.setResultKey(resultKey);
    invoke.setMethodName(methodName);
    processInvokeResolverInit(invoke, resolver);
   
    parseArgs(invoke, element);
  }
 
  /**
   * 解析并构建parent元素下的所有参数信息对象,写入调用对象中
   * @param invoke
   * @param parent
   */
  protected void parseArgs(Invoke invoke, Element parent)
  {
    List<Element> elements=getChildrenByTagName(parent, TAG_ARG);
    if(elements == null)
      return;
   
    String[] strArgs=new String[elements.size()];
    String[] strArgTypes=new String[elements.size()];
   
    for(int i=0, len=strArgs.length;i<len;i++)
    {
      Element e=elements.get(i);
     
      String type=getAttributeValue(e, TAG_ARG_ATTR_TYPE);
      String content=getTextContent(e);
      if(content == null)
        throw new ParseException("<"+TAG_ARG+"> must have text content");
     
      strArgs[i]=content;
      strArgTypes[i]=type;
    }
   
    processInvokeArgsInit(invoke, strArgs, strArgTypes);
  }
 
  /**
   * 处理Invoke属性初始化
   * @param invoke
   * @param resultKey
   * @param resolver
   * @param methodName
   * @param args
   * @param strArgTypes
   * @date 2012-5-8
   */
  /*
  protected void processInvokePropertiesInit(Invoke invoke, String resultKey, String resolver, String methodName, String[] strArgs, String[] strArgTypes)
  {
    invoke.setResultKey(resultKey);
   
    boolean classResolver=false;
    //resolver为类名检测
    if(resolver.indexOf('.') > -1)
    {
      try
      {
        Class<?> rc=Class.forName(resolver);
        invoke.setResolverProvider(new ObjectResolverProvider(null, rc));
       
        classResolver=true;
      }
      catch(Exception e)
      {
        classResolver=false;
      }
    }
    if(!classResolver)
    {
      FactoryResolverProvider frp=new FactoryResolverProvider(configuration.getResolverObjectFactory(), resolver);
      ObjectSourceResolverProvider orp=new ObjectSourceResolverProvider(resolver);
     
      invoke.setResolverProvider(new DynamicResolverProvider(frp, orp));
    }
   
    invoke.setMethodName(methodName);
   
    if(strArgs != null)
    {
      Arg[] args=new Arg[strArgs.length];
     
      for(int i=0; i<strArgs.length; i++)
        args[i]=stringToArg(strArgs[i], (strArgTypes==null ? null : strArgTypes[i]));
     
      invoke.setArgs(args);
    }
  }
  */
 
  /**
   * 处理调用目标初始化
   * @param invoke
   * @param resolver
   * @date 2012-5-11
   */
  protected void processInvokeResolverInit(Invoke invoke, String resolver)
  {
    boolean classResolver=false;
    //resolver为类名检测
    if(resolver.indexOf('.') > -1)
    {
      try
      {
        Class<?> rc=SbmUtils.narrowToClass(nameToType(resolver));
        invoke.setResolver(new ObjectResolver(null, rc));
       
        classResolver=true;
      }
      catch(Exception e)
      {
        classResolver=false;
      }
    }
    if(!classResolver)
    {
      FactoryResolver frp=new FactoryResolver(configuration.getResolverObjectFactory(), resolver);
      ObjectSourceResolver orp=new ObjectSourceResolver(resolver);
     
      invoke.setResolver(new DynamicResolver(frp, orp));
    }
  }
 
  /**
   * 处理调用参数初始化
   * @param invoke
   * @param resolver
   * @date 2012-5-11
   */
  protected void processInvokeArgsInit(Invoke invoke, String[] strArgs, String[] strArgTypes)
  {
    if(strArgs != null)
    {
      Arg[] args=new Arg[strArgs.length];
     
      for(int i=0; i<strArgs.length; i++)
        args[i]=stringToArg(strArgs[i], (strArgTypes==null ? null : strArgTypes[i]));
     
      invoke.setArgs(args);
    }
  }
 
  /**
   * 处理可执行对象引用代理,将它们替换为真正的引用可执行对象,
   * 比如动作中的可执行对象引用代理。
   */
  protected void processExecutableRefs()
  {
    Collection<Executable> executables=configuration.getExecutables();
    if(executables == null)
      return;
   
    for(Executable exe : executables)
    {
      if(exe instanceof Action)
      {
        Action action=(Action)exe;
        List<Executable> actionExes=action.getExecutables();
        if(actionExes==null)
          continue;
       
        for(int i=0,len=actionExes.size();i<len;i++)
        {
          Executable e=actionExes.get(i);
         
          if(e instanceof ExecutableRefProxy)
          {
            ExecutableRefProxy proxy=((ExecutableRefProxy)e);
            Executable targetExe=getTargetRefExecutable((ExecutableRefProxy)e);
           
            if(targetExe == null)
              throw new ParseException("can not find Executable named "+SbmUtils.toString(proxy.getRefName())+" referenced in Action "+SbmUtils.toString(action.getName()));
           
            actionExes.set(i, targetExe);
          }
        }
      }
    }
  }

  /**
   * 替换拦截器的代理为真实的可执行对象
   */
  protected void processInterceptorInfoRefs()
  {
    Interceptor ii=getConfiguration().getInterceptor();
    if(ii == null)
      return;
   
    {
      Executable before=ii.getBefore();
      if(before instanceof ExecutableRefProxy)
      {
        Executable targetExe=getTargetRefExecutable((ExecutableRefProxy)before);
        if(targetExe == null)
          throw new ParseException("can not find 'before' interceptor named "+SbmUtils.toString(((ExecutableRefProxy)before).getRefName()));
       
        ii.setBefore(targetExe);
      }
    }
   
    {
      Executable after=ii.getAfter();
      if(after instanceof ExecutableRefProxy)
      {
        Executable targetExe=getTargetRefExecutable((ExecutableRefProxy)after);
        if(targetExe == null)
          throw new ParseException("can not find 'after' interceptor named "+SbmUtils.toString(((ExecutableRefProxy)after).getRefName()));
       
        ii.setAfter(targetExe);
      }
    }
   
    {
      Executable exception=ii.getException();
      if(exception instanceof ExecutableRefProxy)
      {
        Executable targetExe=getTargetRefExecutable((ExecutableRefProxy)exception);
        if(targetExe == null)
          throw new ParseException("can not find 'exception' interceptor named "+SbmUtils.toString(((ExecutableRefProxy)exception).getRefName()));
       
        ii.setException(targetExe);
      }
    }
  }
 
  /**
   * 获取代理目标
   * @param proxy
   * @return
   * @date 2011-3-15
   */
  protected Executable getTargetRefExecutable(ExecutableRefProxy proxy)
  {
    Executable target=null;
   
    //先从它的文件作用域内取
    if(target == null)
    {
      if(proxy.getCurrentExecutablePrefix() != null)
        target=configuration.getExecutable(proxy.getCurrentExecutablePrefix()+proxy.getRefName());
    }
   
    if(target == null)
      target=configuration.getExecutable(proxy.getRefName());
   
    return target;
  }
 
  /**
   * 格式化全局可执行对象名称,比如增加当前前缀。
   * @param rawName
   * @return
   * @date 2011-3-15
   */
  protected String formatGlobalExecutableName(String rawName)
  {
    String cep=getCurrentExecutablePrefix();
   
    return cep == null ? rawName : cep+rawName;
  }
 
  /**
   * 从输入流解析xml文档对象,此方法同时负责关闭输入流
   * @param in
   * @return
   * @throws ParseException
   */
  protected Document parseDocument(InputStream in)
  {
    Document doc=null;
   
    try
    {
      DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
     
      dbf.setNamespaceAware(false);
     
      //禁止验证
      dbf.setValidating(false);
      dbf.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
     
      doc=dbf.newDocumentBuilder().parse(in);
     
      in.close();
     
      return doc;
    }
    catch(Exception e)
    {
      throw new ParseException("",e);
    }
  }
 
  /**
   * 解析名称中带有匹配符的文档
   * @param fileName
   * @return
   */
  protected Document[] parseDocuments(String fileName)
  {
    Document[] docs=null;
   
    if(fileName.endsWith("/*"))
    {
      fileName=formatIncludeFileName(fileName);
      fileName=fileName.substring(0, fileName.length()-2);
     
      File folder=new File(fileName);
      if(!folder.exists() || !folder.isDirectory())
        throw new ParseException("can not find directory "+SbmUtils.toString(fileName));
     
      File[] files=folder.listFiles(new FileFilter()
      {
        //@Override
        public boolean accept(File pathname)
        {
          String name=pathname.getName().toLowerCase();
          if(name.endsWith(".xml"))
            return true;
          else
            return false;
        }
      });
     
      if(files!=null && files.length>0)
      {
        docs=new Document[files.length];
       
        for(int i=0;i<files.length;i++)
        {
          InputStream in=null;
          try
          {
            in=new FileInputStream(files[i]);
          }
          catch(Exception e)
          {
            throw new ParseException("", e);
          }
         
          docs[i]=parseDocument(in);
         
          if(log.isDebugEnabled())
            log.debug("parsed Document object from "+SbmUtils.toString(files[i].getAbsolutePath()));
        }
      }
      else
      {
        if(log.isDebugEnabled())
          log.debug("no xml file found in directory "+SbmUtils.toString(fileName));
      }
    }
    else
    {
      docs=new Document[1];
      docs[0]=parseDocument(fileName);
    }
   
    return docs;
  }
 
  /**
   * 根据名称取得文档对象
   * @param fileName
   * @return
   */
  protected Document parseDocument(String fileName)
  {
    fileName=formatIncludeFileName(fileName);
   
    InputStream in = null;
    try
    {
      in = getClass().getClassLoader().getResourceAsStream(fileName);
    }
    catch(Exception e){}
   
    if(in == null)
    {
      try
      {
        in=new FileInputStream(fileName);
      }
      catch(Exception e1){}
    }
   
    if(in == null)
      throw new ParseException("can not find config file named "+SbmUtils.toString(fileName));
   
    Document doc=parseDocument(in);
   
    if(log.isDebugEnabled())
      log.debug("parsing Document object from "+SbmUtils.toString(fileName));
   
    return doc;
  }
 
  /**
   * 格式化包含模块文件
   * @param rawFileName
   * @return
   */
  protected String formatIncludeFileName(String rawFileName)
  {
    return rawFileName;
  }
 
  /**
   * 取得文档根元素
   * @return
   */
  protected Element getDocumentRootElement(Document doc)
  {
    return doc.getDocumentElement();
  }
 
  protected void setCurrentExecutablePrefix(String  currentExecutablePrefix)
  {
    this.currentExecutablePrefix=currentExecutablePrefix;
  }
 
  /**
   * 获取当前可执行对象前缀
   * @return
   * @date 2011-3-15
   */
  protected String getCurrentExecutablePrefix()
  {
    return this.currentExecutablePrefix;
  }
 
  /**
   * 取得默认配置文件
   * @return
   */
  protected String getDefaultConfigFile()
  {
    return Constants.DEFAULT_CONFIG_FILE;
  }
 
  /**
   * 取得父元素的直接子元素列表。如果没有,则返回null。
   * 只有子元素的标签名与给定名称匹配的才会返回,如果名称为null,则返回所有。
   * @param parent
   * @param name
   * @return
   * @throws Exception
   */
  protected List<Element> getChildrenByTagName(Element parent,String name)
  {
    if(parent == null)
      return null;
   
    boolean filter= name != null;
   
    NodeList nl=parent.getChildNodes();
   
    List<Element> elements=new ArrayList<Element>();
    for(int i=0;i<nl.getLength();i++)
    {
      Node n=nl.item(i);
      if(!(n instanceof Element))
        continue;
     
      Element e=(Element)nl.item(i);
     
      if(!filter)
        elements.add(e);
      else
      {
        if(name.equals(e.getTagName()))
          elements.add(e);
      }
    }
   
    return elements;
  }
 
  /**
   * 取得父元素的单一子元素
   * @param parent
   * @param name
   * @return
   */
  protected Element getSingleElementByTagName(Element parent,String name)
  {
    if(parent == null)
      return null;
   
    NodeList nodes=parent.getElementsByTagName(name);
   
    if(nodes==null || nodes.getLength()==0)
      return null;
   
    return (Element)nodes.item(0);
  }
 
  /**
   * 确保给定的对象不为null,如果是字符串,同时确保它不为空字符串。
   * @param o 对象
   * @param msg 失败时的异常消息
   */
  protected void assertNotEmpty(Object o,String msg)
  {
    boolean toThrow=false;
   
    if(o == null)
      toThrow=true;
    else if(o instanceof String)
    {
      String s=(String)o;
      if(s.length() == 0)
        toThrow=true;
    }
   
    if(toThrow)
      throw new ParseException(msg);
  }
 
  /**
   * 确保参数不为null
   * @param o
   * @param msg
   */
  protected void assertNotNull(Object o,String msg)
  {
    if(o == null)
      throw new ParseException(msg);
  }
 
  /**
   * 获取元素的属性值,如果属性未定义或者值为空字符串,将返回null
   * @param element
   * @param attrName
   * @return
   */
  protected String getAttributeValueIngoreEmpty(Element element,String attrName)
  {
    String v=element.getAttribute(attrName);
    return v==null || v.length()==0 ? null : v;
  }
 
  /**
   * 获取元素的属性值,空字符串也将被如实返回
   * @param element
   * @param attrName
   * @return
   */
  protected String getAttributeValue(Element element, String attrName)
  {
    Attr attr=element.getAttributeNode(attrName);
    return attr == null ? null : attr.getValue();
  }
 
  /**
   * 获取元素文本内容
   * @param element
   * @return
   */
  protected String getTextContent(Element element)
  {
    String re=element.getTextContent();
   
    return re==null || re.length()==0 ? null : re;
  }
 
  /**
   * 将字符串转换为Arg对象
   * @param strArg
   * @param strType
   * @return
   * @date 2012-5-8
   */
  protected Arg stringToArg(String strArg, String strType)
  {
    Arg re=null;
   
    Type argType=null;
    if(strType!=null && strType.length()>0)
      argType=nameToType(strType);
   
    if(strArg==null || strArg.length()==0)
      re=new ValueArg(strArg, argType);
    else
    {
      int len=strArg.length();
      char first=strArg.charAt(0);
      char end=strArg.charAt(len-1);
     
      //数值
      if(Character.isDigit(first))
      {
        Type wrappedType=(argType == null ? null : SbmUtils.wrapType(argType));
       
        if(Byte.class.equals(wrappedType))
        {
          re=new ValueArg(new Byte(strArg), argType);
        }
        else if(Short.class.equals(wrappedType))
        {
          re=new ValueArg(new Short(strArg), argType);
        }
        else if(Integer.class.equals(wrappedType))
        {
          re=new ValueArg(new Integer(strArg), argType);
        }
        else if(Long.class.equals(wrappedType))
        {
          re=new ValueArg(new Long(strArg), argType);
        }
        else if(Float.class.equals(wrappedType))
        {
          re=new ValueArg(new Float(strArg), argType);
        }
        else if(Double.class.equals(wrappedType))
        {
          re=new ValueArg(new Double(strArg), argType);
        }
        else if('L' == end)
        {
          re=new ValueArg(new Long(strArg.substring(0, len-1)), Long.class);
        }
        else if('l' == end)
        {
          re=new ValueArg(new Long(strArg.substring(0, len-1)), long.class);
        }
        else if('F' == end)
        {
          re=new ValueArg(new Float(strArg.substring(0, len-1)), Float.class);
        }
        else if('f'==end)
        {
          re=new ValueArg(new Float(strArg.substring(0, len-1)), float.class);
        }
        else if('D' == end)
        {
          re=new ValueArg(new Double(strArg.substring(0, len-1)), Double.class);
        }
        else if('d' == end)
        {
          re=new ValueArg(new Double(strArg.substring(0, len-1)), double.class);
        }
        else
        {
          boolean point=strArg.indexOf('.') >= 0;
         
          if(point)
            re=new ValueArg(new Double(strArg), argType);
          else
            re=new ValueArg(new Integer(strArg), argType);
        }
      }
      else if(first =='"')
      {
        String ue=SbmUtils.unEscape(strArg);
        len=ue.length();
       
        if(len<2 || ue.charAt(len-1) != '"')
          throw new ParseException("illegal String definition: "+strArg);
       
        if(len == 2)
          re=new ValueArg("", argType);
        else
          re=new ValueArg(ue.subSequence(1, len-1), argType);
      }
      else if(first =='\'')
      {
        String ue=SbmUtils.unEscape(strArg);
        len=ue.length();
       
        if(len!=3 || end!= '\'')
          throw new ParseException("illegal char definition: "+strArg);
       
        re=new ValueArg(ue.charAt(1), argType);
      }
      else if("true".equals(strArg))
      {
        re=new ValueArg(Boolean.TRUE, argType);
      }
      else if("false".equals(strArg))
      {
        re=new ValueArg(Boolean.FALSE, argType);
      }
      else if("null".equals(strArg))
      {
        re=new ValueArg(null, argType);
      }
      else
        re=new KeyArg(strArg, argType);
    }
   
    return re;
  }
 
  /**
   * 创建空的配置对象,用于从配置文件解析并设置其属性
   * @return
   */
  protected Configuration createConfigurationInstance()
  {
    return new Configuration();
  }
 
  protected ResolverObjectFactory createResolverObjectFactoryInstance()
  {
    return new DefaultResolverObjectFactory();
  }
 
  /**
   * 创建空的通用转换器对象,用于设置其属性
   * @return
   */
  protected GenericConverter createGenericConverterInstance()
  {
    return new DefaultGenericConverter();
  }
 
  /**
   * 创建空的拦截器信息对象,用于设置其属性
   * @return
   */
  protected Interceptor createInterceptorInfoInstance()
  {
    return new Interceptor();
  }
 
  /**
   * 创建空的可执行对象,用于从配置文件解析并设置其属性
   * @return
   */
  protected Executable createExecutableInstance(String type)
  {
    if(TAG_ACTION.equals(type))
      return createActionIntance();
    else if(TAG_INVOKE.equals(type))
      return createInvokeIntance();
    else
      throw new ParseException("illegal Executable type <"+type+">");
  }
 
  /**
   * 创建空的动作对象,用于从配置文件解析并设置其属性
   * @return
   */
  protected Action createActionIntance()
  {
    return new Action();
  }
 
  /**
   * 创建空的调用对象,用于从配置文件解析并设置其属性
   * @return
   */
  protected Invoke createInvokeIntance()
  {
    return new Invoke();
  }
 
  /**
   * 创建对象
   * @param clazz
   * @return
   */
  protected Object createClassInstance(String clazz)
  {
    try
    {
      return SbmUtils.narrowToClass(SbmUtils.nameToType(clazz)).newInstance();
    }
    catch(Exception e)
    {
      throw new ParseException(e);
    }
  }
 
  /**
   * 由类型名称获取其类型
   * @param type
   * @return
   * @date 2012-5-27
   */
  protected Type nameToType(String type)
  {
    try
    {
      return SbmUtils.nameToType(type);
    }
    catch(Exception e)
    {
      throw new ParseException(e);
    }
  }
 
  /**
   * 可执行对象代理,用于可执行对象引用的延迟初始化
   * @author earthangry@gmail.com
   * @date 2010-10-28
   *
   */
  protected static class ExecutableRefProxy implements Executable
  {
    private String refName;
    private String currentExecutablePrefix;
   
    public ExecutableRefProxy(String refName, String currentExecutablePrefix)
    {
      super();
      this.refName = refName;
      this.currentExecutablePrefix=currentExecutablePrefix;
    }

    public String getRefName() {
      return refName;
    }

    public void setRefName(String refName) {
      this.refName = refName;
    }

    public String getCurrentExecutablePrefix()
    {
      return currentExecutablePrefix;
    }

    public void setCurrentExecutablePrefix(String currentExecutablePrefix)
    {
      this.currentExecutablePrefix = currentExecutablePrefix;
    }

    //@Override
    public void execute(ObjectSource objectSource) throws ExecuteException
    {
      throw new UnsupportedOperationException();
    }

    //@Override
    public String getName()
    {
      throw new UnsupportedOperationException();
    }

    //@Override
    public String toString()
    {
      return Executable.class.getSimpleName()+" [name=" + refName + "]";
    }
  }
}
TOP

Related Classes of org.soybeanMilk.core.config.parser.ConfigurationParser

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.