/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* 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 com.alibaba.citrus.springext;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.ClassUtil.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamSource;
/**
* 这个接口的目的是取得configuration point/contribution所需要的一切资源文件,例如定义文件、schema文件等。
* 在不同的环境中,需要不同的实现。例如:
* <ul>
* <li>在应用程序的环境中,将从class loader来寻找和装载所有的资源文件。</li>
* <li>在IDE开发环境中(IDE plugins),每个IDE有自己不同的装载资源的方法。
* 每个IDE插件(例如Intellij IDE、Eclipse)需要实现自己的<code>ResourceResolver</code>来装载项目中的资源文件。</li>
* </ul>
* 默认的实现是用class loader来装载资源。
*
* @author Michael Zhou
*/
public abstract class ResourceResolver {
protected final Logger log = LoggerFactory.getLogger(getClass());
/**
* 取得指定位置的一个资源。
* 如果资源不存在,则返回<code>null</code>。
*/
public abstract Resource getResource(String location);
/**
* 找到所有符合名称的资源。支持同名资源的查找,例如,查找所有jar包中的/META-INF/spring.schemas文件。该方法还支持通配符。
*
* @throws IOException 如果在寻找过程中出错
*/
public abstract Resource[] getResources(String locationPattern) throws IOException;
/** 从<code>ResourceResolver</code>中读取所有指定名称的资源文件,对每一个key/value调用handler。 */
public final void loadAllProperties(String resourceName, PropertyHandler handler)
throws ConfigurationPointException {
assertNotNull(resourceName, "Resource name must not be null");
assertNotNull(handler, "No handler provided");
Map<String, Resource> keyToResources = createHashMap();
try {
for (Resource resource : getResources(resourceName)) {
Properties props = new Properties();
InputStream is = null;
try {
is = resource.getInputStream();
props.load(is);
for (Entry<Object, Object> entry : props.entrySet()) {
String key = (String) entry.getKey();
String value = (String) entry.getValue();
if (keyToResources.containsKey(key)) {
log.warn("Duplicated key \"{}\" in {} and {}", new Object[] { key, resource, keyToResources.get(key) });
} else {
keyToResources.put(key, resource);
handler.handle(key, value, resource, -1); // no line number supported in this implementation
}
}
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {
}
}
}
}
} catch (IOException e) {
throw new ConfigurationPointException("Unable to load data from " + resourceName, e);
}
}
public static abstract class Resource implements InputStreamSource {
public abstract String getName();
public abstract InputStream getInputStream() throws IOException;
@Override
public final String toString() {
String desc = getName();
return getSimpleClassName(getClass()) + (desc == null ? "" : "[" + desc + "]");
}
}
public static interface PropertyHandler {
void handle(String key, String value, Resource source, int lineNumber);
}
}