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