| Line | Hits | Source |
|---|---|---|
| 1 | /* | |
| 2 | Chrysalis Web Framework [http://chrysalis.sourceforge.net] | |
| 3 | Copyright (c) 2002, 2003, 2004, Paul Strack | |
| 4 | ||
| 5 | All rights reserved. | |
| 6 | ||
| 7 | Redistribution and use in source and binary forms, with or without | |
| 8 | modification, are permitted provided that the following conditions are met: | |
| 9 | ||
| 10 | 1. Redistributions of source code must retain the above copyright notice, this | |
| 11 | list of conditions and the following disclaimer. | |
| 12 | ||
| 13 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 14 | this list of conditions and the following disclaimer in the documentation | |
| 15 | and/or other materials provided with the distribution. | |
| 16 | ||
| 17 | 3. Neither the name of the copyright holder nor the names of its contributors | |
| 18 | may be used to endorse or promote products derived from this software without | |
| 19 | specific prior written permission. | |
| 20 | ||
| 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
| 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
| 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
| 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 31 | */ | |
| 32 | ||
| 33 | package org.chwf.resources; | |
| 34 | ||
| 35 | import java.util.HashMap; | |
| 36 | import java.util.Iterator; | |
| 37 | import java.util.Map; | |
| 38 | ||
| 39 | import org.chwf.i18n.Message; | |
| 40 | ||
| 41 | /** | |
| 42 | * A locator for resources. It delegates is calls to the appropriate | |
| 43 | * [@link ResourceFactory}. | |
| 44 | * | |
| 45 | * @author Paul Strack | |
| 46 | */ | |
| 47 | 2 | public class ResourceLocator { |
| 48 | ||
| 49 | /** Empty array. */ | |
| 50 | 2 | private static final Object[] EMPTY_ARRAY = new Object[0]; |
| 51 | ||
| 52 | /** The resource factories, indexed by ResourceID. */ | |
| 53 | 1 | private static final Map RESOURCE_FACTORIES = initResourceFactories(); |
| 54 | ||
| 55 | /** A thread local variable for caching managed resources. */ | |
| 56 | 1 | private static final ThreadLocal MANAGED_RESOURCES = new ThreadLocal(); |
| 57 | ||
| 58 | /** | |
| 59 | * True if the resource has a (default) factory. | |
| 60 | * | |
| 61 | * @param resource The resource class. | |
| 62 | * @return True if the resource has a factory. | |
| 63 | */ | |
| 64 | public static boolean hasFactory(Class resource) { | |
| 65 | 2 | return hasFactory(resource, ResourceManagerConfig.DEFAULT_FACTORY); |
| 66 | } | |
| 67 | ||
| 68 | /** | |
| 69 | * True if the resource has a factory with the given name. | |
| 70 | * | |
| 71 | * @param resource The resource class. | |
| 72 | * @param factoryName The factory name. | |
| 73 | * @return True if the resource has a factory with the given name. | |
| 74 | */ | |
| 75 | public static boolean hasFactory(Class resource, String factoryName) { | |
| 76 | 5 | if (factoryName == null) { |
| 77 | 1 | factoryName = ResourceManagerConfig.DEFAULT_FACTORY; |
| 78 | } | |
| 79 | 5 | ResourceID pair = new ResourceID(resource, factoryName); |
| 80 | 5 | return (RESOURCE_FACTORIES.get(pair) != null); |
| 81 | } | |
| 82 | ||
| 83 | /** | |
| 84 | * True if this resource is managed for the default factory. | |
| 85 | * | |
| 86 | * @param resource The resource class. | |
| 87 | * @return True if this resource is managed by the default factory. | |
| 88 | */ | |
| 89 | public static boolean isManaged(Class resource) { | |
| 90 | 1 | return isManaged(resource, ResourceManagerConfig.DEFAULT_FACTORY); |
| 91 | } | |
| 92 | ||
| 93 | /** | |
| 94 | * True if this resource is managed for the given named factory. | |
| 95 | * | |
| 96 | * @param resource The resource class. | |
| 97 | * @param factoryName The factory name. | |
| 98 | * @return True if this resource is managed for the given named factory. | |
| 99 | */ | |
| 100 | public static boolean isManaged(Class resource, String factoryName) { | |
| 101 | 3 | if (factoryName == null) { |
| 102 | 1 | factoryName = ResourceManagerConfig.DEFAULT_FACTORY; |
| 103 | } | |
| 104 | 3 | ResourceID pair = new ResourceID(resource, factoryName); |
| 105 | 3 | Object factory = RESOURCE_FACTORIES.get(pair); |
| 106 | 3 | return ((factory != null) && (factory instanceof ManagedResourceFactory)); |
| 107 | } | |
| 108 | ||
| 109 | /** | |
| 110 | * Get a resource from its default factory. | |
| 111 | * | |
| 112 | * @param type The resource type. | |
| 113 | * @return The resource. | |
| 114 | * @throws ResourceException If there is no factory for this resource. | |
| 115 | * @throws ResourceInitException If the factory cannot be found. | |
| 116 | */ | |
| 117 | public static Object getResource(Class type) | |
| 118 | throws ResourceException, ResourceInitException { | |
| 119 | 2 | return getResource(type, ResourceManagerConfig.DEFAULT_FACTORY); |
| 120 | } | |
| 121 | ||
| 122 | /** | |
| 123 | * Get a resource from a named factory. | |
| 124 | * | |
| 125 | * @param type The resource type. | |
| 126 | * @param factoryName The factory name. | |
| 127 | * @return The resource. | |
| 128 | * @throws ResourceException If there is no factory with this name. | |
| 129 | * @throws ResourceInitException If the factory cannot be found. | |
| 130 | */ | |
| 131 | public static Object getResource(Class type, String factoryName) | |
| 132 | throws ResourceException, ResourceInitException { | |
| 133 | ||
| 134 | 11 | if (factoryName == null) { |
| 135 | 1 | factoryName = ResourceManagerConfig.DEFAULT_FACTORY; |
| 136 | } | |
| 137 | 11 | ResourceFactory factory = ResourceLocator.getFactory(type, factoryName); |
| 138 | 10 | if (factory instanceof ManagedResourceFactory) { |
| 139 | 8 | ManagedResourceFactory managedFactory = (ManagedResourceFactory) factory; |
| 140 | 8 | return getManagedResource(type, factoryName, managedFactory); |
| 141 | } else { | |
| 142 | 2 | return factory.getResource(); |
| 143 | } | |
| 144 | } | |
| 145 | ||
| 146 | /** | |
| 147 | * True if management is initialized. | |
| 148 | * | |
| 149 | * @return True if management is initialized. | |
| 150 | */ | |
| 151 | public static boolean isManagementActive() { | |
| 152 | 973 | return (MANAGED_RESOURCES.get() != null); |
| 153 | } | |
| 154 | ||
| 155 | /** | |
| 156 | * Initialize resource management for this thread. Developers should not call | |
| 157 | * this method except for testing. This method can only be called once until | |
| 158 | * the release() method is called. | |
| 159 | * | |
| 160 | * @throws ResourceInitException If called while initialized. | |
| 161 | */ | |
| 162 | static void init() throws ResourceInitException { | |
| 163 | 472 | if (!isManagementActive()) { |
| 164 | 471 | MANAGED_RESOURCES.set(new HashMap()); |
| 165 | } else { | |
| 166 | 1 | throw new ResourceInitException( |
| 167 | ResourceInitException.MESSAGE_ALREADY_INITIALIZED); | |
| 168 | } | |
| 169 | 471 | } |
| 170 | ||
| 171 | /** | |
| 172 | * Release all managed resources, and terminate resource management for this | |
| 173 | * thread. Developers should not call this method except for testing. All | |
| 174 | * resources are released, even if there are failures during the release | |
| 175 | * process. The resources are not released in any particular order, however. | |
| 176 | * | |
| 177 | * @param error Error status for the thread of execution (null if there were | |
| 178 | * no errors). | |
| 179 | * @throws ResourceException If there were failures during the release. | |
| 180 | * This is a chained exception; the full set of release errors can | |
| 181 | * be retrieved via {@link ResourceException#getNextException()} | |
| 182 | * @throws ResourceInitException If called when not initialized. | |
| 183 | */ | |
| 184 | static void release(Throwable error) | |
| 185 | throws ResourceException, ResourceInitException { | |
| 186 | ||
| 187 | 472 | if (isManagementActive()) { |
| 188 | 471 | ResourceException errors = null; |
| 189 | 471 | Iterator resources = getManagedResources().values().iterator(); |
| 190 | 948 | while (resources.hasNext()) { |
| 191 | try { | |
| 192 | 6 | ManagedResource resource = (ManagedResource) resources.next(); |
| 193 | 6 | resource.release(error); |
| 194 | 4 | } catch (ResourceException ex) { |
| 195 | 1 | ex.setNextException(errors); |
| 196 | 1 | errors = ex; |
| 197 | 1 | } catch (Throwable ex) { |
| 198 | 1 | ResourceException rex = new ResourceException(ex); |
| 199 | 1 | rex.setNextException(errors); |
| 200 | 1 | errors = rex; |
| 201 | } | |
| 202 | } | |
| 203 | 471 | MANAGED_RESOURCES.set(null); |
| 204 | 471 | if (errors != null) { |
| 205 | 2 | Message msg = |
| 206 | Message.getMessage( | |
| 207 | ResourceException.MESSAGE_RESOURCE_RELEASE_FAILURE, | |
| 208 | EMPTY_ARRAY, | |
| 209 | ResourceException.class); | |
| 210 | 2 | ResourceException ex = new ResourceException(msg.toString()); |
| 211 | 2 | ex.setNextException(errors); |
| 212 | 2 | throw ex; |
| 213 | } | |
| 214 | } else { | |
| 215 | 1 | throw new ResourceInitException( |
| 216 | ResourceInitException.MESSAGE_NOT_INITIALIZED); | |
| 217 | } | |
| 218 | 469 | } |
| 219 | ||
| 220 | /** | |
| 221 | * Initialize all resource factories. | |
| 222 | * | |
| 223 | * @return The map containing the resource factories. | |
| 224 | * @throws ResourceInitException If a factory class cannot be initialized. | |
| 225 | */ | |
| 226 | private static Map initResourceFactories() throws ResourceInitException { | |
| 227 | 1 | Map map = new HashMap(); |
| 228 | 1 | ResourceManagerConfig config = ResourceManagerConfig.getConfig(); |
| 229 | 1 | String[] resourceClasses = config.getResourceClasses(); |
| 230 | 3 | for (int i = 0; i < resourceClasses.length; i++) { |
| 231 | 2 | String resource = resourceClasses[i]; |
| 232 | 2 | Class resourceClass = deriveResourceClass(resource); |
| 233 | 2 | Map factoryClasses = config.getFactoryClasses(resource); |
| 234 | 2 | Iterator iterator = factoryClasses.keySet().iterator(); |
| 235 | 10 | while (iterator.hasNext()) { |
| 236 | 6 | String factoryName = iterator.next().toString(); |
| 237 | 6 | String factoryClassName = factoryClasses.get(factoryName).toString(); |
| 238 | 6 | ResourceFactory factory = createFactory(factoryClassName, resource); |
| 239 | 6 | if (!resourceClass.equals(factory.getType())) { |
| 240 | 0 | Object[] args = { factoryName, resource }; |
| 241 | 0 | throw new ResourceInitException( |
| 242 | ResourceInitException.MESSAGE_WRONG_FACTORY_TYPE, | |
| 243 | args); | |
| 244 | } | |
| 245 | 6 | Map factoryProperties = |
| 246 | config.getFactoryProperties(resource, factoryName); | |
| 247 | 6 | ResourceFactoryConfigImpl factoryConfig = |
| 248 | new ResourceFactoryConfigImpl(factoryName, factoryProperties); | |
| 249 | try { | |
| 250 | 6 | factory.init(factoryConfig); |
| 251 | 6 | } catch (Exception ex) { |
| 252 | 0 | Object[] args = { factoryName, resource, ex }; |
| 253 | 0 | throw new ResourceInitException( |
| 254 | ResourceInitException.MESSAGE_FACTORY_INIT_FAILED, | |
| 255 | args); | |
| 256 | } | |
| 257 | 6 | ResourceID id = new ResourceID(resourceClass, factoryName); |
| 258 | 6 | map.put(id, factory); |
| 259 | } | |
| 260 | } | |
| 261 | 1 | return map; |
| 262 | } | |
| 263 | ||
| 264 | /** | |
| 265 | * Derive resource class for the given class name. | |
| 266 | * | |
| 267 | * @param className The class name. | |
| 268 | * @return The class. | |
| 269 | * @throws ResourceInitException If the factory class is not found. | |
| 270 | */ | |
| 271 | private static Class deriveResourceClass(String className) | |
| 272 | throws ResourceInitException { | |
| 273 | try { | |
| 274 | 2 | return Class.forName(className); |
| 275 | } catch (ClassNotFoundException ex) { | |
| 276 | 0 | Object[] args = { className }; |
| 277 | 0 | throw new ResourceInitException( |
| 278 | ResourceInitException.MESSAGE_RESOURCE_CLASS_NOT_FOUND, | |
| 279 | args); | |
| 280 | } | |
| 281 | } | |
| 282 | ||
| 283 | /** | |
| 284 | * Derive resource factory class for the given class name. | |
| 285 | * | |
| 286 | * @param className The factory class name. | |
| 287 | * @param resource The resource name. | |
| 288 | * @return The class. | |
| 289 | * @throws ResourceInitException If the factory class is not found. | |
| 290 | */ | |
| 291 | private static Class deriveFactoryClass(String className, String resource) | |
| 292 | throws ResourceInitException { | |
| 293 | try { | |
| 294 | 6 | return Class.forName(className); |
| 295 | } catch (ClassNotFoundException ex) { | |
| 296 | 0 | Object[] args = { className, resource }; |
| 297 | 0 | throw new ResourceInitException( |
| 298 | ResourceInitException.MESSAGE_FACTORY_CLASS_NOT_FOUND, | |
| 299 | args); | |
| 300 | } | |
| 301 | } | |
| 302 | ||
| 303 | /** | |
| 304 | * Create resource factory for the given class name. | |
| 305 | * | |
| 306 | * @param className The factory class name. | |
| 307 | * @param resource The resource name. | |
| 308 | * @return The factory. | |
| 309 | * @throws ResourceInitException If the factory cannot be created. | |
| 310 | */ | |
| 311 | private static ResourceFactory createFactory( | |
| 312 | String className, | |
| 313 | String resource) | |
| 314 | throws ResourceInitException { | |
| 315 | 6 | Class factoryClass = deriveFactoryClass(className, resource); |
| 316 | try { | |
| 317 | 6 | return (ResourceFactory) factoryClass.newInstance(); |
| 318 | } catch (ClassCastException ex) { | |
| 319 | 0 | Object[] args = { factoryClass.getName(), resource }; |
| 320 | 0 | throw new ResourceInitException( |
| 321 | ResourceInitException.MESSAGE_NOT_A_RESOURCE_FACTORY, | |
| 322 | args); | |
| 323 | } catch (Exception ex) { | |
| 324 | 0 | Object[] args = { factoryClass.getName(), resource, ex }; |
| 325 | 0 | throw new ResourceInitException( |
| 326 | ResourceInitException.MESSAGE_FACTORY_NOT_CREATED, | |
| 327 | args); | |
| 328 | } | |
| 329 | } | |
| 330 | ||
| 331 | /** | |
| 332 | * Retrieve the factory for the given resource type. | |
| 333 | * | |
| 334 | * @param type The resource type. | |
| 335 | * @param name The factory name. | |
| 336 | * @return The factory. | |
| 337 | * @throws ResourceInitException If the factory is not found. | |
| 338 | */ | |
| 339 | private static ResourceFactory getFactory(Class type, String name) | |
| 340 | throws ResourceInitException { | |
| 341 | ||
| 342 | 11 | ResourceID pair = new ResourceID(type, name); |
| 343 | 11 | ResourceFactory factory = (ResourceFactory) RESOURCE_FACTORIES.get(pair); |
| 344 | 11 | if (factory == null) { |
| 345 | 1 | Object[] args = { name, type }; |
| 346 | 1 | throw new ResourceInitException( |
| 347 | ResourceInitException.MESSAGE_FACTORY_NOT_FOUND, | |
| 348 | args); | |
| 349 | } | |
| 350 | 10 | return factory; |
| 351 | } | |
| 352 | ||
| 353 | /** | |
| 354 | * Retrieve a managed resource. | |
| 355 | * | |
| 356 | * @param type The resource type. | |
| 357 | * @param name The factory name. | |
| 358 | * @param factory The factory. | |
| 359 | * @return The managed resource. | |
| 360 | * @throws ResourceException If the resource cannot be retrieved. | |
| 361 | * @throws ResourceInitException If the factory is not initialized. | |
| 362 | */ | |
| 363 | private static Object getManagedResource( | |
| 364 | Class type, | |
| 365 | String name, | |
| 366 | ManagedResourceFactory factory) | |
| 367 | throws ResourceException, ResourceInitException { | |
| 368 | ||
| 369 | 8 | if (!isManagementActive()) { |
| 370 | 1 | Object[] args = { type.getName(), name }; |
| 371 | 1 | throw new ResourceInitException( |
| 372 | ResourceInitException.MESSAGE_MANAGEMENT_NOT_INITIALIZED, | |
| 373 | args); | |
| 374 | } | |
| 375 | 7 | ResourceID id = new ResourceID(type, name); |
| 376 | 7 | Map managedResources = getManagedResources(); |
| 377 | 7 | ManagedResource managed = (ManagedResource) managedResources.get(id); |
| 378 | 7 | if (managed == null) { |
| 379 | 7 | managed = new ManagedResource(factory, factory.getResource()); |
| 380 | 6 | managedResources.put(id, managed); |
| 381 | } | |
| 382 | 6 | return managed.getResource(); |
| 383 | } | |
| 384 | ||
| 385 | /** | |
| 386 | * The list of managed resources. | |
| 387 | * | |
| 388 | * @return The list of managed resources. | |
| 389 | */ | |
| 390 | private static Map getManagedResources() { | |
| 391 | 478 | return (Map) MANAGED_RESOURCES.get(); |
| 392 | } | |
| 393 | ||
| 394 | /** | |
| 395 | * A class for map values for managed resources. | |
| 396 | * | |
| 397 | * @author Paul Strack | |
| 398 | */ | |
| 399 | private static class ManagedResource { | |
| 400 | ||
| 401 | /** The factory. */ | |
| 402 | private final ManagedResourceFactory factory; | |
| 403 | ||
| 404 | /** The resource. */ | |
| 405 | private final Object resource; | |
| 406 | ||
| 407 | /** | |
| 408 | * Constructor. | |
| 409 | * | |
| 410 | * @param factory The factory. | |
| 411 | * @param resource The resource. | |
| 412 | */ | |
| 413 | ManagedResource(ManagedResourceFactory factory, Object resource) { | |
| 414 | this.factory = factory; | |
| 415 | this.resource = resource; | |
| 416 | } | |
| 417 | ||
| 418 | /** | |
| 419 | * The resource. | |
| 420 | * | |
| 421 | * @return The resource. | |
| 422 | */ | |
| 423 | Object getResource() { | |
| 424 | return resource; | |
| 425 | } | |
| 426 | ||
| 427 | /** | |
| 428 | * Release the resource. | |
| 429 | * | |
| 430 | * @param error An error message (or null if there were no errors). | |
| 431 | * @throws ResourceException If the release fails. | |
| 432 | */ | |
| 433 | void release(Throwable error) throws ResourceException { | |
| 434 | factory.release(resource, error); | |
| 435 | } | |
| 436 | } | |
| 437 | } |
|
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |