package io.graceland.configuration;

import java.io.File;
import java.lang.annotation.Annotation;
import javax.validation.Validation;

import com.google.common.base.Preconditions;
import com.google.inject.Binder;

import io.dropwizard.configuration.ConfigurationFactory;
import io.dropwizard.jackson.Jackson;

/**
 * Used to bring a configuration into the dependency graph. The simplest way is to load it from a file or to a specific
 * instance.
 *
 * @param <Config> The specific class of the Configuration.
 */
public class ConfigurationBinder<Config extends Configuration> {

    private final Class<Config> configClass;
    private final Binder binder;
    private Class<? extends Annotation> annotationClass = null;

    ConfigurationBinder(Class<Config> configClass, Binder binder) {
        this.configClass = Preconditions.checkNotNull(configClass, "Configuration Class cannot be null.");
        this.binder = Preconditions.checkNotNull(binder, "Binder cannot be null.");
    }

    /**
     * The starting point for using a ConfigurationBinder. A class needs to be passed through, along with a binder to
     * eventually bind the configuration with.
     *
     * @param klass  The Configuration Class to load & bind.
     * @param binder The {@link com.google.inject.Binder} from the {@link io.graceland.plugin.AbstractPlugin}.
     * @param <T>    The Configuration Type.
     * @return Returns a working ConfigurationBinder using the provided type and class information.
     */
    public static <T extends Configuration> ConfigurationBinder<T> forClass(Class<T> klass, Binder binder) {
        return new ConfigurationBinder<>(klass, binder);
    }

    public ConfigurationBinder<Config> annotatedWith(Class<? extends Annotation> annotation) {
        this.annotationClass = Preconditions.checkNotNull(annotation, "Annotation cannot be null.");
        return this;
    }

    /**
     * This method will bind the class to a particular instance.
     *
     * @param configuration
     */
    public void toInstance(Config configuration) {
        Preconditions.checkNotNull(configuration, "Configuration Instance cannot be null.");

        if (annotationClass == null) {
            binder.bind(configClass).toInstance(configuration);

        } else {
            binder.bind(configClass).annotatedWith(annotationClass).toInstance(configuration);
        }
    }

    /**
     * This method will load the configuration using a {@link io.dropwizard.configuration.ConfigurationFactory} to load
     * the file from the current relative working directory.
     *
     * @param fileName The filename to load.
     */
    public void toFile(String fileName) {
        Preconditions.checkNotNull(fileName, "File Name cannot be null.");

        Config configuration = buildFromFile(fileName);

        if (annotationClass == null) {
            binder.bind(configClass).toInstance(configuration);

        } else {
            binder.bind(configClass).annotatedWith(annotationClass).toInstance(configuration);
        }
    }

    /**
     * Builds a Configuration object from the file path given. It uses the {@link io.dropwizard.configuration.ConfigurationFactory}
     * to build the configuration.
     *
     * @param possibleFilename The path to the configuration.
     * @return A configuration object loaded form the filename given.
     */
    private Config buildFromFile(String possibleFilename) {
        File configFile = new File(possibleFilename);
        Preconditions.checkArgument(configFile.exists(), "File must exist at: " + configFile.getAbsolutePath());

        try {
            return new ConfigurationFactory<>(
                    configClass,
                    Validation.buildDefaultValidatorFactory().getValidator(),
                    Jackson.newObjectMapper(),
                    "graceland")
                    .build(configFile);

        } catch (Exception e) {
            String msg = "Unknown exception triggered when attempting to build config from file:" + "\n" +
                    "\t* Configuration Class: " + configClass.getCanonicalName() + "\n" +
                    "\t* File: " + configFile.getAbsolutePath();

            throw new RuntimeException(msg, e);
        }
    }
}


/*
 * Copyright (C) 2012 Eiichiro Uchiumi. All Rights Reserved.
 *
 * 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.eiichiro.reverb.lang;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.Set;

/**
 * {@code JLCClassResolver} is a {@code java.lang.Class} based extension of
 * {@link ClassResolver} ('JLC' means {@code java.lang.Class}).
 * This class loads the class as {@code java.lang.Class} directly from the
 * specified search path.
 *
 * @author Eiichiro Uchiumi
 */
public class JLCClassResolver extends ClassResolver<Class<?>> {

	private ClassLoader classLoader;

