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