1 /* 2 * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt; 27 28 import java.io.*; 29 30 import java.util.*; 31 import sun.util.logging.PlatformLogger; 32 33 /* 34 * Internal class that manages sun.awt.Debug settings. 35 * Settings can be specified on a global, per-package, 36 * or per-class level. 37 * 38 * Properties affecting the behaviour of the Debug class are 39 * loaded from the awtdebug.properties file at class load 40 * time. The properties file is assumed to be in the 41 * user.home directory. A different file can be used 42 * by setting the awtdebug.properties system property. 43 * e.g. java -Dawtdebug.properties=foo.properties 44 * 45 * Only properties beginning with 'awtdebug' have any 46 * meaning-- all other properties are ignored. 47 * 48 * You can override the properties file by specifying 49 * 'awtdebug' props as system properties on the command line. 50 * e.g. java -Dawtdebug.trace=true 51 * Properties specific to a package or a class can be set 52 * by qualifying the property names as follows: 53 * awtdebug.<property name>.<class or package name> 54 * So for example, turning on tracing in the com.acme.Fubar 55 * class would be done as follows: 56 * awtdebug.trace.com.acme.Fubar=true 57 * 58 * Class settings always override package settings, which in 59 * turn override global settings. 60 * 61 * Addition from July, 2007. 62 * 63 * After the fix for 4638447 all the usage of DebugHelper 64 * classes in Java code are replaced with the corresponding 65 * Java Logging API calls. This file is now used only to 66 * control native logging. 67 * 68 * To enable native logging you should set the following 69 * system property to 'true': sun.awt.nativedebug. After 70 * the native logging is enabled, the actual debug settings 71 * are read the same way as described above (as before 72 * the fix for 4638447). 73 */ 74 final class DebugSettings { 75 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.debug.DebugSettings"); 76 77 /* standard debug property key names */ 78 static final String PREFIX = "awtdebug"; 79 static final String PROP_FILE = "properties"; 80 81 /* default property settings */ 82 private static final String DEFAULT_PROPS[] = { 83 "awtdebug.assert=true", 84 "awtdebug.trace=false", 85 "awtdebug.on=true", 86 "awtdebug.ctrace=false" 87 }; 88 89 /* global instance of the settings object */ 90 private static DebugSettings instance = null; 91 92 private Properties props = new Properties(); 93 94 static void init() { 95 if (instance != null) { 96 return; 97 } 98 99 NativeLibLoader.loadLibraries(); 100 instance = new DebugSettings(); 101 instance.loadNativeSettings(); 102 } 103 104 private DebugSettings() { 105 new java.security.PrivilegedAction() { 106 public Object run() { 107 loadProperties(); 108 return null; 109 } 110 }.run(); 111 } 112 113 /* 114 * Load debug properties from file, then override 115 * with any command line specified properties 116 */ 117 private synchronized void loadProperties() { 118 // setup initial properties 119 java.security.AccessController.doPrivileged( 120 new java.security.PrivilegedAction() 121 { 122 public Object run() { 123 loadDefaultProperties(); 124 loadFileProperties(); 125 loadSystemProperties(); 126 return null; 127 } 128 }); 129 130 // echo the initial property settings to stdout 131 if (log.isLoggable(PlatformLogger.FINE)) { 132 log.fine("DebugSettings:\n{0}" + this); 133 } 134 } 135 136 public String toString() { 137 Enumeration enum_ = props.propertyNames(); 138 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 139 PrintStream pout = new PrintStream(bout); 140 141 while (enum_.hasMoreElements()) { 142 String key = (String)enum_.nextElement(); 143 String value = props.getProperty(key, ""); 144 pout.println(key + " = " + value); 145 } 146 return new String(bout.toByteArray()); 147 } 148 149 /* 150 * Sets up default property values 151 */ 152 private void loadDefaultProperties() { 153 // is there a more inefficient way to setup default properties? 154 // maybe, but this has got to be close to 100% non-optimal 155 try { 156 for ( int nprop = 0; nprop < DEFAULT_PROPS.length; nprop++ ) { 157 StringBufferInputStream in = new StringBufferInputStream(DEFAULT_PROPS[nprop]); 158 props.load(in); 159 in.close(); 160 } 161 } catch(IOException ioe) { 162 } 163 } 164 165 /* 166 * load properties from file, overriding defaults 167 */ 168 private void loadFileProperties() { 169 String propPath; 170 Properties fileProps; 171 172 // check if the user specified a particular settings file 173 propPath = System.getProperty(PREFIX + "." + PROP_FILE, ""); 174 if (propPath.equals("")) { 175 // otherwise get it from the user's home directory 176 propPath = System.getProperty("user.home", "") + 177 File.separator + 178 PREFIX + "." + PROP_FILE; 179 } 180 181 File propFile = new File(propPath); 182 try { 183 println("Reading debug settings from '" + propFile.getCanonicalPath() + "'..."); 184 FileInputStream fin = new FileInputStream(propFile); 185 props.load(fin); 186 fin.close(); 187 } catch ( FileNotFoundException fne ) { 188 println("Did not find settings file."); 189 } catch ( IOException ioe ) { 190 println("Problem reading settings, IOException: " + ioe.getMessage()); 191 } 192 } 193 194 /* 195 * load properties from system props (command line spec'd usually), 196 * overriding default or file properties 197 */ 198 private void loadSystemProperties() { 199 // override file properties with system properties 200 Properties sysProps = System.getProperties(); 201 Enumeration enum_ = sysProps.propertyNames(); 202 while ( enum_.hasMoreElements() ) { 203 String key = (String)enum_.nextElement(); 204 String value = sysProps.getProperty(key,""); 205 // copy any "awtdebug" properties over 206 if ( key.startsWith(PREFIX) ) { 207 props.setProperty(key, value); 208 } 209 } 210 } 211 212 /** 213 * Gets named boolean property 214 * @param key Name of property 215 * @param defval Default value if property does not exist 216 * @return boolean value of the named property 217 */ 218 public synchronized boolean getBoolean(String key, boolean defval) { 219 String value = getString(key, String.valueOf(defval)); 220 return value.equalsIgnoreCase("true"); 221 } 222 223 /** 224 * Gets named integer property 225 * @param key Name of property 226 * @param defval Default value if property does not exist 227 * @return integer value of the named property 228 */ 229 public synchronized int getInt(String key, int defval) { 230 String value = getString(key, String.valueOf(defval)); 231 return Integer.parseInt(value); 232 } 233 234 /** 235 * Gets named String property 236 * @param key Name of property 237 * @param defval Default value if property does not exist 238 * @return string value of the named property 239 */ 240 public synchronized String getString(String key, String defval) { 241 String actualKeyName = PREFIX + "." + key; 242 String value = props.getProperty(actualKeyName, defval); 243 //println(actualKeyName+"="+value); 244 return value; 245 } 246 247 public synchronized Enumeration getPropertyNames() { 248 Vector propNames = new Vector(); 249 Enumeration enum_ = props.propertyNames(); 250 251 // remove global prefix from property names 252 while ( enum_.hasMoreElements() ) { 253 String propName = (String)enum_.nextElement(); 254 propName = propName.substring(PREFIX.length()+1); 255 propNames.addElement(propName); 256 } 257 return propNames.elements(); 258 } 259 260 private void println(Object object) { 261 if (log.isLoggable(PlatformLogger.FINER)) { 262 log.finer(object.toString()); 263 } 264 } 265 266 private static final String PROP_CTRACE = "ctrace"; 267 private static final int PROP_CTRACE_LEN = PROP_CTRACE.length(); 268 269 private native synchronized void setCTracingOn(boolean enabled); 270 private native synchronized void setCTracingOn(boolean enabled, String file); 271 private native synchronized void setCTracingOn(boolean enabled, String file, int line); 272 273 private void loadNativeSettings() { 274 boolean ctracingOn; 275 276 ctracingOn = getBoolean(PROP_CTRACE, false); 277 setCTracingOn(ctracingOn); 278 279 // 280 // Filter out file/line ctrace properties from debug settings 281 // 282 Vector traces = new Vector(); 283 Enumeration enum_ = getPropertyNames(); 284 285 while ( enum_.hasMoreElements() ) { 286 String key = (String)enum_.nextElement(); 287 if ( key.startsWith(PROP_CTRACE) && key.length() > PROP_CTRACE_LEN ) { 288 traces.addElement(key); 289 } 290 } 291 292 // sort traces list so file-level traces will be before line-level ones 293 Collections.sort(traces); 294 295 // 296 // Setup the trace points 297 // 298 Enumeration enumTraces = traces.elements(); 299 300 while ( enumTraces.hasMoreElements() ) { 301 String key = (String)enumTraces.nextElement(); 302 String trace = key.substring(PROP_CTRACE_LEN+1); 303 String filespec; 304 String linespec; 305 int delim= trace.indexOf('@'); 306 boolean enabled; 307 308 // parse out the filename and linenumber from the property name 309 filespec = delim != -1 ? trace.substring(0, delim) : trace; 310 linespec = delim != -1 ? trace.substring(delim+1) : ""; 311 enabled = getBoolean(key, false); 312 //System.out.println("Key="+key+", File="+filespec+", Line="+linespec+", Enabled="+enabled); 313 314 if ( linespec.length() == 0 ) { 315 // set file specific trace setting 316 setCTracingOn(enabled, filespec); 317 } else { 318 // set line specific trace setting 319 int linenum = Integer.parseInt(linespec, 10); 320 setCTracingOn(enabled, filespec, linenum); 321 } 322 } 323 } 324 }