	/**
	 * Constructs a new {@code JLCClassResolver} instance with the specified
	 * search paths.
	 *
	 * @param paths The search path.
	 */
	public JLCClassResolver(Iterable<URL> paths) {
		this(Thread.currentThread().getContextClassLoader(), paths);
	}

	/**
	 * Constructs a new {@code JLCClassResolver} instance with the specified
	 * {@code ClassLoader} and search paths.
	 *
	 * @param classLoader The {@code ClassLoader} to load classes.
	 * @param paths The search path.
	 */
	public JLCClassResolver(ClassLoader classLoader, Iterable<URL> paths) {
		super(paths);
		this.classLoader = classLoader;
	}

	/**
	 * Loads the class of the specified name from the specified
	 * {@code InputStream} and returns loaded class representation as
	 * {@code java.lang.Class}.
	 *
	 * @param clazz The name of the class to be loaded.
	 * @param stream {@code InputStream} to load a class file.
	 * @return The loaded class representation as {@code java.lang.Class}.
	 */
	@Override
	protected Class<?> load(String clazz, InputStream stream) {
//		System.out.println(clazz);

		try {
			return Class.forName(clazz, true, classLoader);
		} catch (Exception e) {
//			System.out.println(e);
			return null;
		} catch (NoClassDefFoundError e) {
//			System.out.println(e);
			return null;
		}
	}

	/**
	 * Resolves the classes that contains the specified name as
	 * {@code java.lang.Class}.
	 *
	 * @param name The part of the class name.
	 * @return Classes that contains the specified name as
	 * {@code java.lang.Class}.
	 * @throws IOException If any I/O access fails while traversing the search
	 * path.
	 */
	@Override
	public Set<Class<?>> resolveByName(final String name) throws IOException {
		Matcher<Class<?>> matcher = new Matcher<Class<?>>() {

			public boolean matches(Class<?> clazz) {
				return clazz.getName().contains(name);
			}

		};
		return resolve(matcher);
	}

	/**
	 * Resolves the classes that inherits the specified superclass as
	 * {@code java.lang.Class}.
	 *
	 * @param superclass The superclass being inherited.
	 * @return Classes that inherits the specified superclass as
	 * {@code java.lang.Class}.
	 * @throws IOException If any I/O access fails while traversing the search
	 * path.
	 */
	@Override
	public Set<Class<?>> resolveBySuperclass(final Class<?> superclass)
			throws IOException {
		Matcher<Class<?>> matcher = new Matcher<Class<?>>() {

			public boolean matches(Class<?> clazz) {
				if (clazz.getSuperclass() != null) {
					if (clazz.getSuperclass().equals(superclass)) {
						return true;
					} else {
						return matches(clazz.getSuperclass());
					}

				} else {
					return false;
				}
			}

		};
		return resolve(matcher);
	}

	/**
	 * Resolves the classes that implements the specified interface as
	 * {@code java.lang.Class}.
	 *
	 * @param interfaceClass The interface being implemented.
	 * @return Classes that implements the specified interface as
	 * {@code java.lang.Class}.
	 * @throws IOException If any I/O access fails while traversing the search
	 * path.
	 */
	@Override
	public Set<Class<?>> resolveByInterface(final Class<?> interfaceClass)
			throws IOException {
		Matcher<Class<?>> matcher = new Matcher<Class<?>>() {

			public boolean matches(Class<?> clazz) {
				Class<?>[] interfaces = clazz.getInterfaces();

				for (Class<?> c : interfaces) {
					if (c.equals(interfaceClass)) {
						return true;
					}
				}

				if (clazz.getSuperclass() != null) {
					return matches(clazz.getSuperclass());
				} else {
					return false;
				}
			}

		};
		return resolve(matcher);
	}

	/**
	 * Resolves the classes that is annotated by the specified annotation as
	 * {@code java.lang.Class}.
	 *
	 * @param annotation The annotation the class being annotated.
	 * @return Classes that is annotated by the specified annotation as
	 * {@code java.lang.Class}.
	 * @throws IOException If any I/O access fails while traversing the search
	 * path.
	 */
	@Override
	public Set<Class<?>> resolveByAnnotation(
			final Class<? extends Annotation> annotation) throws IOException {
		Matcher<Class<?>> matcher = new Matcher<Class<?>>() {

			public boolean matches(Class<?> clazz) {
				Annotation[] annotations = clazz.getAnnotations();

				for (Annotation a : annotations) {
					if (a.annotationType().equals(annotation)) {
						return true;
					}
				}

				return false;
			}

		};
		return resolve(matcher);
	}

