1 2 package com.sun.tracing; 3 4 import java.util.HashSet; 5 import java.io.PrintStream; 6 import java.lang.reflect.Field; 7 import java.security.AccessController; 8 import java.security.PrivilegedActionException; 9 import java.security.PrivilegedExceptionAction; 10 import sun.security.action.GetPropertyAction; 11 12 import sun.tracing.NullProviderFactory; 13 import sun.tracing.PrintStreamProviderFactory; 14 import sun.tracing.MultiplexProviderFactory; 15 import sun.tracing.dtrace.DTraceProviderFactory; 16 17 /** 18 * {@code ProviderFactory} is a factory class used to create instances of 19 * providers. 20 * 21 * To enable tracing in an application, this class must be used to create 22 * instances of the provider interfaces defined by users. 23 * The system-defined factory is obtained by using the 24 * {@code getDefaultFactory()} static method. The resulting instance can be 25 * used to create any number of providers. 26 * 27 * @since 1.7 28 */ 29 public abstract class ProviderFactory { 30 31 protected ProviderFactory() {} 32 33 /** 34 * Creates an implementation of a Provider interface. 35 * 36 * @param cls the provider interface to be defined. 37 * @return an implementation of {@code cls}, whose methods, when called, 38 * will trigger tracepoints in the application. 39 * @throws NullPointerException if cls is null 40 * @throws IllegalArgumentException if the class definition contains 41 * non-void methods 42 */ 43 public abstract <T extends Provider> T createProvider(Class<T> cls); 44 45 /** 46 * Returns an implementation of a {@code ProviderFactory} which 47 * creates instances of Providers. 48 * 49 * The created Provider instances will be linked to all appropriate 50 * and enabled system-defined tracing mechanisms in the JDK. 51 * 52 * @return a {@code ProviderFactory} that is used to create Providers. 53 */ 54 public static ProviderFactory getDefaultFactory() { 55 HashSet<ProviderFactory> factories = new HashSet<ProviderFactory>(); 56 57 // Try to instantiate a DTraceProviderFactory 58 String prop = AccessController.doPrivileged( 59 new GetPropertyAction("com.sun.tracing.dtrace")); 60 61 if ( (prop == null || !prop.equals("disable")) && 62 DTraceProviderFactory.isSupported() ) { 63 factories.add(new DTraceProviderFactory()); 64 } 65 66 // Try to instantiate an output stream factory 67 prop = AccessController.doPrivileged( 68 new GetPropertyAction("sun.tracing.stream")); 69 if (prop != null) { 70 for (String spec : prop.split(",")) { 71 PrintStream ps = getPrintStreamFromSpec(spec); 72 if (ps != null) { 73 factories.add(new PrintStreamProviderFactory(ps)); 74 } 75 } 76 } 77 78 // See how many factories we instantiated, and return an appropriate 79 // factory that encapsulates that. 80 if (factories.size() == 0) { 81 return new NullProviderFactory(); 82 } else if (factories.size() == 1) { 83 return factories.toArray(new ProviderFactory[1])[0]; 84 } else { 85 return new MultiplexProviderFactory(factories); 86 } 87 } 88 89 private static PrintStream getPrintStreamFromSpec(final String spec) { 90 try { 91 // spec is in the form of <class>.<field>, where <class> is 92 // a fully specified class name, and <field> is a static member 93 // in that class. The <field> must be a 'PrintStream' or subtype 94 // in order to be used. 95 final int fieldpos = spec.lastIndexOf('.'); 96 final Class<?> cls = Class.forName(spec.substring(0, fieldpos)); 97 98 Field f = AccessController.doPrivileged(new PrivilegedExceptionAction<Field>() { 99 public Field run() throws NoSuchFieldException { 100 return cls.getField(spec.substring(fieldpos + 1)); 101 } 102 }); 103 104 return (PrintStream)f.get(null); 105 } catch (ClassNotFoundException e) { 106 throw new AssertionError(e); 107 } catch (IllegalAccessException e) { 108 throw new AssertionError(e); 109 } catch (PrivilegedActionException e) { 110 throw new AssertionError(e); 111 } 112 } 113 } 114