KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > vfs > util > DelegatingFileSystemOptionsBuilder


1 /*
2  * Copyright 2002-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.vfs.util;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.apache.commons.vfs.FileSystemConfigBuilder;
21 import org.apache.commons.vfs.FileSystemException;
22 import org.apache.commons.vfs.FileSystemManager;
23 import org.apache.commons.vfs.FileSystemOptions;
24
25 import java.lang.reflect.Array JavaDoc;
26 import java.lang.reflect.Constructor JavaDoc;
27 import java.lang.reflect.InvocationTargetException JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.lang.reflect.Modifier JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.TreeMap JavaDoc;
35
36 /**
37  * This class use reflection to set a configuration value using the fileSystemConfigBuilder
38  * associated the a scheme.<br><br>
39  * Example:<br>
40  * <pre>
41  * FileSystemOptions fso = new FileSystemOptions();
42  * DelegatingFileSystemOptionsBuilder delegate = new DelegatingFileSystemOptionsBuilder(VFS.getManager());
43  * delegate.setConfigString(fso, "sftp", "identities", "c:/tmp/test.ident");
44  * delegate.setConfigString(fso, "http", "proxyPort", "8080");
45  * delegate.setConfigClass(fso, "sftp", "userinfo", TrustEveryoneUserInfo.class);
46  * </pre>
47  *
48  * @author <a HREF="mailto:imario@apache.org">Mario Ivankovits</a>
49  */