	/**
	 * Returns the {@code ClassLoader} to load classes.
	 *
	 * @return The {@code ClassLoader} to load classes.
	 */
	public ClassLoader classLoader() {
		return classLoader;
	}

}


package io.github.huherto.springyRecords;
/*
The MIT License (MIT)

Copyright (c) 2014 <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.util.Assert;

/**
 * Implementation adapted from BeanPropertyRowMapper
 */
public class RecordMapper<T> implements RowMapper<T> {

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

    /** The class we are mapping to */
    private Class<T> mappedClass;

    /** Whether we're defaulting primitives when mapping a null value */
    private boolean primitivesDefaultedForNullValue = false;

    private final boolean autoTrimStrings = true;

    private Map<String, Field> mappedFields;

    /**
     * Create a new DtoRowMapper for bean-style configuration.
     * @see #setMappedClass
     * @see #setCheckFullyPopulated
     */
    public RecordMapper() {
    }

    /**
     * Create a new DtoRowMapper, accepting unpopulated properties
     * in the target bean.
     *
Consider using the {@link #newInstance} factory method instead,
     * which allows for specifying the mapped type once only.
     * @param mappedClass the class that each row should be mapped to
     */
    public RecordMapper(Class<T> mappedClass) {
        initialize(mappedClass);
    }

    /**
     * Create a new DtoRowMapper.
     * @param mappedClass the class that each row should be mapped to
     * @param checkFullyPopulated whether we're strictly validating that
     * all bean properties have been mapped from corresponding database fields
     */
    public RecordMapper(Class<T> mappedClass, boolean checkFullyPopulated) {
        initialize(mappedClass);
    }

    /**
     * Set the class that each row should be mapped to.
     */
    public void setMappedClass(Class<T> mappedClass) {
        if (this.mappedClass == null) {
            initialize(mappedClass);
        }
        else {
            if (!this.mappedClass.equals(mappedClass)) {
                throw new InvalidDataAccessApiUsageException("The mapped class can not be reassigned to map to " +
                        mappedClass + " since it is already providing mapping for " + this.mappedClass);
            }
        }
    }

