1 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 ; 26 import java.lang.reflect.Constructor ; 27 import java.lang.reflect.InvocationTargetException ; 28 import java.lang.reflect.Method ; 29 import java.lang.reflect.Modifier ; 30 import java.util.ArrayList ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.TreeMap ; 35 36 50 public class DelegatingFileSystemOptionsBuilder 51 { 52 private Log log = LogFactory.getLog(DelegatingFileSystemOptionsBuilder.class); 53 54 private final static Class [] STRING_PARAM = new Class []{String .class}; 55 56 private final FileSystemManager manager; 57 58 private final Map beanMethods = new TreeMap (); 59 60 private final static Map primitiveToObject = new TreeMap (); 61 62 static 63 { 64 primitiveToObject.put(Void.TYPE.getName(), Void .class); 65 primitiveToObject.put(Boolean.TYPE.getName(), Boolean .class); 66 primitiveToObject.put(Byte.TYPE.getName(), Byte .class); 67 primitiveToObject.put(Character.TYPE.getName(), Character .class); 68 primitiveToObject.put(Short.TYPE.getName(), Short .class); 69 primitiveToObject.put(Integer.TYPE.getName(), Integer .class); 70 primitiveToObject.put(Long.TYPE.getName(), Long .class); 71 primitiveToObject.put(Double.TYPE.getName(), Double .class); 72 primitiveToObject.put(Float.TYPE.getName(), Float .class); 73 } 74 75 private static class Context 76 { 77 private final FileSystemOptions fso; 78 private final String scheme; 79 private final String name; 80 private final Object [] values; 81 82 private List configSetters; 83 private FileSystemConfigBuilder fileSystemConfigBuilder; 84 85 private Context(final FileSystemOptions fso, final String scheme, final String name, final Object [] values) 86 { 87 this.fso = fso; 88 this.scheme = scheme; 89 this.name = name; 90 this.values = values; 91 } 92 } 93 94 100 public DelegatingFileSystemOptionsBuilder(final FileSystemManager manager) 101 { 102 this.manager = manager; 103 } 104 105 protected FileSystemManager getManager() 106 { 107 return manager; 108 } 109 110 118 public void setConfigString(final FileSystemOptions fso, final String scheme, final String name, final String value) throws FileSystemException 119 { 120 setConfigStrings(fso, scheme, name, new String []{value}); 121 } 122 123 131 public void setConfigStrings(final FileSystemOptions fso, final String scheme, final String name, final String [] values) throws FileSystemException 132 { 133 Context ctx = new Context(fso, scheme, name, values); 134 135 setValues(ctx); 136 } 137 138 147 public void setConfigClass(final FileSystemOptions fso, final String scheme, final String name, final Class className) throws FileSystemException, IllegalAccessException , InstantiationException 148 { 149 setConfigClasses(fso, scheme, name, new Class []{className}); 150 } 151 152 161 public void setConfigClasses(final FileSystemOptions fso, final String scheme, final String name, final Class [] classNames) throws FileSystemException, IllegalAccessException , InstantiationException 162 { 163 Object values[] = new Object [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 177 private void setValues(Context ctx) throws FileSystemException 178 { 179 if (!fillConfigSetters(ctx)) 181 { 182 throw new FileSystemException("vfs.provider/config-key-invalid.error", new String [] 183 { 184 ctx.scheme, 185 ctx.name 186 }); 187 } 188 189 ctx.fileSystemConfigBuilder = getManager().getFileSystemConfigBuilder(ctx.scheme); 191 192 Iterator iterConfigSetters = ctx.configSetters.iterator(); 194 while (iterConfigSetters.hasNext()) 195 { 196 Method configSetter = (Method ) 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 [] 204 { 205 ctx.scheme, 206 ctx.name, 207 ctx.values 208 }); 209 } 210 211 214 private boolean convertValuesAndInvoke(final Method configSetter, final Context ctx) throws FileSystemException 215 { 216 Class 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 valueParameter = parameters[1]; 227 Class 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 objectType = (Class ) 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 valueClass = ctx.values[0].getClass(); 254 if (type.isAssignableFrom(valueClass)) 255 { 256 invokeSetter(valueParameter, ctx, configSetter, ctx.values); 258 return true; 259 } 260 if (valueClass != String .class) 261 { 262 log.warn(Messages.getString("vfs.provider/config-unexpected-value-class.error", new String [] 263 { 264 valueClass.getName(), 265 ctx.scheme, 266 ctx.name 267 })); 268 return false; 269 } 270 271 Object convertedValues = java.lang.reflect.Array.newInstance(type, ctx.values.length); 272 273 Constructor valueConstructor; 274 try 275 { 276 valueConstructor = type.getConstructor(STRING_PARAM); 277 } 278 catch (NoSuchMethodException e) 279 { 280 valueConstructor = null; 281 } 282 if (valueConstructor != null) 283 { 284 for (int iterValues = 0; iterValues < ctx.values.length; iterValues++) 286 { 287 try 288 { 289 Array.set(convertedValues, iterValues, valueConstructor.newInstance(new Object []{ctx.values[iterValues]})); 290 } 291 catch (InstantiationException e) 292 { 293 throw new FileSystemException(e); 294 } 295 catch (IllegalAccessException e) 296 { 297 throw new FileSystemException(e); 298 } 299 catch (InvocationTargetException e) 300 { 301 throw new FileSystemException(e); 302 } 303 } 304 305 invokeSetter(valueParameter, ctx, configSetter, convertedValues); 306 return true; 307 } 308 309 Method 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 e) 319 { 320 valueFactory = null; 321 } 322 323 if (valueFactory != null) 324 { 325 for (int iterValues = 0; iterValues < ctx.values.length; iterValues++) 327 { 328 try 329 { 330 Array.set(convertedValues, iterValues, valueFactory.invoke(null, new Object []{ctx.values[iterValues]})); 331 } 332 catch (IllegalAccessException e) 333 { 334 throw new FileSystemException(e); 335 } 336 catch (InvocationTargetException 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 352 private void invokeSetter(Class valueParameter, final Context ctx, final Method configSetter, final Object values) 353 throws FileSystemException 354 { 355 Object [] args; 356 if (valueParameter.isArray()) 357 { 358 args = new Object [] 359 { 360 ctx.fso, 361 values 362 }; 363 } 364 else 365 { 366 args = new Object [] 367 { 368 ctx.fso, 369 Array.get(values, 0) 370 }; 371 } 372 try 373 { 374 configSetter.invoke(ctx.fileSystemConfigBuilder, args); 375 } 376 catch (IllegalAccessException e) 377 { 378 throw new FileSystemException(e); 379 } 380 catch (InvocationTargetException e) 381 { 382 throw new FileSystemException(e); 383 } 384 } 385 386 389 private boolean fillConfigSetters(final Context ctx) 390 throws FileSystemException 391 { 392 Map schemeMethods = getSchemeMethods(ctx.scheme); 393 List configSetters = (List ) 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 406 private Map getSchemeMethods(final String scheme) throws FileSystemException 407 { 408 Map schemeMethods = (Map ) 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 421 private Map createSchemeMethods(String 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 schemeMethods = new TreeMap (); 430 431 Method methods[] = fscb.getClass().getMethods(); 432 for (int iterMethods = 0; iterMethods < methods.length; iterMethods++) 433 { 434 Method method = methods[iterMethods]; 435 if (!Modifier.isPublic(method.getModifiers())) 436 { 437 continue; 438 } 439 440 String methodName = method.getName(); 441 if (!methodName.startsWith("set")) 442 { 443 continue; 445 } 446 447 String key = methodName.substring(3).toLowerCase(); 448 449 List configSetter = (List ) schemeMethods.get(key); 450 if (configSetter == null) 451 { 452 configSetter = new ArrayList (2); 453 schemeMethods.put(key, configSetter); 454 } 455 configSetter.add(method); 456 } 457 458 return schemeMethods; 459 } 460 } 461 | Popular Tags |