001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2007-2012 Pentaho and others 008// All Rights Reserved. 009*/ 010package mondrian.util; 011 012import org.eigenbase.util.property.StringProperty; 013 014import java.lang.reflect.*; 015import java.util.Properties; 016 017/** 018 * Concrete derived classes of the generic <code>ObjectFactory</code> class 019 * are used to produce an implementation of an interface (a 020 * normal interface implementation or a Proxy). In general, a 021 * factory should produce a default implementation for general application 022 * use as well as particular implementations used during testing. 023 * During testing of application code and during normal execution, 024 * the application code uses one of the <code>ObjectFactory</code>'s 025 * methods for producing implementation instances - the same method is 026 * used both for test and non-test modes. There are two ways of 027 * modifying the implementation returned to the application code. 028 * 029 * <p>The first is for the application to use Properties. 030 * The <code>ObjectFactory</code> implementation looks for a given 031 * property (by default the name of the property is the class name 032 * of the interfaceClass object) and if found uses it as the classname 033 * to create.</p> 034 * 035 * <p>A second approach is to use a ThreadLocal; if the ThreadLocal 036 * is non-empty then use it as the class name.</p> 037 * 038 * <p>When to use a Factory? 039 * 040 * <p>Everyone has an opinion. For me, there are two criteria: enabling 041 * unit testing and providing end-user/developer-customizer overriding. 042 * 043 * <p>If a method has side-effects, either its result depends upon 044 * a side-effect or calling it causes a side-effect, then the Object 045 * hosting the method is a candidate for having a factory. Why? 046 * Well, consider the case where a method returns the value of 047 * a System property and the System property is determined only once 048 * and set to a static final variable: 049 * 050 * <pre> 051 * class OneValue { 052 * private static final boolean propValue; 053 * static { 054 * propValue = Boolean.getBoolean("com.app.info.value"); 055 * } 056 * ..... 057 * public boolean hasInfo() { 058 * return propValue; 059 * } 060 * } 061 * </pre> 062 * 063 * <p>In this case, only one value is ever returned. If you have a 064 * module, a client of the above code, that uses the value returned 065 * by a call to the 066 * <code>hasInfo()</code> method, how do you write a unit test of 067 * your module that tests both possible return values? 068 * You can not, its value is based upon a side-effect, an external 069 * value that can not be controlled by the unit test.</p> 070 * 071 * <p>If the <code>OneValue</code> class was an interface and there was a 072 * factory, then the unit test could arrange that its own version of the 073 * <code>OneValue</code> 074 * interface was returned and in one test arrange that <code>true</code> 075 * was returned and in a second test, arrange that <code>false</code> 076 * was returned.</p> 077 * 078 * <p>The above is a trivial example of code that disallows clients of the 079 * code from being properly tested.</p> 080 * 081 * <p>Another example might be a module that directly initializes a JMS 082 * queue and receives JMS message 083 * from the JMS queue. This code can not be tested without having a live 084 * JMS queue. On the other hand, if one defines an interface allowing 085 * one to wrap access to the JMS queue and accesses the implementation 086 * via a factory, then unit tests can be create that use a mock 087 * JMS queue.</p> 088 * 089 * <p>With regards to providing end-user/developer-customizer overriding, 090 * its generally good to have a flexible application framework. 091 * Experimental or just different implementations can be developed and 092 * tested without having to touch a lot of the application code itself.</p> 093 * 094 * <p>There is, of course, a trade-off between the use of a factory 095 * and the size or simplicity of the object being created.</p> 096 * 097 * <p>What are the requirements for a template ObjectFactory?</p> 098 * 099 * <p>First, every implementation must support the writing of unit tests. 100 * What this means it that test cases can override what the factory 101 * produces. The test cases can all use the same produced Object or 102 * each can request an Object targeted to its particular test. All this 103 * without changing the <code>default</code> behavior of the factory.</p> 104 * 105 * <p>Next, it should be possible to create a factory from the template that 106 * is intended to deliver the same Object each time it is called, a 107 * different, new Object each time it is called, or, based on the 108 * calling environment (parameters, properties, <code>ThreadLocal</code>, 109 * etc.) one of a set of Objects. These are possible <code>default</code> 110 * behaviors, but, again, they can be overridden for test purposes.</p> 111 * 112 * <p>While a factory has a <code>default</code> behavior in an 113 * application, it must be possible for every factory's behavior 114 * in that application to be globally overridden. What that means is 115 * if the application designer has dictated a <code>default</code>, the 116 * application user should be able to change the default. An example of 117 * this is overriding what Object is returned based upon a 118 * <code>System</code> property value.</p> 119 * 120 * <p>Lastly, every factory is a singleton - if an interface with 121 * an implementation whose creation is mediated by a factory, then 122 * there is a single factory that does that creating. 123 * This does not mean that such a factory always return the same value, 124 * rather that there is only one instance of the factory itself.</p> 125 * 126 * <p>The following is an example class that generates a factory 127 * singleton. In this case, the factory extends the 128 * <code>ObjectFactory</code> 129 * rather than the <code>ObjectFactory.Singleton</code>:</p> 130 * 131 * <pre> 132 * 133 * public final class FooFactory extends ObjectFactory<Foo> { 134 * // The single instance of the factory 135 * private static final FooFactory factory; 136 * static { 137 * factory = new FooFactory(); 138 * } 139 * public static FooFactory instance() { 140 * return factory; 141 * } 142 * .......... 143 * private FooFactory() { 144 * super(Foo.class); 145 * } 146 * .......... 147 * } 148 * 149 * </pre> 150 * 151 * <p>There are multiple ways of creating derived classes that have support 152 * for unit testing. A very simple way is to use <code>ThreadLocal</code>s.</p> 153 * 154 * <pre> 155 * 156 * private static final ThreadLocal ClassName = new ThreadLocal(); 157 * private static String getThreadLocalClassName() { 158 * return (String) ClassName.get(); 159 * } 160 * public static void setThreadLocalClassName(String className) { 161 * ClassName.set(className); 162 * } 163 * public static void clearThreadLocalClassName() { 164 * ClassName.set(null); 165 * } 166 * .......... 167 * protected String getClassName() { 168 * return getThreadLocalClassName(); 169 * } 170 * 171 * </pre> 172 * 173 * <p>Here, the unit test will call the <code>setThreadLocalClassName</code> 174 * method setting it with the class name of a specialized implementation of 175 * the template interface. In the <code>finally</code> clause of the 176 * unit test, it is very important that there be a call to the 177 * <code>clearThreadLocalClassName</code> method so that other 178 * tests, etc. do not get an instance of the test-specific specialized 179 * implementation.</p> 180 * 181 * <p>The following is an example unit test that uses the factory's 182 * <code>ThreadLocal</code> to override the implementation that is returned.</p> 183 * 184 * <pre> 185 * interface Boo { 186 * boolean getValue(); 187 * ....... 188 * } 189 * class NormalBooImpl implements Boo { 190 * public boolean getValue() { ... } 191 * ....... 192 * } 193 * class MyCode { 194 * private Boo boo; 195 * MyCode() { 196 * boo = BooFactory.instance().getObject(); 197 * } 198 * ....... 199 * int getValue() { 200 * if (boo.getValue()) { 201 * return 1; 202 * } else { 203 * return 0; 204 * } 205 * 206 * } 207 * } 208 * 209 * class MyCodeTest { 210 * private static boolean testValue; 211 * static class BooTest1 implements Boo { 212 * public boolean getValue() { 213 * return MyTest.testValue; 214 * } 215 * ..... 216 * } 217 * static class BooTest2 implements 218 * java.lang.reflect.InvocationHandler { 219 * private final Boo boo; 220 * public BooTest2() { 221 * // remove test class name 222 * BooFactory.clearThreadLocalClassName(); 223 * // get default Boo implementation 224 * this.boo = BooFactory.instance().getObject(); 225 * } 226 * public Object invoke(Object proxy, Method method, Object[] args) 227 * throws Throwable { 228 * if (method.getName().equals("getValue")) [ 229 * return new Boolean(MyTest.testValue); 230 * } else { 231 * return method.invoke(this.boo, args); 232 * } 233 * } 234 * } 235 * public void test1() { 236 * try { 237 * // Factory will creates test class 238 * BooFactory.setThreadLocalClassName("MyTest.BooTest1"); 239 * 240 * MyTest.testValue = true; 241 * MyCode myCode = new MyCode(); 242 * int value = myCode.getValue(); 243 * assertTrue("Value not 1", (value == 1)); 244 * 245 * MyTest.testValue = false; 246 * myCode = new MyCode(); 247 * value = myCode.getValue(); 248 * assertTrue("Value not 0", (value == 0)); 249 * } finally { 250 * BooFactory.clearThreadLocalClassName(); 251 * } 252 * } 253 * public void test2() { 254 * try { 255 * // Use InvocationHandler and Factory Proxy capability 256 * BooFactory.setThreadLocalClassName("MyTest.BooTest2"); 257 * 258 * MyTest.testValue = true; 259 * MyCode myCode = new MyCode(); 260 * int value = myCode.getValue(); 261 * assertTrue("Value not 1", (value == 1)); 262 * 263 * MyTest.testValue = false; 264 * myCode = new MyCode(); 265 * value = myCode.getValue(); 266 * assertTrue("Value not 0", (value == 0)); 267 * } finally { 268 * BooFactory.clearThreadLocalClassName(); 269 * } 270 * } 271 * } 272 * 273 * </pre> 274 * 275 * <p>While this is a very simple example, it shows how using such factories 276 * can aid in creating testable code. The MyCode method is a client of 277 * the Boo implementation. How to test the two different code branches the 278 * method can take? Because the Boo object is generated by a factory, 279 * one can override what object the factory returns.</p> 280 * 281 * @author Richard M. Emberson 282 * @since Feb 01 2007 283 */ 284public abstract class ObjectFactory<V> { 285 286 private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; 287 private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; 288 289 /** 290 * The type of the object to be generated. 291 */ 292 private final Class<V> interfaceClass; 293 294 /** 295 * Creates a new factory object. The <code>interfaceClass</code> parameter 296 * is used to cast the object generated to type right type. 297 * 298 * @param interfaceClass the class object for the interface implemented 299 * by the objects returned by this factory 300 * 301 */ 302 protected ObjectFactory(final Class<V> interfaceClass) { 303 this.interfaceClass = interfaceClass; 304 } 305 306 /** 307 * Constructs an object where the System Properties can be used 308 * to look up a class name. 309 * The constructor for the object takes no parameters. 310 * 311 * @return the newly created object 312 * @throws CreationException if unable to create the object 313 */ 314 protected final V getObject() throws CreationException { 315 return getObject(System.getProperties()); 316 } 317 318 /** 319 * Constructs an object where the <code>Properties</code> parameter can 320 * be used to look up a class name. 321 * The constructor for the object takes no parameters. 322 * 323 * @param props the property definitions to use to determine the 324 * implementation class 325 * 326 * @return the newly created object 327 * @throws CreationException if unable to create the object 328 */ 329 protected final V getObject(final Properties props) 330 throws CreationException 331 { 332 return getObject(props, EMPTY_CLASS_ARRAY, EMPTY_OBJECT_ARRAY); 333 } 334 335 /** 336 * Constructs an object where the <code>parameterTypes</code> and 337 * <code>parameterValues</code> are constructor parameters and 338 * System Properties are used to look up a class name. 339 * 340 * @param parameterTypes the class parameters that define the signature 341 * of the constructor to use 342 * @param parameterValues the values to use to construct the current 343 * instance of the object 344 * @return the newly created object 345 * @throws CreationException if unable to create the object 346 */ 347 protected final V getObject( 348 final Class[] parameterTypes, 349 final Object[] parameterValues) 350 throws CreationException 351 { 352 return getObject( 353 System.getProperties(), parameterTypes, parameterValues); 354 } 355 356 /** 357 * Constructs an object where the <code>parameterTypes</code> and 358 * <code>parameterValues</code> are constructor parameters and 359 * Properties parameter is used to look up a class name. 360 * <p> 361 * This returns a new instance of the Object each time its 362 * called (assuming that if the method <code>getDefault</code>, 363 * which derived classes implement), if called, creates a new 364 * object each time. 365 * 366 * @param props the property definitions to use to determine the 367 * @param parameterTypes the class parameters that define the signature 368 * of the constructor to use 369 * @param parameterValues the values to use to construct the current 370 * instance of the object 371 * @return the newly created object 372 * @throws CreationException if unable to create the object 373 */ 374 protected V getObject( 375 final Properties props, 376 final Class[] parameterTypes, 377 final Object[] parameterValues) throws CreationException 378 { 379 // Unit test override 380 final String className = getClassName(); 381 if (className != null) { 382 return getObject(className, parameterTypes, parameterValues); 383 } 384 385 final String propClassName = getClassName(props); 386 return (propClassName != null) 387 // User overriding application default 388 ? getObject(propClassName, parameterTypes, parameterValues) 389 // Get application default 390 : getDefault(parameterTypes, parameterValues); 391 } 392 393 /** 394 * Creates an instance with the given <code>className</code>, 395 * <code>parameterTypes</code> and <code>parameterValues</code> or 396 * throw a <code>CreationException</code>. There are two different 397 * mechanims available. The first is to uses reflection 398 * to create the instance typing the generated Object based upon 399 * the <code>interfaceClass</code> factory instance object. 400 * With the second the <code>className</code> is an class that implements 401 * the <code>InvocationHandler</code> interface and in this case 402 * the <code>java.lang.reflect.Proxy</code> class is used to 403 * generate a proxy. 404 * 405 * @param className the class name used to create Object instance 406 * @param parameterTypes the class parameters that define the signature 407 * of the constructor to use 408 * @param parameterValues the values to use to construct the current 409 * instance of the object 410 * @return the newly created object 411 * @throws CreationException if unable to create the object 412 */ 413 protected V getObject( 414 final String className, 415 final Class[] parameterTypes, 416 final Object[] parameterValues) throws CreationException 417 { 418 try { 419 // As a place to begin google: 420 // org.apache.cxf.BusFactoryHelper.java 421 final Class<?> genericClass = 422 ClassResolver.INSTANCE.forName(className, true); 423 424 // Are we creating a Proxy or an instance? 425 if (InvocationHandler.class.isAssignableFrom(genericClass)) { 426 final Constructor constructor = 427 genericClass.getConstructor(parameterTypes); 428 InvocationHandler handler = (InvocationHandler) 429 constructor.newInstance(parameterValues); 430 //noinspection unchecked 431 return (V) Proxy.newProxyInstance( 432 genericClass.getClassLoader(), 433 new Class[] { this.interfaceClass }, 434 handler); 435 } else { 436 final Class<? extends V> specificClass = 437 genericClass.asSubclass(interfaceClass); 438 final Constructor<? extends V> constructor = 439 specificClass.getConstructor(parameterTypes); 440 441 return constructor.newInstance(parameterValues); 442 } 443 } catch (Exception exc) { 444 throw new CreationException( 445 "Error creating object of type \"" 446 + this.interfaceClass.getName() + "\"", 447 exc); 448 } 449 } 450 451 /** 452 * Returns the name of a class to use to create an object. 453 * The default implementation returns null but derived 454 * classes can return a class name. 455 * <p> 456 * This method is the primary mechanism for supporting Unit testing. 457 * A derived class can have, as an example, this method return 458 * the value of a <code>ThreadLocal</code>. For testing it 459 * return a class name while for normal use it returns <code>null</code>. 460 * 461 * @return <code>null</code> or a class name 462 */ 463 protected String getClassName() { 464 return null; 465 } 466 467 /** 468 * Returns the name of a class to use to create an object. 469 * The factory's <code>StringProperty</code> is gotten and 470 * if it has a non-null value, then that is returned. Otherwise, 471 * the <code>StringProperty</code>'s name (path) is used as the 472 * name to probe the <code>Properties</code> object for a value. 473 * This method is allowed to return null. 474 * 475 * @return <code>null</code> or a class name 476 */ 477 protected String getClassName(final Properties props) { 478 final StringProperty stringProp = getStringProperty(); 479 final String className = stringProp.get(); 480 return (className != null) 481 ? className 482 : (props == null) 483 ? null : props.getProperty(stringProp.getPath()); 484 } 485 486 /** 487 * Return the <code>StringProperty</code> associated with this factory. 488 * 489 * @return the <code>StringProperty</code> 490 */ 491 protected abstract StringProperty getStringProperty(); 492 493 /** 494 * For most uses (other than testing) this is the method that derived 495 * classes implement that return the desired object. 496 * 497 * @param parameterTypes the class parameters that define the signature 498 * of the constructor to use 499 * @param parameterValues the values to use to construct the current 500 * instance of the object 501 * @return the newly created object 502 * @throws CreationException if unable to create the object 503 */ 504 protected abstract V getDefault( 505 Class[] parameterTypes, 506 Object[] parameterValues) 507 throws CreationException; 508 509 /** 510 * Gets the current override values in the opaque context object and 511 * clears those values within the Factory. 512 * 513 * <p>This is used in testing. 514 * 515 * @return the test <code>Context</code> object. 516 */ 517 public Object removeContext() { 518 return null; 519 } 520 521 /** 522 * Restores the context object resetting override values. 523 * 524 * <p>This is used in testing. 525 * 526 * @param context the context object to be restored. 527 */ 528 public void restoreContext(final Object context) { 529 // empty 530 } 531 532 533 /** 534 * Implementation of ObjectFactory 535 * that returns only a single instance of the Object. 536 */ 537 public static abstract class Singleton<T> extends ObjectFactory<T> { 538 539 /** 540 * The single instance of the object created by the factory. 541 */ 542 protected T singleInstance; 543 544 /** 545 * The test single instance of the object created by the factory. 546 * Creating this <code>testSingleInstance</code> does not change the 547 * current value of the <code>singleInstance</code> variable. 548 */ 549 protected T testSingleInstance; 550 551 /** 552 * Creates a new singleton factory object. The 553 * <code>interfaceClass</code> parameter 554 * is used to cast the object generated to type right type. 555 * 556 * @param interfaceClass the class object for the interface implemented 557 * by the objects returned by this factory 558 */ 559 protected Singleton(final Class<T> interfaceClass) { 560 super(interfaceClass); 561 } 562 563 /** 564 * Returns the singleton Object. 565 * The first time this is called, an object is created where 566 * the <code>parameterTypes</code> and 567 * <code>parameterValues</code> are constructor parameters and 568 * Properties parameter is used to look up a class name. 569 * <p> 570 * This returns a same instance of the Object each time its 571 * called except if the <code>getClassName</code> method 572 * returns a non-null class name which should only 573 * happen as needed for unit testing. 574 * 575 * @param props the property definitions to use to determine the 576 * @param parameterTypes the class parameters that define the signature 577 * of the constructor to use 578 * @param parameterValues the values to use to construct the current 579 * instance of the object 580 * @return the newly created object 581 * @throws CreationException if unable to create the object 582 */ 583 protected T getObject( 584 final Properties props, 585 final Class[] parameterTypes, 586 final Object[] parameterValues) throws CreationException 587 { 588 // Unit test override, do not use application instance. 589 final String className = getClassName(); 590 if (className != null) { 591 if (this.testSingleInstance == null) { 592 this.testSingleInstance = 593 getTestObject( 594 className, 595 parameterTypes, 596 parameterValues); 597 } 598 return this.testSingleInstance; 599 } 600 601 // NOTE: Should we distinguish between any Properties Object 602 // and that returned by System? When its the System's 603 // Properties Object (which is not a final instance variable 604 // within the System class), then its for sure the user 605 // providing a global override. If its not the System 606 // Properties object, then it may or may not be a global 607 // override so we may not want to set the singleInstance 608 // to it. For now I am ignoring the issue. 609 if (this.singleInstance == null) { 610 final String propClassName = getClassName(props); 611 612 this.singleInstance = (propClassName != null) 613 // The user overriding application default 614 ? getObject(propClassName, parameterTypes, parameterValues) 615 // Get application default 616 : getDefault(parameterTypes, parameterValues); 617 } 618 return this.singleInstance; 619 } 620 621 /** 622 * Create an instance for test purposes. 623 * 624 * @param className the class name used to create Object instance 625 * @param parameterTypes the class parameters that define the signature 626 * of the constructor to use 627 * @param parameterValues the values to use to construct the current 628 * instance of the object 629 * @return the newly created object 630 * @throws CreationException if unable to create the object 631 */ 632 protected T getTestObject( 633 final String className, 634 final Class[] parameterTypes, 635 final Object[] parameterValues) throws CreationException 636 { 637 return getObject(className, parameterTypes, parameterValues); 638 } 639 } 640 641 /** 642 * This is for testing only. 643 * <p> 644 * <code>Context</code> contain the Factory implementation specific 645 * non-default values and mechanism for overriding the default 646 * instance type returned by the Factory. 647 * Factory implementation can extend the <code>Context</code> interface 648 * to capture its specific override values. 649 * If, for example, a Factory implementation uses a <code>ThreadLocal</code> 650 * to override the default instance type for unit tests, then the 651 * <code>Context</code> 652 * will hold the current value of the <code>ThreadLocal</code>. 653 * Getting the Context, clears the <code>ThreadLocal</code> value. 654 * This allows the tester who wishes to create code that will provide 655 * a wrapper around the default instance type to register their 656 * wrapper class name with the <code>ThreadLocal</code>, and, within 657 * the wrapper constructor, get the <code>Context</code>, get 658 * a default instance, and then restore the <code>Context</code>. 659 */ 660 public interface Context { 661 } 662} 663 664// End ObjectFactory.java