50 public class DelegatingFileSystemOptionsBuilder
51 {
52     private Log log = LogFactory.getLog(DelegatingFileSystemOptionsBuilder.class);
53
54     private final static Class JavaDoc[] STRING_PARAM = new Class JavaDoc[]{String JavaDoc.class};
55
56     private final FileSystemManager manager;
57
58     private final Map JavaDoc beanMethods = new TreeMap JavaDoc();
59
60     private final static Map JavaDoc primitiveToObject = new TreeMap JavaDoc();
61
62     static
63     {
64         primitiveToObject.put(Void.TYPE.getName(), Void JavaDoc.class);
65         primitiveToObject.put(Boolean.TYPE.getName(), Boolean JavaDoc.class);
66         primitiveToObject.put(Byte.TYPE.getName(), Byte JavaDoc.class);
67         primitiveToObject.put(Character.TYPE.getName(), Character JavaDoc.class);
68         primitiveToObject.put(Short.TYPE.getName(), Short JavaDoc.class);
69         primitiveToObject.put(Integer.TYPE.getName(), Integer JavaDoc.class);
70         primitiveToObject.put(Long.TYPE.getName(), Long JavaDoc.class);
71         primitiveToObject.put(Double.TYPE.getName(), Double JavaDoc.class);
72         primitiveToObject.put(Float.TYPE.getName(), Float JavaDoc.class);
73     }
74
75     private static class Context
76     {
77         private final FileSystemOptions fso;
78         private final String JavaDoc scheme;
79         private final String JavaDoc name;
80         private final Object JavaDoc[] values;
81
82         private List JavaDoc configSetters;
83         private FileSystemConfigBuilder fileSystemConfigBuilder;
84
85         private Context(final FileSystemOptions fso, final String JavaDoc scheme, final String JavaDoc name, final Object JavaDoc[] values)
86         {
87             this.fso = fso;
88             this.scheme = scheme;
89             this.name = name;
90             this.values = values;
91         }
92     }
93
94     /**
95      * Constructor.<br>
96      * Pass in your fileSystemManager instance.
97      *
98      * @param manager the manager to use to get the fileSystemConfigBuilder assocated to a scheme
99      */

100     public DelegatingFileSystemOptionsBuilder(final FileSystemManager manager)
101     {
102         this.manager = manager;
103     }
104
105     protected FileSystemManager getManager()
106     {
107         return manager;
108     }
109
110     /**
111      * Set a single string value.
112      *
113      * @param fso FileSystemOptions
114      * @param scheme scheme
115      * @param name name
116      * @param value value
117      */

118     public void setConfigString(final FileSystemOptions fso, final String JavaDoc scheme, final String JavaDoc name, final String JavaDoc value) throws FileSystemException
119     {
120         setConfigStrings(fso, scheme, name, new String JavaDoc[]{value});
121     }
122
123     /**
124      * Set an array of string value.
125      *
126      * @param fso FileSystemOptions
127      * @param scheme scheme
128      * @param name name
129      * @param values values
130      */

131     public void setConfigStrings(final FileSystemOptions fso, final String JavaDoc scheme, final String JavaDoc name, final String JavaDoc[] values) throws FileSystemException
132     {
133         Context ctx = new Context(fso, scheme, name, values);
134
135         setValues(ctx);
136     }
137
138     /**
139      * Set a single class value.<br>
140      * The class has to implement a no-args constructor, else the instantiation might fail.
141      *
142      * @param fso FileSystemOptions
143      * @param scheme scheme
144      * @param name name
145      * @param className className
146      */

147     public void setConfigClass(final FileSystemOptions fso, final String JavaDoc scheme, final String JavaDoc name, final Class JavaDoc className) throws FileSystemException, IllegalAccessException JavaDoc, InstantiationException JavaDoc
148     {
149         setConfigClasses(fso, scheme, name, new Class JavaDoc[]{className});
150     }
151
152     /**
153      * Set an array of class values.<br>
154      * The class has to implement a no-args constructor, else the instantiation might fail.
155      *
156      * @param fso FileSystemOptions
157      * @param scheme scheme
158      * @param name name
159      * @param classNames classNames
160      */

161     public void setConfigClasses(final FileSystemOptions fso, final String JavaDoc scheme, final String JavaDoc name, final Class JavaDoc[] classNames) throws FileSystemException, IllegalAccessException JavaDoc, InstantiationException JavaDoc
162     {
163         Object JavaDoc values[] = new Object JavaDoc[classNames.length];
164         for (int iterClassNames = 0; iterClassNames < values.length; iterClassNames++)
165         {
166             values[iterClassNames] = classNames[iterClassNames].newInstance();
167         }
168
169         Context ctx = new Context(fso, scheme, name, values);
170
171         setValues(ctx);
172     }
173
174     /**
175      * sets the values using the informations of the given context.<br>
176      */

177     private void setValues(Context ctx) throws FileSystemException
178     {
179         // find all setter methods suitable for the given "name"
180
if (!fillConfigSetters(ctx))
181         {
182             throw new FileSystemException("vfs.provider/config-key-invalid.error", new String JavaDoc[]
183             {
184                 ctx.scheme,
185                 ctx.name
186             });
187         }
188
189         // get the fileSystemConfigBuilder
190
ctx.fileSystemConfigBuilder = getManager().getFileSystemConfigBuilder(ctx.scheme);
191
192         // try to find a setter which could accept the value
193
Iterator JavaDoc iterConfigSetters = ctx.configSetters.iterator();
194         while (iterConfigSetters.hasNext())
195         {
196             Method JavaDoc configSetter = (Method JavaDoc) iterConfigSetters.next();
197             if (convertValuesAndInvoke(configSetter, ctx))
198             {
199                 return;
200             }
201         }
202
203         throw new FileSystemException("vfs.provider/config-value-invalid.error", new Object JavaDoc[]
204         {
205             ctx.scheme,
206             ctx.name,
207             ctx.values
208         });
209     }
210
211     /**
212      * tries to convert the value and pass it to the given method
213      */

214     private boolean convertValuesAndInvoke(final Method JavaDoc configSetter, final Context ctx) throws FileSystemException
215     {
216         Class JavaDoc parameters[] = configSetter.getParameterTypes();
217         if (parameters.length < 2)
218         {
219             return false;
220         }
221         if (!parameters[0].isAssignableFrom(FileSystemOptions.class))
222         {
223             return false;
224         }
225
226         Class JavaDoc valueParameter = parameters[1];
227         Class JavaDoc type;
228         if (valueParameter.isArray())
229         {
230             type = valueParameter.getComponentType();
231         }
232         else
233         {
234             if (ctx.values.length > 1)
235             {
236                 return false;
237             }
238
239             type = valueParameter;
240         }
241
242         if (type.isPrimitive())
243         {
244             Class JavaDoc objectType = (Class JavaDoc) primitiveToObject.get(type.getName());
245             if (objectType == null)
246             {
247                 log.warn(Messages.getString("vfs.provider/config-unexpected-primitive.error", type.getName()));
248                 return false;
249             }
250             type = objectType;
251         }
252
253         Class JavaDoc valueClass = ctx.values[0].getClass();
254         if (type.isAssignableFrom(valueClass))
255         {
256             // can set value directly
257
invokeSetter(valueParameter, ctx, configSetter, ctx.values);
258             return true;
259         }
260         if (valueClass != String JavaDoc.class)
261         {
262             log.warn(Messages.getString("vfs.provider/config-unexpected-value-class.error", new String JavaDoc[]
263             {
264                 valueClass.getName(),
265                 ctx.scheme,
266                 ctx.name
267             }));
268             return false;
269         }
270
271         Object JavaDoc convertedValues = java.lang.reflect.Array.newInstance(type, ctx.values.length);
272
273         Constructor JavaDoc valueConstructor;
274         try
275         {
276             valueConstructor = type.getConstructor(STRING_PARAM);
277         }
278         catch (NoSuchMethodException JavaDoc e)
279         {
280             valueConstructor = null;
281         }
282         if (valueConstructor != null)
283         {
284             // can convert using constructor
285
for (int iterValues = 0; iterValues < ctx.values.length; iterValues++)
286             {
287                 try
288                 {
289                     Array.set(convertedValues, iterValues, valueConstructor.newInstance(new Object JavaDoc[]{ctx.values[iterValues]}));
290                 }
291                 catch (InstantiationException JavaDoc e)
292                 {
293                     throw new FileSystemException(e);
294                 }
295                 catch (IllegalAccessException JavaDoc e)
296                 {
297                     throw new FileSystemException(e);
298                 }
299                 catch (InvocationTargetException JavaDoc e)
300                 {
301                     throw new FileSystemException(e);
302                 }
303             }
304
305             invokeSetter(valueParameter, ctx, configSetter, convertedValues);
306             return true;
307         }
308
309         Method JavaDoc valueFactory;
310         try
311         {
312             valueFactory = type.getMethod("valueOf", STRING_PARAM);
313             if (!Modifier.isStatic(valueFactory.getModifiers()))
314             {
315                 valueFactory = null;
316             }
317         }
318         catch (NoSuchMethodException JavaDoc e)
319         {
320             valueFactory = null;
321         }
322
323         if (valueFactory != null)
324         {
325             // can convert using factory method (valueOf)
326
for (int iterValues = 0; iterValues < ctx.values.length; iterValues++)
327             {
328                 try
329                 {
330                     Array.set(convertedValues, iterValues, valueFactory.invoke(null, new Object JavaDoc[]{ctx.values[iterValues]}));
331                 }
332                 catch (IllegalAccessException JavaDoc e)
333                 {
334                     throw new FileSystemException(e);
335                 }
336                 catch (InvocationTargetException JavaDoc e)
337                 {
338                     throw new FileSystemException(e);
339                 }
340             }
341
342             invokeSetter(valueParameter, ctx, configSetter, convertedValues);
343             return true;
344         }
345
346         return false;
347     }
348
349     /**
350      * invokes the method with the converted values
351      */

352     private void invokeSetter(Class JavaDoc valueParameter, final Context ctx, final Method JavaDoc configSetter, final Object JavaDoc values)
353         throws FileSystemException
354     {
355         Object JavaDoc[] args;
356         if (valueParameter.isArray())
357         {
358             args = new Object JavaDoc[]
359             {
360                 ctx.fso,
361                 values
362             };
363         }
364         else
365         {
366             args = new Object JavaDoc[]
367             {
368                 ctx.fso,
369                 Array.get(values, 0)
370             };
371         }
372         try
373         {
374             configSetter.invoke(ctx.fileSystemConfigBuilder, args);
375         }
376         catch (IllegalAccessException JavaDoc e)
377         {
378             throw new FileSystemException(e);
379         }
380         catch (InvocationTargetException JavaDoc e)
381         {
382             throw new FileSystemException(e);
383         }
384     }
385
386     /**
387      * fills all available set*() methods for the context-scheme into the context.
388      */

389     private boolean fillConfigSetters(final Context ctx)
390         throws FileSystemException
391     {
392         Map JavaDoc schemeMethods = getSchemeMethods(ctx.scheme);
393         List JavaDoc configSetters = (List JavaDoc) schemeMethods.get(ctx.name.toLowerCase());
394         if (configSetters == null)
395         {
396             return false;
397         }
398
399         ctx.configSetters = configSetters;
400         return true;
401     }
402
403     /**
404      * get (cached) list of set*() methods for the given scheme
405      */

406     private Map JavaDoc getSchemeMethods(final String JavaDoc scheme) throws FileSystemException
407     {
408         Map JavaDoc schemeMethods = (Map JavaDoc) beanMethods.get(scheme);
409         if (schemeMethods == null)
410         {
411             schemeMethods = createSchemeMethods(scheme);
412             beanMethods.put(scheme, schemeMethods);
413         }
414
415         return schemeMethods;
416     }
417
418     /**
419      * create the list of all set*() methods for the given scheme
420      */

421     private Map JavaDoc createSchemeMethods(String JavaDoc scheme) throws FileSystemException
422     {
423         final FileSystemConfigBuilder fscb = getManager().getFileSystemConfigBuilder(scheme);
424         if (fscb == null)
425         {
426             throw new FileSystemException("vfs.provider/no-config-builder.error", scheme);
427         }
428
429         Map JavaDoc schemeMethods = new TreeMap JavaDoc();
430
431         Method JavaDoc methods[] = fscb.getClass().getMethods();
432         for (int iterMethods = 0; iterMethods < methods.length; iterMethods++)
433         {
434             Method JavaDoc method = methods[iterMethods];
435             if (!Modifier.isPublic(method.getModifiers()))
436             {
437                 continue;
438             }
439
440             String JavaDoc methodName = method.getName();
441             if (!methodName.startsWith("set"))
442             {
443                 // not a setter
444
continue;
445             }
446
447             String JavaDoc key = methodName.substring(3).toLowerCase();
448
449             List JavaDoc configSetter = (List JavaDoc) schemeMethods.get(key);
450             if (configSetter == null)
451             {
452                 configSetter = new ArrayList JavaDoc(2);
453                 schemeMethods.put(key, configSetter);
454             }
455             configSetter.add(method);
456         }
457
458         return schemeMethods;
459     }
460 }
461
Popular Tags