1 /* 2 * Copyright (c) 1999, 2013, 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 java.security.AccessController.doPrivileged( 106 new java.security.PrivilegedAction<Void>() { 107 public Void run() { 108 loadProperties(); 109 return null; 110 } 111 }); 112 } 113 114 /* 115 * Load debug properties from file, then override 116 * with any command line specified properties 117 */ 118 private synchronized void loadProperties() { 119 // setup initial properties 120 java.security.AccessController.doPrivileged( 121 new java.security.PrivilegedAction<Void>() { 122 public Void 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.Level.FINE)) { 132 log.fine("DebugSettings:\n{0}", this); 133 } 134 } 135 136 public String toString() { 137 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 138 PrintStream pout = new PrintStream(bout); 139 for (String key : props.stringPropertyNames()) { 140 String value = props.getProperty(key, ""); 141 pout.println(key + " = " + value); 142 } 143 return new String(bout.toByteArray()); 144 } 145 146 /* 147 * Sets up default property values 148 */ 149 private void loadDefaultProperties() { 150 // is there a more inefficient way to setup default properties? 151 // maybe, but this has got to be close to 100% non-optimal 152 try { 153 for ( int nprop = 0; nprop < DEFAULT_PROPS.length; nprop++ ) { 154 StringBufferInputStream in = new StringBufferInputStream(DEFAULT_PROPS[nprop]); 155 props.load(in); 156 in.close(); 157 } 158 } catch(IOException ioe) { 159 } 160 } 161 162 /* 163 * load properties from file, overriding defaults 164 */ 165 private void loadFileProperties() { 166 String propPath; 167 Properties fileProps; 168 169 // check if the user specified a particular settings file 170 propPath = System.getProperty(PREFIX + "." + PROP_FILE, ""); 171 if (propPath.equals("")) { 172 // otherwise get it from the user's home directory 173 propPath = System.getProperty("user.home", "") + 174 File.separator + 175 PREFIX + "." + PROP_FILE; 176 } 177 178 File propFile = new File(propPath); 179 try { 180 println("Reading debug settings from '" + propFile.getCanonicalPath() + "'..."); 181 FileInputStream fin = new FileInputStream(propFile); 182 props.load(fin); 183 fin.close(); 184 } catch ( FileNotFoundException fne ) { 185 println("Did not find settings file."); 186 } catch ( IOException ioe ) { 187 println("Problem reading settings, IOException: " + ioe.getMessage()); 188 } 189 } 190 191 /* 192 * load properties from system props (command line spec'd usually), 193 * overriding default or file properties 194 */ 195 private void loadSystemProperties() { 196 // override file properties with system properties 197 Properties sysProps = System.getProperties(); 198 for (String key : sysProps.stringPropertyNames()) { 199 String value = sysProps.getProperty(key,""); 200 // copy any "awtdebug" properties over 201 if ( key.startsWith(PREFIX) ) { 202 props.setProperty(key, value); 203 } 204 } 205 } 206 207 /** 208 * Gets named boolean property 209 * @param key Name of property 210 * @param defval Default value if property does not exist 211 * @return boolean value of the named property 212 */ 213 public synchronized boolean getBoolean(String key, boolean defval) { 214 String value = getString(key, String.valueOf(defval)); 215 return value.equalsIgnoreCase("true"); 216 } 217 218 /** 219 * Gets named integer property 220 * @param key Name of property 221 * @param defval Default value if property does not exist 222 * @return integer value of the named property 223 */ 224 public synchronized int getInt(String key, int defval) { 225 String value = getString(key, String.valueOf(defval)); 226 return Integer.parseInt(value); 227 } 228 229 /** 230 * Gets named String property 231 * @param key Name of property 232 * @param defval Default value if property does not exist 233 * @return string value of the named property 234 */ 235 public synchronized String getString(String key, String defval) { 236 String actualKeyName = PREFIX + "." + key; 237 String value = props.getProperty(actualKeyName, defval); 238 //println(actualKeyName+"="+value); 239 return value; 240 } 241 242 private synchronized List<String> getPropertyNames() { 243 List<String> propNames = new LinkedList<>(); 244 // remove global prefix from property names 245 for (String propName : props.stringPropertyNames()) { 246 propName = propName.substring(PREFIX.length()+1); 247 propNames.add(propName); 248 } 249 return propNames; 250 } 251 252 private void println(Object object) { 253 if (log.isLoggable(PlatformLogger.Level.FINER)) { 254 log.finer(object.toString()); 255 } 256 } 257 258 private static final String PROP_CTRACE = "ctrace"; 259 private static final int PROP_CTRACE_LEN = PROP_CTRACE.length(); 260 261 private native synchronized void setCTracingOn(boolean enabled); 262 private native synchronized void setCTracingOn(boolean enabled, String file); 263 private native synchronized void setCTracingOn(boolean enabled, String file, int line); 264 265 private void loadNativeSettings() { 266 boolean ctracingOn; 267 268 ctracingOn = getBoolean(PROP_CTRACE, false); 269 setCTracingOn(ctracingOn); 270 271 // 272 // Filter out file/line ctrace properties from debug settings 273 // 274 List<String> traces = new LinkedList<>(); 275 276 for (String key : getPropertyNames()) { 277 if (key.startsWith(PROP_CTRACE) && key.length() > PROP_CTRACE_LEN) { 278 traces.add(key); 279 } 280 } 281 282 // sort traces list so file-level traces will be before line-level ones 283 Collections.sort(traces); 284 285 // 286 // Setup the trace points 287 // 288 for (String key : traces) { 289 String trace = key.substring(PROP_CTRACE_LEN+1); 290 String filespec; 291 String linespec; 292 int delim= trace.indexOf('@'); 293 boolean enabled; 294 295 // parse out the filename and linenumber from the property name 296 filespec = delim != -1 ? trace.substring(0, delim) : trace; 297 linespec = delim != -1 ? trace.substring(delim+1) : ""; 298 enabled = getBoolean(key, false); 299 //System.out.println("Key="+key+", File="+filespec+", Line="+linespec+", Enabled="+enabled); 300 301 if ( linespec.length() == 0 ) { 302 // set file specific trace setting 303 setCTracingOn(enabled, filespec); 304 } else { 305 // set line specific trace setting 306 int linenum = Integer.parseInt(linespec, 10); 307 setCTracingOn(enabled, filespec, linenum); 308 } 309 } 310 } 311 }