Package com.quickwebframework.ioc.spring.util

Source Code of com.quickwebframework.ioc.spring.util.BundleNamespaceHandlerResolver

package com.quickwebframework.ioc.spring.util;

import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.xml.NamespaceHandler;
import org.springframework.beans.factory.xml.NamespaceHandlerResolver;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;

public class BundleNamespaceHandlerResolver implements NamespaceHandlerResolver {

  /**
   * The location to look for the mapping files. Can be present in multiple
   * JAR files.
   */
  public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";

  /** Logger available to subclasses */
  protected final Log logger = LogFactory.getLog(getClass());

  /** Spring的类加载器 */
  private final ClassLoader springClassLoader;
  /** 插件的类加载器 */
  private final ClassLoader bundleClassLoader;

  /** Resource location to search for */
  private final String handlerMappingsLocation;

  /**
   * Stores the mappings from namespace URI to NamespaceHandler class name /
   * instance
   */
  private volatile Map<String, Object> handlerMappings;

  public BundleNamespaceHandlerResolver(ClassLoader bundleClassLoader) {
    this(BundleNamespaceHandlerResolver.class.getClassLoader(),
        bundleClassLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
  }

  public BundleNamespaceHandlerResolver(ClassLoader springClassLoader,
      ClassLoader bundleClassLoader) {
    this(springClassLoader, bundleClassLoader,
        DEFAULT_HANDLER_MAPPINGS_LOCATION);
  }

  public BundleNamespaceHandlerResolver(ClassLoader springClassLoader,
      ClassLoader bundleClassLoader, String handlerMappingsLocation) {
    this.springClassLoader = springClassLoader;
    this.bundleClassLoader = bundleClassLoader;
    this.handlerMappingsLocation = handlerMappingsLocation;
  }

  /**
   * Locate the {@link NamespaceHandler} for the supplied namespace URI from
   * the configured mappings.
   *
   * @param namespaceUri
   *            the relevant namespace URI
   * @return the located {@link NamespaceHandler}, or <code>null</code> if
   *         none found
   */
  public NamespaceHandler resolve(String namespaceUri) {
    Map<String, Object> handlerMappings = getHandlerMappings();
    Object handlerOrClassName = handlerMappings.get(namespaceUri);
    if (handlerOrClassName == null) {
      return null;
    } else if (handlerOrClassName instanceof NamespaceHandler) {
      return (NamespaceHandler) handlerOrClassName;
    } else {
      String className = (String) handlerOrClassName;
      try {
        Class<?> handlerClass = null;
        try {
          handlerClass = ClassUtils.forName(className,
              this.springClassLoader);
        } catch (ClassNotFoundException ex) {
          handlerClass = ClassUtils.forName(className,
              this.bundleClassLoader);
        }

        if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
          throw new FatalBeanException("Class [" + className
              + "] for namespace [" + namespaceUri
              + "] does not implement the ["
              + NamespaceHandler.class.getName() + "] interface");
        }
        NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils
            .instantiateClass(handlerClass);
        namespaceHandler.init();
        handlerMappings.put(namespaceUri, namespaceHandler);
        return namespaceHandler;
      } catch (ClassNotFoundException ex) {
        throw new FatalBeanException("NamespaceHandler class ["
            + className + "] for namespace [" + namespaceUri
            + "] not found", ex);
      } catch (LinkageError err) {
        throw new FatalBeanException(
            "Invalid NamespaceHandler class ["
                + className
                + "] for namespace ["
                + namespaceUri
                + "]: problem with handler class file or dependent class",
            err);
      }
    }
  }

  /**
   * Load the specified NamespaceHandler mappings lazily.
   */
  private Map<String, Object> getHandlerMappings() {
    if (this.handlerMappings == null) {
      synchronized (this) {
        if (this.handlerMappings == null) {
          try {
            // 加载本类的类加载器的配置文件
            Properties springMappings = PropertiesLoaderUtils
                .loadAllProperties(
                    this.handlerMappingsLocation,
                    springClassLoader);
            if (logger.isDebugEnabled()) {
              logger.debug("Loaded Spring NamespaceHandler mappings: "
                  + springMappings);
            }
            // 加载插件的类加载器的配置文件
            Properties bundleMappings = PropertiesLoaderUtils
                .loadAllProperties(
                    this.handlerMappingsLocation,
                    this.bundleClassLoader);
            if (logger.isDebugEnabled()) {
              logger.debug("Loaded Bundle NamespaceHandler mappings: "
                  + bundleMappings);
            }

            Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(
                springMappings.size() + bundleMappings.size());
            CollectionUtils.mergePropertiesIntoMap(springMappings,
                handlerMappings);
            CollectionUtils.mergePropertiesIntoMap(bundleMappings,
                handlerMappings);

            this.handlerMappings = handlerMappings;
          } catch (IOException ex) {
            throw new IllegalStateException(
                "Unable to load NamespaceHandler mappings from location ["
                    + this.handlerMappingsLocation + "]",
                ex);
          }
        }
      }
    }
    return this.handlerMappings;
  }

  @Override
  public String toString() {
    return "BundleNamespaceHandlerResolver using mappings "
        + getHandlerMappings();
  }
}
TOP

Related Classes of com.quickwebframework.ioc.spring.util.BundleNamespaceHandlerResolver

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.