Skip to content

Commit

Permalink
Merge pull request #57 from alipay/20201030-multiAccountResouce
Browse files Browse the repository at this point in the history
20201030 multi account resouce
  • Loading branch information
quhongwei authored Nov 2, 2020
2 parents 7a89431 + dbe603a commit 77dc7dd
Show file tree
Hide file tree
Showing 12 changed files with 309 additions and 23 deletions.
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
<url>https://github.com/alipay/rdf-file</url>

<properties>
<rdf.file.core.version>2.2.7</rdf.file.core.version>
<rdf.file.oss.version>2.2.7</rdf.file.oss.version>
<rdf.file.sftp.version>2.2.7</rdf.file.sftp.version>
<rdf.file.core.version>2.2.8</rdf.file.core.version>
<rdf.file.oss.version>2.2.8</rdf.file.oss.version>
<rdf.file.sftp.version>2.2.8</rdf.file.sftp.version>
</properties>

<modules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@
import com.alipay.rdf.file.exception.RdfErrorEnum;
import com.alipay.rdf.file.exception.RdfFileException;
import com.alipay.rdf.file.init.RdfInit;
import com.alipay.rdf.file.interfaces.FileStorage;
import com.alipay.rdf.file.model.FileDefaultConfig;
import com.alipay.rdf.file.model.StorageConfig;
import com.alipay.rdf.file.resource.RdfInputStream;
import com.alipay.rdf.file.spi.RdfFileResourceSpi;
import com.alipay.rdf.file.util.RdfFileLogUtil;
import com.alipay.rdf.file.util.RdfFileUtil;

import java.util.Collections;
import java.util.Map;
import java.util.Queue;
import java.util.WeakHashMap;

