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