imario 2004/06/28 12:47:05
Modified: vfs/src/java/org/apache/commons/vfs Resources.properties
Added: vfs/src/java/org/apache/commons/vfs/util
DelegatingFileSystemOptionsBuilder.java
vfs/src/test/org/apache/commons/vfs/util
DelegatingFileSystemOptionsBuilderTest.java
Log:
DelegatingFileSystemOptionsBuilder
Helper to set the filesystem the options using key/value strings. It could be used
e.g. for configurations set by ant
Revision Changes Path
1.1
jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilder.java
Index: DelegatingFileSystemOptionsBuilder.java
===================================================================
/*
* Copyright 2002, 2003,2004 The Apache Software Foundation.
*
* 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.apache.commons.vfs.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs.FileSystemConfigBuilder;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileSystemOptions;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* This class use reflection to set a configuration value using the
fileSystemConfigBuilder
* associated the a scheme.<br><br>
* Example:<br>
* <code>
* FileSystemOptions fso = new FileSystemOptions();
* DelegatingFileSystemOptionsBuilder delegate = new
DelegatingFileSystemOptionsBuilder(VFS.getManager());
* delegate.setConfigString(fso, "sftp", "identities", "c:/tmp/test.ident");
* delegate.setConfigString(fso, "http", "proxyPort", "8080");
* delegate.setConfigClass(fso, "sftp", "userinfo", TrustEveryoneUserInfo.class);
* </code>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Mario Ivankovits</a>
* @version $Revision: 1.1 $ $Date: 2004/06/28 19:47:05 $
*/
public class DelegatingFileSystemOptionsBuilder
{
private Log log = LogFactory.getLog(DelegatingFileSystemOptionsBuilder.class);
private final static Class[] STRING_PARAM = new Class[]{String.class};
private final FileSystemManager manager;
private final Map beanMethods = new TreeMap();
private final static Map primitiveToObject = new TreeMap();
static
{
primitiveToObject.put(Void.TYPE.getName(), Void.class);
primitiveToObject.put(Boolean.TYPE.getName(), Boolean.class);
primitiveToObject.put(Byte.TYPE.getName(), Byte.class);
primitiveToObject.put(Character.TYPE.getName(), Character.class);
primitiveToObject.put(Short.TYPE.getName(), Short.class);
primitiveToObject.put(Integer.TYPE.getName(), Integer.class);
primitiveToObject.put(Long.TYPE.getName(), Long.class);
primitiveToObject.put(Double.TYPE.getName(), Double.class);
primitiveToObject.put(Float.TYPE.getName(), Float.class);
}
private static class Context
{
private final FileSystemOptions fso;
private final String scheme;
private final String name;
private final Object[] values;
private List configSetters;
private FileSystemConfigBuilder fileSystemConfigBuilder;
private Context(final FileSystemOptions fso, final String scheme, final
String name, final Object[] values)
{
this.fso = fso;
this.scheme = scheme;
this.name = name;
this.values = values;
}
}
/**
* Constructor.<br>
* Pass in your fileSystemManager instance.
*
* @param manager the manager to use to get the fileSystemConfigBuilder
assocated to a scheme
*/
public DelegatingFileSystemOptionsBuilder(final FileSystemManager manager)
{
this.manager = manager;
}
protected FileSystemManager getManager()
{
return manager;
}
/**
* Set a single string value.
*
* @param fso FileSystemOptions
* @param scheme scheme
* @param name name
* @param value value
*/
public void setConfigString(final FileSystemOptions fso, final String scheme,
final String name, final String value) throws FileSystemException
{
setConfigStrings(fso, scheme, name, new String[]{value});
}
/**
* Set an array of string value.
*
* @param fso FileSystemOptions
* @param scheme scheme
* @param name name
* @param values values
*/
public void setConfigStrings(final FileSystemOptions fso, final String scheme,
final String name, final String[] values) throws FileSystemException
{
Context ctx = new Context(fso, scheme, name, values);
setValues(ctx);
}
/**
* Set a single class value.<br>
* The class has to implement a no-args constructor, else the instantiation
might fail.
*
* @param fso FileSystemOptions
* @param scheme scheme
* @param name name
* @param className className
*/
public void setConfigClass(final FileSystemOptions fso, final String scheme,
final String name, final Class className) throws FileSystemException,
IllegalAccessException, InstantiationException
{
setConfigClasses(fso, scheme, name, new Class[]{className});
}
/**
* Set an array of class values.<br>
* The class has to implement a no-args constructor, else the instantiation
might fail.
*
* @param fso FileSystemOptions
* @param scheme scheme
* @param name name
* @param classNames classNames
*/
public void setConfigClasses(final FileSystemOptions fso, final String scheme,
final String name, final Class[] classNames) throws FileSystemException,
IllegalAccessException, InstantiationException
{
Object values[] = new Object[classNames.length];
for (int iterClassNames = 0; iterClassNames < values.length;
iterClassNames++)
{
values[iterClassNames] = classNames[iterClassNames].newInstance();
}
Context ctx = new Context(fso, scheme, name, values);
setValues(ctx);
}
/**
* sets the values using the informations of the given context.<br>
*/
private void setValues(Context ctx) throws FileSystemException
{
// find all setter methods suitable for the given "name"
if (!fillConfigSetters(ctx))
{
throw new FileSystemException("vfs.provider/config-key-invalid.error",
new String[]
{
ctx.scheme,
ctx.name
});
}
// get the fileSystemConfigBuilder
ctx.fileSystemConfigBuilder =
getManager().getFileSystemConfigBuilder(ctx.scheme);
// try to find a setter which could accept the value
Iterator iterConfigSetters = ctx.configSetters.iterator();
while (iterConfigSetters.hasNext())
{
Method configSetter = (Method) iterConfigSetters.next();
if (convertValuesAndInvoke(configSetter, ctx))
{
return;
}
}
throw new FileSystemException("vfs.provider/config-value-invalid.error", new
Object[]
{
ctx.scheme,
ctx.name,
ctx.values
});
}
/**
* tries to convert the value and pass it to the given method
*/
private boolean convertValuesAndInvoke(final Method configSetter, final Context
ctx) throws FileSystemException
{
Class parameters[] = configSetter.getParameterTypes();
if (parameters.length < 2)
{
return false;
}
if (!parameters[0].isAssignableFrom(FileSystemOptions.class))
{
return false;
}
Class valueParameter = parameters[1];
Class type;
if (valueParameter.isArray())
{
type = valueParameter.getComponentType();
}
else
{
if (ctx.values.length > 1)
{
return false;
}
type = valueParameter;
}
if (type.isPrimitive())
{
Class objectType = (Class) primitiveToObject.get(type.getName());
if (objectType == null)
{
log.warn(Messages.getString("vfs.provider/config-unexpected-primitive.error",
type.getName()));
return false;
}
type = objectType;
}
Class valueClass = ctx.values[0].getClass();
if (type.isAssignableFrom(valueClass))
{
// can set value directly
invokeSetter(valueParameter, ctx, configSetter, ctx.values);
return true;
}
if (valueClass != String.class)
{
log.warn(Messages.getString("vfs.provider/config-unexpected-value-class.error", new
String[]
{
valueClass.getName(),
ctx.scheme,
ctx.name
}));
return false;
}
Object convertedValues = java.lang.reflect.Array.newInstance(type,
ctx.values.length);
Constructor valueConstructor;
try
{
valueConstructor = type.getConstructor(STRING_PARAM);
}
catch (NoSuchMethodException e)
{
valueConstructor = null;
}
if (valueConstructor != null)
{
// can convert using constructor
for (int iterValues = 0; iterValues < ctx.values.length; iterValues++)
{
try
{
Array.set(convertedValues, iterValues,
valueConstructor.newInstance(new Object[]{ctx.values[iterValues]}));
}
catch (InstantiationException e)
{
throw new FileSystemException(e);
}
catch (IllegalAccessException e)
{
throw new FileSystemException(e);
}
catch (InvocationTargetException e)
{
throw new FileSystemException(e);
}
}
invokeSetter(valueParameter, ctx, configSetter, convertedValues);
return true;
}
Method valueFactory;
try
{
valueFactory = type.getMethod("valueOf", STRING_PARAM);
if (!Modifier.isStatic(valueFactory.getModifiers()))
{
valueFactory = null;
}
}
catch (NoSuchMethodException e)
{
valueFactory = null;
}
if (valueFactory != null)
{
// can convert using factory method (valueOf)
for (int iterValues = 0; iterValues < ctx.values.length; iterValues++)
{
try
{
Array.set(convertedValues, iterValues, valueFactory.invoke(null,
new Object[]{ctx.values[iterValues]}));
}
catch (IllegalAccessException e)
{
throw new FileSystemException(e);
}
catch (InvocationTargetException e)
{
throw new FileSystemException(e);
}
}
invokeSetter(valueParameter, ctx, configSetter, convertedValues);
return true;
}
return false;
}
/**
* invokes the method with the converted values
*/
private void invokeSetter(Class valueParameter, final Context ctx, final Method
configSetter, final Object values)
throws FileSystemException
{
Object[] args;
if (valueParameter.isArray())
{
args = new Object[]
{
ctx.fso,
values
};
}
else
{
args = new Object[]
{
ctx.fso,
Array.get(values, 0)
};
}
try
{
configSetter.invoke(ctx.fileSystemConfigBuilder, args);
}
catch (IllegalAccessException e)
{
throw new FileSystemException(e);
}
catch (InvocationTargetException e)
{
throw new FileSystemException(e);
}
}
/**
* fills all available set*() methods for the context-scheme into the context.
*/
private boolean fillConfigSetters(final Context ctx)
throws FileSystemException
{
Map schemeMethods = getSchemeMethods(ctx.scheme);
List configSetters = (List) schemeMethods.get(ctx.name.toLowerCase());
if (configSetters == null)
{
return false;
}
ctx.configSetters = configSetters;
return true;
}
/**
* get (cached) list of set*() methods for the given scheme
*/
private Map getSchemeMethods(final String scheme) throws FileSystemException
{
Map schemeMethods = (Map) beanMethods.get(scheme);
if (schemeMethods == null)
{
schemeMethods = createSchemeMethods(scheme);
beanMethods.put(scheme, schemeMethods);
}
return schemeMethods;
}
/**
* create the list of all set*() methods for the given scheme
*/
private Map createSchemeMethods(String scheme) throws FileSystemException
{
final FileSystemConfigBuilder fscb =
getManager().getFileSystemConfigBuilder(scheme);
if (fscb == null)
{
throw new FileSystemException("vfs.provider/no-config-builder.error",
scheme);
}
Map schemeMethods = new TreeMap();
Method methods[] = fscb.getClass().getMethods();
for (int iterMethods = 0; iterMethods < methods.length; iterMethods++)
{
Method method = methods[iterMethods];
if (!Modifier.isPublic(method.getModifiers()))
{
continue;
}
String methodName = method.getName();
if (!methodName.startsWith("set"))
{
// not a setter
continue;
}
String key = methodName.substring(3).toLowerCase();
List configSetter = (List) schemeMethods.get(key);
if (configSetter == null)
{
configSetter = new ArrayList(2);
schemeMethods.put(key, configSetter);
}
configSetter.add(method);
}
return schemeMethods;
}
}
1.1
jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilderTest.java
Index: DelegatingFileSystemOptionsBuilderTest.java
===================================================================
/*
* Copyright 2002, 2003,2004 The Apache Software Foundation.
*
* 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.apache.commons.vfs.util;
import junit.framework.TestCase;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.impl.StandardFileSystemManager;
import org.apache.commons.vfs.provider.http.HttpFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.sftp.TrustEveryoneUserInfo;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
/**
* Some tests for the DelegatingFileSystemOptionsBuilder
*
* @author <a href="mailto:[EMAIL PROTECTED]">Mario Ivankovits</a>
* @version $Revision: 1.1 $ $Date: 2004/06/28 19:47:05 $
*/
public class DelegatingFileSystemOptionsBuilderTest extends TestCase
{
private StandardFileSystemManager fsm = null;
protected void setUp() throws Exception
{
super.tearDown();
// get a full blown, fully functional manager
fsm = new StandardFileSystemManager();
fsm.init();
}
protected void tearDown() throws Exception
{
if (fsm != null)
{
fsm.close();
}
super.tearDown();
}
public void testDelegatingGood() throws Throwable
{
final String[] identityPaths = new String[]
{
"/file1",
"/file2",
};
FileSystemOptions opts = new FileSystemOptions();
DelegatingFileSystemOptionsBuilder delgate = new
DelegatingFileSystemOptionsBuilder(fsm);
delgate.setConfigString(opts, "http", "proxyHost", "proxy");
delgate.setConfigString(opts, "http", "proxyPort", "8080");
delgate.setConfigClass(opts, "sftp", "userinfo",
TrustEveryoneUserInfo.class);
delgate.setConfigStrings(opts, "sftp", "identities", identityPaths);
assertEquals("http.proxyHost",
HttpFileSystemConfigBuilder.getInstance().getProxyHost(opts), "proxy");
assertEquals("http.proxyPort",
HttpFileSystemConfigBuilder.getInstance().getProxyPort(opts), 8080);
assertEquals("sftp.userInfo",
SftpFileSystemConfigBuilder.getInstance().getUserInfo(opts).getClass(),
TrustEveryoneUserInfo.class);
File identities[] =
SftpFileSystemConfigBuilder.getInstance().getIdentities(opts);
assertNotNull("sftp.identities", identities);
assertEquals("sftp.identities size", identities.length,
identityPaths.length);
for (int iterIdentities = 0; iterIdentities < identities.length;
iterIdentities++)
{
assertEquals("sftp.identities #" + iterIdentities,
identities[iterIdentities].getAbsolutePath(),
new File(identityPaths[iterIdentities]).getAbsolutePath());
}
}
public void testDelegatingBad() throws Throwable
{
FileSystemOptions opts = new FileSystemOptions();
DelegatingFileSystemOptionsBuilder delgate = new
DelegatingFileSystemOptionsBuilder(fsm);
try
{
delgate.setConfigString(opts, "http", "proxyPort", "wrong_port");
fail();
}
catch (FileSystemException e)
{
assertEquals(e.getCause().getClass(), InvocationTargetException.class);
assertEquals(e.getCause().getCause().getClass(),
NumberFormatException.class);
}
try
{
delgate.setConfigClass(opts, "sftp", "userinfo", String.class);
fail();
}
catch (FileSystemException e)
{
assertEquals(e.getCode(), "vfs.provider/config-value-invalid.error");
}
}
}
1.39 +6 -0
jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/Resources.properties
Index: Resources.properties
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/Resources.properties,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- Resources.properties 23 Jun 2004 18:17:44 -0000 1.38
+++ Resources.properties 28 Jun 2004 19:47:05 -0000 1.39
@@ -71,6 +71,12 @@
# AbstractFileSystemProvider
vfs.provider/invalid-absolute-uri.error=Invalid absolute URI "{0}".
vfs.provider/not-layered-fs.error=File system for URL scheme "{0}" is not a layered
file system.
+vfs.provider/no-config-builder.error=File provider for URL scheme "{0}" do not
provide a configuration builder.
+vfs.provider/config-key-invalid.error=The configuration builder for scheme "{0}"
has no option "{1}".
+vfs.provider/config-value-invalid.error=The delegating configuration builder cant
convert value "{2}" for key "{1}" scheme "{0}".
+vfs.provider/config-too-many-values.error=Too many values for configuration builder
for scheme "{0}" key "{1}".
+vfs.provider/config-unexpected-primitive.error=Unexpected primitive "{0}".
+vfs.provider/config-unexpected-value-class.error=Cant convert a "{0}" value for
scheme "{1}" key "{2}".
# AbstractFileSystem
vfs.provider/files-cache-missing.error=No files-cache implementation set.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]