/**
* Copyright (C) 2013-2018 Ant Financial Services Group
*
Expand All @@ -18,7 +25,13 @@
public class ResourceLoader {
private static final String DEFAULT_TYPE = "classpath";

private static final String SPLIT = ":";
private static final String SPLIT = ":";
// 扩展配置项key,同种协议可以指定不同配置
private static final String RESOURCE_KEY = "resourceKey";

private static final Map<String, RdfFileResourceSpi> RESOURCE_CACHE = Collections.synchronizedMap(new WeakHashMap<String, RdfFileResourceSpi>());

private static final Object LOCK = new Object();

@SuppressWarnings({ "rawtypes", "unchecked" })
public static RdfInputStream getInputStream(String path) {
Expand All @@ -28,6 +41,7 @@ public static RdfInputStream getInputStream(String path) {
int idx = path.indexOf(SPLIT);

String resourceType = null;
String resourceValue = RdfFileUtil.parsePathParams(path).get(RESOURCE_KEY);

if (idx < 0) {
resourceType = DEFAULT_TYPE;
Expand All @@ -36,19 +50,45 @@ public static RdfInputStream getInputStream(String path) {
path = path.substring(idx + 1);
}

RdfFileResourceSpi rdfResource = ExtensionLoader
.getExtensionLoader(RdfFileResourceSpi.class).getExtension(resourceType);

if (null == rdfResource) {
throw new RdfFileException("rdf-file#ResourceLoader.getInputStream(path=" + path
+ ") resourceType=" + resourceType + "没有对应的实现!",
RdfErrorEnum.NOT_EXSIT);
idx = path.indexOf(RdfFileUtil.QUESTION);
if (idx > -1) {
path = path.substring(idx + 1);
}

rdfResource.resourceType(resourceType);
String cacheKey = resourceType + (resourceValue == null ? RdfFileUtil.EMPTY : resourceValue);

if (rdfResource instanceof RdfInit) {
((RdfInit) rdfResource).init(FileDefaultConfig.DEFAULT_FILE_PARAMS.get(resourceType));
RdfFileResourceSpi rdfResource = RESOURCE_CACHE.get(cacheKey);

if (null == rdfResource) {
synchronized (LOCK) {
rdfResource = RESOURCE_CACHE.get(cacheKey);
if (null == rdfResource) {
rdfResource = ExtensionLoader.getExtensionLoader(RdfFileResourceSpi.class).getNewExtension(resourceType);

if (null == rdfResource) {
throw new RdfFileException("rdf-file#ResourceLoader.getInputStream(path=" + path
+ ") resourceType=" + resourceType + "没有对应的实现!",
RdfErrorEnum.NOT_EXSIT);
}

rdfResource.resourceType(resourceType);

if (rdfResource instanceof RdfInit) {
Object configValue = null;
if (RdfFileUtil.isNotBlank(resourceValue)) {
// 指定了特殊配置
configValue = FileDefaultConfig.DEFAULT_FILE_PARAMS.get(resourceValue);
}
if (null == configValue) {
// 使用协议通用配置
configValue = FileDefaultConfig.DEFAULT_FILE_PARAMS.get(resourceType);
}
((RdfInit) rdfResource).init(configValue);
}

RESOURCE_CACHE.put(cacheKey, rdfResource);
}
}
}

return rdfResource.getInputStream(path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
*/
public class ClasspathRdfResource extends AbstractRdfResources {

/**
* @see com.alipay.rdf.file.spi.RdfFileResourceSpi#getInputStream()
*/
@Override
public RdfInputStream getInputStream(String path) {
InputStream is = RdfFileUtil.getDefaultClassLoader().getResourceAsStream(path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public interface RdfFileResourceSpi extends RdfInit<StorageConfig> {
/**
* 资源加载类型
*
* @param type
* @param resourceType
*/
void resourceType(String resourceType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import java.math.BigDecimal;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Copyright (C) 2013-2018 Ant Financial Services Group
Expand All @@ -24,10 +26,16 @@
* @version $Id: RdfUtil.java, v 0.1 2017年8月8日 上午11:29:42 hongwei.quhw Exp $
*/
public class RdfFileUtil {
private static final String EMPTY = "";
public static final String EMPTY = "";

private static final int BUF_SIZE = 8192;

private static final String AMPERSAND = "&";

private static final String EQUALS = "=";

public static final String QUESTION = "?";

public static String trimNotNull(String text) {
if (null == text) {
return null;
Expand Down Expand Up @@ -787,4 +795,30 @@ public static String humanReadableByteCount(long bytes, boolean si) {
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}

public static Map<String, String> parsePathParams(String path) {
Map<String, String> params = new HashMap<String, String>();

if (isBlank(path)) {
return params;
}

int idx = path.indexOf(QUESTION);
if (idx < 0) {
return params;
}

path = path.substring(idx + 1);
String[] pairs = path.split(AMPERSAND);
for (String pair : pairs) {
String[] param = split(pair, EQUALS);
if (param.length == 2) {
params.put(param[0], param[1]);
} else {
throw new RdfFileException("path=" + path + ", parseParams format error, it has not valid param pairs ", RdfErrorEnum.ILLEGAL_ARGUMENT);
}
}

return params;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* Alipay.com Inc.
* Copyright (c) 2004-2020 All Rights Reserved.
*/
package com.alipay.rdf.file.loader;

import com.alipay.rdf.file.model.FileDefaultConfig;
import com.alipay.rdf.file.model.StorageConfig;
import com.alipay.rdf.file.resource.TestResource;
import com.alipay.rdf.file.spi.RdfFileResourceSpi;
import org.junit.Assert;
import org.junit.Test;

import java.lang.reflect.Field;
import java.util.Map;

import static com.alipay.rdf.file.loader.ResourceLoader.getInputStream;

/**
* Copyright (C) 2013-2018 Ant Financial Services Group
*
* @author quhongwei
* @version : ResourceLoaderTest.java, v 0.1 2020年11月01日 09:19 quhongwei Exp $
*/
public class ResourceLoaderTest {

@Test
public void testGetInputStreamResourceKey() throws Exception{

FileDefaultConfig.DEFAULT_FILE_PARAMS.remove("key1");
FileDefaultConfig.DEFAULT_FILE_PARAMS.remove("key1");
FileDefaultConfig.DEFAULT_FILE_PARAMS.remove("testResource");

Field field = ResourceLoader.class.getDeclaredField("RESOURCE_CACHE");
field.setAccessible(true);

Map<String, RdfFileResourceSpi> resourceMap = ( Map<String, RdfFileResourceSpi>)field.get(null);

getInputStream("aa/bb/cc/dd.json");
Assert.assertNotNull(resourceMap.get("classpath"));

getInputStream("classpath:aa/bb/cc/dd.json");
Assert.assertNotNull(resourceMap.get("classpath"));

getInputStream("classpath:aa/bb/cc/dd.json?resourceKey=hzconfig");
Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathhzconfig"));

getInputStream("classpath:aa/bb/cc/dd.json?resourceKey=shconfig");
Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathshconfig"));

getInputStream("classpath:aa/bb/cc/dd.json?resourceKey=shconfig&xx=dd");
Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathhzconfig"));
Assert.assertNotNull(resourceMap.get("classpathshconfig"));


TestResource.TestInputStream testInputStream = (TestResource.TestInputStream)ResourceLoader.getInputStream("testResource:aa/bb/cc/dd.json");

Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathhzconfig"));
Assert.assertNotNull(resourceMap.get("classpathshconfig"));
Assert.assertNotNull(resourceMap.get("testResource"));

Assert.assertEquals("testResource", testInputStream.getResourceType());
Assert.assertEquals("aa/bb/cc/dd.json", testInputStream.getPath());
Assert.assertNull( testInputStream.getConfig());

FileDefaultConfig.DEFAULT_FILE_PARAMS.put("testResource", new StorageConfig("nas") {
{
addParam("type", "testResource");
}
});

FileDefaultConfig.DEFAULT_FILE_PARAMS.put("key1", new StorageConfig("nas") {
{
addParam("type", "key1");
}
});

FileDefaultConfig.DEFAULT_FILE_PARAMS.put("key2", new StorageConfig("nas") {
{
addParam("type", "key2");
}
});

testInputStream = (TestResource.TestInputStream)ResourceLoader.getInputStream("testResource:aa/bb/cc/dd.json?resourceKey=key1");
Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathhzconfig"));
Assert.assertNotNull(resourceMap.get("classpathshconfig"));
Assert.assertNotNull(resourceMap.get("testResource"));
Assert.assertNotNull(resourceMap.get("testResourcekey1"));

RdfFileResourceSpi pre = resourceMap.get("testResourcekey1");

// 重复看看缓存
testInputStream = (TestResource.TestInputStream)ResourceLoader.getInputStream("testResource:aa/bb/cc/dd.json?resourceKey=key1");
Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathhzconfig"));
Assert.assertNotNull(resourceMap.get("classpathshconfig"));
Assert.assertNotNull(resourceMap.get("testResource"));
Assert.assertNotNull(resourceMap.get("testResourcekey1"));
Assert.assertEquals("key1", testInputStream.getConfig().getParam("type"));
Assert.assertEquals(pre, resourceMap.get("testResourcekey1"));

testInputStream = (TestResource.TestInputStream)ResourceLoader.getInputStream("testResource:aa/bb/cc/dd.json?resourceKey=key2");
Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathhzconfig"));
Assert.assertNotNull(resourceMap.get("classpathshconfig"));
Assert.assertNotNull(resourceMap.get("testResource"));
Assert.assertNotNull(resourceMap.get("testResourcekey1"));
Assert.assertNotNull(resourceMap.get("testResourcekey2"));
Assert.assertEquals("key2", testInputStream.getConfig().getParam("type"));

testInputStream = (TestResource.TestInputStream)ResourceLoader.getInputStream("testResource:aa/bb/cc/dd.json?resourceKey=key3");
Assert.assertNotNull(resourceMap.get("classpath"));
Assert.assertNotNull(resourceMap.get("classpathhzconfig"));
Assert.assertNotNull(resourceMap.get("classpathshconfig"));
Assert.assertNotNull(resourceMap.get("testResource"));
Assert.assertNotNull(resourceMap.get("testResourcekey1"));
Assert.assertNotNull(resourceMap.get("testResourcekey2"));
Assert.assertNotNull(resourceMap.get("testResourcekey3"));
Assert.assertEquals("testResource", testInputStream.getConfig().getParam("type"));

FileDefaultConfig.DEFAULT_FILE_PARAMS.remove("key1");
FileDefaultConfig.DEFAULT_FILE_PARAMS.remove("key2");
FileDefaultConfig.DEFAULT_FILE_PARAMS.remove("testResource");

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Alipay.com Inc.
* Copyright (c) 2004-2020 All Rights Reserved.
*/
package com.alipay.rdf.file.resource;

import com.alipay.rdf.file.model.StorageConfig;
import com.alipay.rdf.file.spi.RdfFileResourceSpi;

import java.io.IOException;
import java.io.InputStream;

/**
* Copyright (C) 2013-2018 Ant Financial Services Group
*
* @author quhongwei
* @version : TestResource.java, v 0.1 2020年11月01日 09:48 quhongwei Exp $
*/
public class TestResource extends AbstractRdfResources {
@Override
public RdfInputStream getInputStream(String path) {
return new TestInputStream(storageConfig, resourceType, path);
}

public static class TestInputStream extends RdfInputStream {
private final StorageConfig config;
private final String resourceType;
private final String path;

public TestInputStream(StorageConfig config, String resourceType, String path) {
super(new InputStream() {
@Override
public int read() throws IOException {
return 0;
}
});
this.config = config;
this.resourceType = resourceType;
this.path = path;
}

public StorageConfig getConfig() {
return config;
}

public String getResourceType() {
return resourceType;
}

public String getPath() {
return path;
}
}
}
Loading

0 comments on commit 77dc7dd

Please sign in to comment.