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