001    /*
002    // $Id: //open/mondrian/src/main/mondrian/util/MemoryMonitorFactory.java#8 $
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) 2002-2002 Kana Software, Inc.
007    // Copyright (C) 2002-2008 Julian Hyde and others
008    // All Rights Reserved.
009    // You must accept the terms of that agreement to use this software.
010    //
011    // jhyde, Dec 23, 2002
012    */
013    package mondrian.util;
014    
015    import org.eigenbase.util.property.StringProperty;
016    import mondrian.olap.MondrianProperties;
017    import mondrian.olap.Util;
018    
019    /**
020     * The <code>MemoryMonitorFactory</code> is used to get the application's
021     * <code>MemoryMonitor</code>. The <code>MemoryMonitorFactory</code> is
022     * based upon the <code>ObjectFactory.Singleton</code> generic. The
023     * <code>MemoryMonitorFactory</code> implementation has a single, default
024     * <code>MemoryMonitor</code> per JVM instance which can be overridden
025     * using the provided <code>ThreadLocal</code> variable. Normally, this
026     * <code>ThreadLocal</code> override should only be used during JUnit testing.
027     * The JUnit test, set the <code>ThreadLocal</code> variable to the name of its
028     * own implementation of the <code>MemoryMonitor</code> interface and
029     * then calls the <code>ObjectFactory</code> <code>getObject</code> method.
030     * After doing the test, the <code>ThreadLocal</code> variable should
031     * be cleared.
032     * <p>
033     * The <code>ObjectFactory.Singleton</code> permits the use
034     * of <code>System</code> properties to provide a class name to the
035     * factory. This can be used to create a <code>MemoryMonitor</code>
036     * that is not the default one. The property name is the
037     * <code>MemoryMonitor</code> class name, "mondrian.util.MemoryMonitor".
038     *
039     * @author <a>Richard M. Emberson</a>
040     * @since Feb 03 2007
041     * @version $Id: //open/mondrian/src/main/mondrian/util/MemoryMonitorFactory.java#8 $
042     */
043    public final class MemoryMonitorFactory
044            extends ObjectFactory.Singleton<MemoryMonitor> {
045    
046        /**
047         * Single instance of the <code>MemoryMonitorFactory</code>.
048         */
049        private static final MemoryMonitorFactory factory;
050        static {
051            factory = new MemoryMonitorFactory();
052        }
053    
054        /**
055         * Access the <code>MemoryMonitorFactory</code> instance.
056         *
057         * @return the <code>MemoryMonitor</code>.
058         */
059        public static MemoryMonitor getMemoryMonitor() {
060            return factory.getObject();
061        }
062    
063        /**
064         * ThreadLocal used to hold the class name of an <code>MemoryMonitor</code>
065         * implementation. Generally, this should only be used for testing.
066         */
067        private static final ThreadLocal<String> ClassName =
068            new ThreadLocal<String>();
069    
070        /**
071         * Get the class name of a <code>MemoryMonitor</code> implementation
072         * or null.
073         *
074         * @return the class name or null.
075         */
076        private static String getThreadLocalClassName() {
077            return ClassName.get();
078        }
079    
080        /**
081         * Sets the class name of a  <code>MemoryMonitor</code> implementation.
082         * This should be called (obviously) before calling the
083         * <code>MemoryMonitorFactory</code> <code>getMemoryMonitor</code>
084         * method to get the <code>MemoryMonitor</code> implementation.
085         * Generally, this is only used for testing.
086         *
087         * @param className Class name
088         */
089        public static void setThreadLocalClassName(String className) {
090            ClassName.set(className);
091        }
092    
093        /**
094         * Clears the class name (regardless of whether a class name was set).
095         * When a class name is set using <code>setThreadLocalClassName</code>,
096         * the setting whould be done in a try-block and a call to this
097         * clear method should be in the finally-clause of that try-block.
098         */
099        public static void clearThreadLocalClassName() {
100            ClassName.set(null);
101            if (factory.testSingleInstance != null) {
102                factory.testSingleInstance.removeAllListener();
103                factory.testSingleInstance = null;
104            }
105            if (factory.singleInstance instanceof MemoryMonitor.Test) {
106                ((MemoryMonitor.Test) factory.singleInstance).resetFromTest();
107            }
108        }
109    
110        /**
111         * The constructor for the <code>MemoryMonitorFactory</code>. This passes
112         * the <code>MemoryMonitor</code> class to the <code>ObjectFactory</code>
113         * base class.
114         */
115        private MemoryMonitorFactory() {
116            super(MemoryMonitor.class);
117        }
118    
119        /**
120         * Returns whether the use of a <code>MemoryMonitor</code> is enabled.
121         *
122         * @return <code>true</code> if enabled and <code>false</code> otherwise.
123         */
124        protected boolean enabled() {
125            return MondrianProperties.instance().MemoryMonitor.get();
126        }
127    
128        /**
129         * Get the class name set in the <code>ThreadLocal</code> or null.
130         *
131         * @return class name or null.
132         */
133        protected String getClassName() {
134            return getThreadLocalClassName();
135        }
136    
137        /**
138         * Return the <code>MemoryMonitorFactory</code property name.
139         *
140         * @return <code>MemoryMonitorFactory</code> property name
141         */
142        protected StringProperty getStringProperty() {
143            return MondrianProperties.instance().MemoryMonitorClass;
144        }
145    
146        /**
147         * The <code>MemoryMonitorFactory</code>'s implementation of the
148         * <code>ObjectFactory</code>'s abstract method which returns
149         * the default <code>MemoryMonitor</code> instance.
150         * For Java4 or if the <code>MemoryMonitorFactory</code> is not enabled
151         * then this method returns the "faux" <code>MemoryMonitor</code>
152         * implementation, it does nothing. When enabled and for
153         * Java5 and above JVMs, and instance of the
154         * <code>NotificationMemoryMonitor</code> is returned.
155         *
156         * @param parameterTypes  not used
157         * @param parameterValues  not used
158         * @return <code>MemoryMonitor</code> instance
159         * @throws CreationException if the <code>MemoryMonitor</code> can not be
160         * created.
161         */
162        protected MemoryMonitor getDefault(Class[] parameterTypes,
163                                           Object[] parameterValues)
164                throws CreationException {
165            return (! enabled() || Util.PreJdk15)
166                        // not enabled or Java4 or below
167                    ? new FauxMemoryMonitor()
168                        // enabled and Java5 or above
169                    : new NotificationMemoryMonitor();
170        }
171    
172    }
173    
174    // End MemoryMonitorFactory.java