    /**
     * Initialize the mapping metadata for the given class.
     * @param mappedClass the mapped class.
     */
    protected void initialize(Class<T> mappedClass) {
        this.mappedClass = mappedClass;
        this.mappedFields = new HashMap<String, Field>();

        Field fields[] = mappedClass.getFields();
        for (Field field : fields) {
            int mod = field.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isStatic(mod)) {
                for(Annotation a: field.getAnnotations()) {
                    if (a.annotationType().isAssignableFrom(Column.class)) {
                        Column c = (Column)a;
                        String columnName = c.name();
                        mappedFields.put(columnName, field);
                    }
                }
            }
        }
    }

    /**
     * Get the class that we are mapping to.
     */
    public final Class<T> getMappedClass() {
        return this.mappedClass;
    }

    /**
     * Set whether we're defaulting Java primitives in the case of mapping a null value
     * from corresponding database fields.
     *
Default is false, throwing an exception when nulls are mapped to Java primitives.
     */
    public void setPrimitivesDefaultedForNullValue(boolean primitivesDefaultedForNullValue) {
        this.primitivesDefaultedForNullValue = primitivesDefaultedForNullValue;
    }

    /**
     * Return whether we're defaulting Java primitives in the case of mapping a null value
     * from corresponding database fields.
     */
    public boolean isPrimitivesDefaultedForNullValue() {
        return primitivesDefaultedForNullValue;
    }

    /**
     * Extract the values for all columns in the current row.
     *
Utilizes public setters and result set metadata.
     * @see java.sql.ResultSetMetaData
     */
    @Override
    public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
        Assert.state(this.mappedClass != null, "Mapped class was not specified");

        T mappedObject;
        try {
            mappedObject = mappedClass.newInstance();
        }
        catch(Exception ex) {
            throw new RuntimeException(ex);
        }

        ResultSetMetaData rsmd = rs.getMetaData();
        int columnCount = rsmd.getColumnCount();

        for (int index = 1; index <= columnCount; index++) {
            String column = JdbcUtils.lookupColumnName(rsmd, index);
            Field field = this.mappedFields.get(column.replaceAll(" ", ""));
            if (field != null) {
                Object value = getColumnValue(rs, index, field);
                if (logger.isTraceEnabled() && rowNumber == 0) {
                    logger.trace("Mapping column '" + column + "' to property '" +
                            field.getName() + "' of type " + field.getType());
                }
                try {
                    field.set(mappedObject, value);
                }
                catch (IllegalArgumentException e) {
                    if (value == null && primitivesDefaultedForNullValue) {
                        logger.debug("Intercepted IllegalArgumentException for row " + rowNumber +
                                " and column '" + column + "' with value " + value +
                                " when setting property '" + field.getName() + "' of type " + field.getType() +
                                " on object: " + mappedObject);
                    }
                    else {
                        throw e;
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return mappedObject;
    }

    /**
     * Retrieve a JDBC object value for the specified column.
     *
The default implementation calls
     * {@link JdbcUtils#getResultSetValue(java.sql.ResultSet, int, Class)}.
     * Subclasses may override this to check specific value types upfront,
     * or to post-process values return from getResultSetValue.
     * @param rs is the ResultSet holding the data
     * @param index is the column index
     * @param pd the bean property that each result object is expected to match
     * (or null if none specified)
     * @return the Object value
     * @throws SQLException in case of extraction failure
     * @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue(java.sql.ResultSet, int, Class)
     */
    protected Object getColumnValue(ResultSet rs, int index, Field field) throws SQLException {

        Object value = JdbcUtils.getResultSetValue(rs, index, field.getType());
        if (value != null &&  value instanceof String && autoTrimStrings) {
            return ((String)value).trim();
        }
        return value;
    }

    /**
     * Static factory method to create a new RecordMapper
     * (with the mapped class specified only once).
     * @param mappedClass the class that each row should be mapped to
     */
    public static <T> RecordMapper<T> newInstance(Class<T> mappedClass) {
        RecordMapper<T> newInstance = new RecordMapper<T>();
        newInstance.setMappedClass(mappedClass);
        return newInstance;
    }

}


/*
 * Copyright(C) 2009 matrix
 * All right reserved.
 */
package net.matrix.app.repository;

import java.util.Objects;

import javax.annotation.concurrent.Immutable;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 资源仓库选择，指向资源仓库中的一项资源。
 */
@Immutable
public class ResourceSelection {
	/**
	 * 类别。
	 */
	private final String catalog;

	/**
	 * 版本。
	 */
	private final String version;

	/**
	 * 名称。
	 */
	private final String name;

	/**
	 * 构造一个实例。如果未提供名称，则根据类别生成默认的名称。
	 *
	 * @param catalog
	 *            分类
	 * @param version
	 *            版本
	 * @param name
	 *            名称
	 */
	public ResourceSelection(final String catalog, final String version, final String name) {
		this.catalog = catalog;
		this.version = version;
		if (StringUtils.isBlank(name)) {
			this.name = generateName(catalog);
		} else {
			this.name = name;
		}
	}

	/**
	 * 根据类别生成默认的名称。
	 *
	 * @param catalog
	 *            类别
	 * @return 名称
	 */
	public static String generateName(final String catalog) {
		String[] catalogs = catalog.split("/");
		return catalogs[catalogs.length - 1];
	}

	/**
	 * @return 分类
	 */
	public String getCatalog() {
		return catalog;
	}

	/**
	 * @return 版本
	 */
	public String getVersion() {
		return version;
	}

	/**
	 * @return 名称
	 */
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return "ResourceSelection[" + catalog + ':' + ObjectUtils.defaultIfNull(version, "") + ':' + name + ']';
	}

	@Override
	public int hashCode() {
		return Objects.hash(catalog, name, version);
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		ResourceSelection other = (ResourceSelection) obj;
		if (catalog == null) {
			if (other.catalog != null) {
				return false;
			}
		} else if (!catalog.equals(other.catalog)) {
			return false;
		}
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		if (version == null) {
			if (other.version != null) {
				return false;
			}
		} else if (!version.equals(other.version)) {
			return false;
		}
		return true;
	}
}


/*
 * Copyright(C) 2009 matrix
 * All right reserved.
 */
package net.matrix.app.message;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 编码消息实用工具。
 */
public final class CodedMessages {
	private static final DocumentBuilderFactory DOM_FACTORY = DocumentBuilderFactory.newInstance();

	private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();

	/**
	 * 阻止实例化。
	 */
	private CodedMessages() {
	}

	/**
	 * 新建跟踪级别的消息。
	 *
	 * @param code
	 *            编码
	 * @param arguments
	 *            参数列表
	 * @return 新建的消息
	 */
	public static CodedMessage trace(final String code, final String... arguments) {
		return new CodedMessage(code, CodedMessageLevel.TRACE, arguments);
	}

	/**
	 * 新建调试级别的消息。
	 *
	 * @param code
	 *            编码
	 * @param arguments
	 *            参数列表
	 * @return 新建的消息
	 */
	public static CodedMessage debug(final String code, final String... arguments) {
		return new CodedMessage(code, CodedMessageLevel.DEBUG, arguments);
	}

	/**
	 * 新建消息级别的消息。
	 *
	 * @param code
	 *            编码
	 * @param arguments
	 *            参数列表
	 * @return 新建的消息
	 */
	public static CodedMessage information(final String code, final String... arguments) {
		return new CodedMessage(code, CodedMessageLevel.INFORMATION, arguments);
	}

	/**
	 * 新建警告级别的消息。
	 *
	 * @param code
	 *            编码
	 * @param arguments
	 *            参数列表
	 * @return 新建的消息
	 */
	public static CodedMessage warning(final String code, final String... arguments) {
		return new CodedMessage(code, CodedMessageLevel.WARNING, arguments);
	}

	/**
	 * 新建错误级别的消息。
	 *
	 * @param code
	 *            编码
	 * @param arguments
	 *            参数列表
	 * @return 新建的消息
	 */
	public static CodedMessage error(final String code, final String... arguments) {
		return new CodedMessage(code, CodedMessageLevel.ERROR, arguments);
	}

	/**
	 * 新建致命错误级别的消息。
	 *
	 * @param code
	 *            编码
	 * @param arguments
	 *            参数列表
	 * @return 新建的消息
	 */
	public static CodedMessage fatal(final String code, final String... arguments) {
		return new CodedMessage(code, CodedMessageLevel.FATAL, arguments);
	}

	/**
	 * 从文件加载。
	 *
	 * @param reader
	 *            输入流
	 * @return 消息记录组
	 * @throws CodedMessageException
	 *             操作异常
	 */
	public static List<CodedMessage> load(final InputStream reader)
		throws CodedMessageException {
		Document document;
		try {
			Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
			DOMResult result = new DOMResult();
			transformer.transform(new StreamSource(reader), result);
			document = (Document) result.getNode();
		} catch (TransformerException e) {
			throw new CodedMessageException(e, "CodedMessage.LoadXMLError");
		}
		return load0(document.getDocumentElement());
	}

	/**
	 * 从文件加载。
	 *
	 * @param reader
	 *            输入流
	 * @return 消息记录组
	 * @throws CodedMessageException
	 *             操作异常
	 */
	public static List<CodedMessage> load(final Reader reader)
		throws CodedMessageException {
		Document document;
		try {
			Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
			DOMResult result = new DOMResult();
			transformer.transform(new StreamSource(reader), result);
			document = (Document) result.getNode();
		} catch (TransformerException e) {
			throw new CodedMessageException(e, "CodedMessage.LoadXMLError");
		}
		return load0(document.getDocumentElement());
	}

	private static List<CodedMessage> load0(final Node node) {
		List<CodedMessage> messageList = new ArrayList<>();
		NodeList messageNodeList = node.getChildNodes();
		for (int i = 0; i < messageNodeList.getLength(); i++) {
			Node messageNode = messageNodeList.item(i);
			if (messageNode.getNodeType() != Node.ELEMENT_NODE) {
				continue;
			}
			if ("message".equals(messageNode.getNodeName())) {
				messageList.add(load1(messageNode));
			}
		}
		return messageList;
	}

	private static CodedMessage load1(final Node node) {
		NamedNodeMap messageNodeAttributes = node.getAttributes();
		String code = getCodeNode(messageNodeAttributes).getNodeValue();
		long time = Long.parseLong(messageNodeAttributes.getNamedItem("time").getNodeValue());
		CodedMessageLevel level = CodedMessageLevel.forCode(Integer.valueOf(messageNodeAttributes.getNamedItem("level").getNodeValue()));
		CodedMessage message = new CodedMessage(code, time, level);
		NodeList childNodeList = node.getChildNodes();
		for (int j = 0; j < childNodeList.getLength(); j++) {
			Node childNode = childNodeList.item(j);
			if (childNode.getNodeType() != Node.ELEMENT_NODE) {
				continue;
			}
			if ("argument".equals(childNode.getNodeName())) {
				message.addArgument(childNode.getTextContent());
			} else if ("unformattedArgument".equals(childNode.getNodeName())) {
				message.addUnformattedArgument(childNode.getTextContent());
			} else if ("message".equals(childNode.getNodeName())) {
				message.getMessages().add(load1(childNode));
			}
		}
		return message;
	}

	private static Node getCodeNode(final NamedNodeMap messageNodeAttributes) {
		Node codeNode = messageNodeAttributes.getNamedItem("logId");
		if (codeNode == null) {
			codeNode = messageNodeAttributes.getNamedItem("code");
		}
		return codeNode;
	}

	/**
	 * 保存到文件。
	 *
	 * @param messageList
	 *            消息记录组
	 * @param writer
	 *            输出流
	 * @throws CodedMessageException
	 *             操作异常
	 */
	public static void save(final List<CodedMessage> messageList, final OutputStream writer)
		throws CodedMessageException {
		try {
			Document document = save0(messageList);
			Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			transformer.transform(new DOMSource(document), new StreamResult(writer));
		} catch (TransformerException e) {
			throw new CodedMessageException(e, "CodedMessage.SaveXMLError");
		}
	}

	/**
	 * 保存到文件。
	 *
	 * @param messageList
	 *            消息记录组
	 * @param writer
	 *            输出流
	 * @throws CodedMessageException
	 *             操作异常
	 */
	public static void save(final List<CodedMessage> messageList, final Writer writer)
		throws CodedMessageException {
		try {
			Document document = save0(messageList);
			Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			transformer.transform(new DOMSource(document), new StreamResult(writer));
		} catch (TransformerException e) {
			throw new CodedMessageException(e, "CodedMessage.SaveXMLError");
		}
	}

	private static Document save0(final List<CodedMessage> messageList)
		throws CodedMessageException {
		try {
			DocumentBuilder builder = DOM_FACTORY.newDocumentBuilder();
			Document document = builder.newDocument();
			Element messagesElement = document.createElement("messages");
			document.appendChild(messagesElement);
			for (CodedMessage message : messageList) {
				messagesElement.appendChild(save1(message, document));
			}
			return document;
		} catch (ParserConfigurationException e) {
			throw new CodedMessageException(e, "CodedMessage.SaveXMLError");
		}
	}

	private static Element save1(final CodedMessage message, final Document document) {
		Element messageElement = document.createElement("message");
		messageElement.setAttribute("time", Long.toString(message.getTime()));
		messageElement.setAttribute("code", message.getCode());
		messageElement.setAttribute("level", Integer.toString(message.getLevel().getCode()));
		for (String argument : message.getArguments()) {
			Element argumentElement = document.createElement("argument");
			messageElement.appendChild(argumentElement);
			argumentElement.setTextContent(argument);
		}
		for (String unformattedArgument : message.getUnformattedArguments()) {
			Element unformattedArgumentElement = document.createElement("unformattedArgument");
			messageElement.appendChild(unformattedArgumentElement);
			unformattedArgumentElement.setTextContent(unformattedArgument);
		}
		for (CodedMessage childMessage : message.getMessages()) {
			messageElement.appendChild(save1(childMessage, document));
		}
		return messageElement;
	}
}


package io.graceland.filter;

import java.util.EnumSet;
import javax.servlet.DispatcherType;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;

/**
 * Holds the URL patterns that a filter will be associated with.
 *
 * @see io.graceland.filter.FilterSpec
 */
public class FilterPattern {
    public static final EnumSet<DispatcherType> DEFAULT_DISPATCHER_TYPES = EnumSet.allOf(DispatcherType.class);
    public static final boolean DEFAULT_MATCH_AFTER = true;

    private final EnumSet<DispatcherType> dispatcherTypes;
    private final boolean matchAfter;
    private final ImmutableList<String> urlPatterns;

    FilterPattern(EnumSet<DispatcherType> dispatcherTypes, boolean matchAfter, ImmutableList<String> urlPatterns) {
        Preconditions.checkNotNull(dispatcherTypes, "Dispatcher Types cannot be null.");
        Preconditions.checkNotNull(urlPatterns, "URL Patterns cannot be null.");

        Preconditions.checkArgument(!dispatcherTypes.isEmpty(), "Dispatcher Arguments cannot be empty");
        Preconditions.checkArgument(!urlPatterns.isEmpty(), "URL Patterns cannot be empty");

        this.dispatcherTypes = dispatcherTypes;
        this.matchAfter = matchAfter;
        this.urlPatterns = urlPatterns;
    }

    /**
     * Returns a new instance of FilterPattern, using the passed in arguments.
     */
    public static FilterPattern newInstance(
            EnumSet<DispatcherType> dispatcherTypes,
            boolean matchAfter,
            Iterable<String> patterns) {

        return new FilterPattern(dispatcherTypes, matchAfter, ImmutableList.copyOf(patterns));
    }

    /**
     * Returns a new instance of FilterPattern, using the passed in arguments.
     */
    public static FilterPattern newInstance(
            EnumSet<DispatcherType> dispatcherTypes,
            boolean matchAfter,
            String... patterns) {

        return new FilterPattern(dispatcherTypes, matchAfter, ImmutableList.copyOf(patterns));
    }

    /**
     * Returns a new intance of FitlerPattern using default values and the patterns passed in.
     *

     * The default values are {@link io.graceland.filter.FilterPattern#DEFAULT_DISPATCHER_TYPES} and
     * {@link io.graceland.filter.FilterPattern#DEFAULT_MATCH_AFTER}.
     *
     * @param patterns The URL patterns to use.
     */
    public static FilterPattern forPatterns(String... patterns) {
        return new FilterPattern(DEFAULT_DISPATCHER_TYPES, DEFAULT_MATCH_AFTER, ImmutableList.copyOf(patterns));
    }

    /**
     * Returns a new intance of FitlerPattern using default values and the patterns passed in.
     *

     * The default values are {@link io.graceland.filter.FilterPattern#DEFAULT_DISPATCHER_TYPES} and
     * {@link io.graceland.filter.FilterPattern#DEFAULT_MATCH_AFTER}.
     *
     * @param patterns The URL patterns to use.
     */
    public static FilterPattern forPatterns(Iterable<String> patterns) {
        return new FilterPattern(DEFAULT_DISPATCHER_TYPES, DEFAULT_MATCH_AFTER, ImmutableList.copyOf(patterns));
    }

    public EnumSet<DispatcherType> getDispatcherTypes() {
        return dispatcherTypes;
    }

    public boolean isMatchAfter() {
        return matchAfter;
    }

    public ImmutableList<String> getUrlPatterns() {
        return urlPatterns;
    }
}


/*
 * Copyright(C) 2008 Matrix
 * All right reserved.
 */
package net.matrix.app.configuration;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.configuration.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;

import net.matrix.app.repository.ResourceContext;
import net.matrix.app.repository.ResourceContextConfig;
import net.matrix.app.repository.ResourceRepository;
import net.matrix.app.repository.ResourceSelection;
import net.matrix.configuration.ReloadableConfigurationContainer;

/**
 * 配置仓库加载环境，加载和缓存配置信息。
 */
public final class ConfigurationContext
	extends ResourceContext {
	/**
	 * 日志记录器。
	 */
	private static final Logger LOG = LoggerFactory.getLogger(ConfigurationContext.class);

	/**
	 * 缓存的配置信息。
	 */
	private Map<Resource, ReloadableConfigurationContainer> containerCache;

	/**
	 * 根据必要信息构造。
	 *
	 * @param repository
	 *            资源仓库
	 * @param contextConfig
	 *            资源仓库加载环境配置
	 */
	public ConfigurationContext(final ResourceRepository repository, final ResourceContextConfig contextConfig) {
		super(repository, contextConfig);
		this.containerCache = new ConcurrentHashMap<>();
	}

	/**
	 * 从资源仓库的某位置加载。
	 *
	 * @param repository
	 *            资源仓库
	 * @param selection
	 *            资源仓库选择
	 * @return 加载环境
	 * @throws ConfigurationException
	 *             加载错误
	 */
	public static ConfigurationContext load(final ResourceRepository repository, final ResourceSelection selection)
		throws ConfigurationException {
		LOG.debug("从 {} 加载配置集合", selection);
		Resource resource = repository.getResource(selection);
		if (resource == null) {
			throw new ConfigurationException(selection + " 解析失败");
		}
		ResourceContextConfig contextConfig = new ResourceContextConfig();
		contextConfig.load(resource);
		return new ConfigurationContext(repository, contextConfig);
	}

	/**
	 * 重新加载配置，清空缓存。
	 */
	@Override
	public void reload() {
		super.reload();
		containerCache = new ConcurrentHashMap<>();
		LOG.info("重新加载配置，清空缓存。");
	}

	/**
	 * 定位配置资源。
	 *
	 * @param selection
	 *            配置资源选择
	 * @return 配置资源
	 * @throws ConfigurationException
	 *             配置错误
	 */
	public Resource getConfigurationResource(final ResourceSelection selection)
		throws ConfigurationException {
		Resource resource = getResource(selection);
		if (resource == null) {
			String catalog = selection.getCatalog();
			String version = selection.getVersion();
			String name = selection.getName();
			throw new ConfigurationException("未找到类别 " + catalog + " 版本 " + version + " 的配置 " + name);
		}
		return resource;
	}

	/**
	 * 加载配置资源，返回配置对象。
	 *
	 * @param <T>
	 *            配置对象的类型
	 * @param type
	 *            配置对象的类型
	 * @param selection
	 *            配置资源选择
	 * @return 配置对象
	 * @throws ConfigurationException
	 *             配置错误
	 */
	public <T extends ReloadableConfigurationContainer> T getConfiguration(final Class<T> type, final ResourceSelection selection)
		throws ConfigurationException {
		Resource resource = getConfigurationResource(selection);
		T container = (T) containerCache.get(resource);
		if (container != null) {
			container.checkReload();
			return container;
		}
		synchronized (containerCache) {
			container = (T) containerCache.get(resource);
			if (container != null) {
				container.checkReload();
				return container;
			}
			try {
				container = type.newInstance();
			} catch (ReflectiveOperationException e) {
				throw new ConfigurationException("配置类 " + type.getName() + " 实例化失败", e);
			}
			// 加载配置
			LOG.debug("从 {}({}) 加载配置", selection, resource);
			try {
				container.load(resource);
			} catch (ConfigurationException e) {
				throw new ConfigurationException("配置 " + resource.getDescription() + " 加载错误", e);
			}
			containerCache.put(resource, container);
			return container;
		}
	}
}


/*
 * Copyright (C) 2011 Eiichiro Uchiumi. All Rights Reserved.
 *
 * 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.eiichiro.reverb.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * {@code ConstructorInvocation} represents a constructor invocation.
 *
 * @author Eiichiro Uchiumi
 */
public class ConstructorInvocation<T> implements Invocation<T> {

	private final Constructor<T> constructor;

	private final Object[] args;

	/**
	 * Constructs a new {@code ConstructorInvocation} with the specified
	 * constructor.
	 *
	 * @param constructor The constructor to be invoked.
	 */
	public ConstructorInvocation(Constructor<T> constructor) {
		this.constructor = constructor;
		args = new Object[0];
	}

	/**
	 * Constructs a new {@code ConstructorInvocation} with the specified
	 * class, parameter types and arguments.
	 *
	 * @param clazz The class that the constructor is invoked.
	 * @param parameterTypes The array of parameter type to specify the
	 * constructor.
	 * @param args The arguments to be passed to the constructor.
	 * @throws NoSuchMethodException If the constructor is not declared on the
	 * specified class.
	 */
	public ConstructorInvocation(Class<T> clazz, Class<?>[] parameterTypes,
			Object[] args) throws NoSuchMethodException {
		constructor = clazz.getConstructor(parameterTypes);
		this.args = args;
	}

	/**
	 * Constructs a new {@code ConstructorInvocation} with the specified
	 * class and arguments.
	 *
	 * @param clazz The class that the constructor is invoked.
	 * @param args The arguments to be passed to the constructor.
	 * @throws NoSuchMethodException If the constructor is not declared on the
	 * specified class.
	 */
	public ConstructorInvocation(Class<T> clazz, Object[] args)
			throws NoSuchMethodException {
		Class<?>[] parameterTypes = new Class<?>[args.length];

		for (int i = 0; i < args.length; i++) {
			parameterTypes[i] = args[i].getClass();
		}

		constructor = clazz.getConstructor(parameterTypes);
		this.args = args;
	}

	/**
	 * Proceeds this constructor invocation.
	 *
	 * @return The instance of the specified class.
	 * @throws Throwable If any exceptions occur while this invocation is
	 * proceeding.
	 */
	public T proceed() throws Throwable {
		try {
			return constructor().newInstance(args);
		} catch (InvocationTargetException e) {
			throw e.getTargetException();
		}
	}

	/**
	 * Returns the constructor to be invoked.
	 *
	 * @return The constructor to be invoked.
	 */
	public Constructor<T> constructor() {
		return constructor;
	}

	/**
	 * Returns the arguments the constructor to be invoked with.
	 *
	 * @return The arguments the constructor to be invoked with.
	 */
	@Override
	public Object[] args() {
		return args;
	}

}