Home | History | Annotate | Download | only in emma
      1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
      2  *
      3  * This program and the accompanying materials are made available under
      4  * the terms of the Common Public License v1.0 which accompanies this distribution,
      5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
      6  *
      7  * $Id: EMMAProperties.java,v 1.1.1.1.2.3 2004/07/16 23:32:03 vlad_r Exp $
      8  */
      9 package com.vladium.emma;
     10 
     11 import java.io.File;
     12 import java.util.Collections;
     13 import java.util.HashMap;
     14 import java.util.Map;
     15 import java.util.Properties;
     16 import java.util.WeakHashMap;
     17 
     18 import com.vladium.util.ClassLoaderResolver;
     19 import com.vladium.util.IProperties;
     20 import com.vladium.util.Property;
     21 import com.vladium.emma.report.IReportProperties;
     22 import com.vladium.emma.report.ReportProperties;
     23 
     24 // ----------------------------------------------------------------------------
     25 /**
     26  * A reflection of "${IAppConstants.APP_PROPERTY_RES_NAME}.properties" resource
     27  * as viewed by a given classloader.
     28  *
     29  * @author Vlad Roubtsov, (C) 2003
     30  */
     31 public
     32 abstract class EMMAProperties
     33 {
     34     // public: ................................................................
     35 
     36     public static final String GENERIC_PROPERTY_OVERRIDE_PREFIX = "D";
     37 
     38     // [the DEFAULT_xxx settings duplicate the defaults in APP_DEFAULT_PROPERTIES_RES_NAME
     39     // resource to provide a safe fallback option if that resource cannot be loaded]
     40 
     41     public static final String DEFAULT_META_DATA_OUT_FILE       = "coverage.em";
     42     public static final Boolean DEFAULT_META_DATA_OUT_MERGE     = Boolean.TRUE;
     43     public static final String PREFIX_META_DATA                 = "metadata.";
     44     public static final String PROPERTY_META_DATA_OUT_FILE      = PREFIX_META_DATA + "out.file";
     45     public static final String PROPERTY_META_DATA_OUT_MERGE     = PREFIX_META_DATA + "out.merge";
     46 
     47     public static final String DEFAULT_COVERAGE_DATA_OUT_FILE   = "coverage.ec";
     48     public static final Boolean DEFAULT_COVERAGE_DATA_OUT_MERGE = Boolean.TRUE;
     49     public static final String PREFIX_COVERAGE_DATA             = "coverage.";
     50     public static final String PROPERTY_COVERAGE_DATA_OUT_FILE  = PREFIX_COVERAGE_DATA + "out.file";
     51     public static final String PROPERTY_COVERAGE_DATA_OUT_MERGE = PREFIX_COVERAGE_DATA + "out.merge";
     52 
     53     public static final String DEFAULT_SESSION_DATA_OUT_FILE    = "coverage.es";
     54     public static final Boolean DEFAULT_SESSION_DATA_OUT_MERGE  = Boolean.TRUE;
     55     public static final String PREFIX_SESSION_DATA              = "session.";
     56     public static final String PROPERTY_SESSION_DATA_OUT_FILE   = PREFIX_SESSION_DATA + "out.file";
     57     public static final String PROPERTY_SESSION_DATA_OUT_MERGE  = PREFIX_SESSION_DATA + "out.merge";
     58 
     59     public static final String PROPERTY_TEMP_FILE_EXT           = ".et";
     60 
     61     public static final Map SYSTEM_PROPERTY_REDIRECTS; // set in <clinit>
     62 
     63 
     64     /**
     65      * Global method used to create an appearance that all app work has been
     66      * done at the same point in time (useful for setting archive and report
     67      * timestamps etc).
     68      *
     69      * @return the result of System.currentTimeMillis (), evaluated on the
     70      * first call only
     71      */
     72     public static synchronized long getTimeStamp ()
     73     {
     74         long result = s_timestamp;
     75         if (result == 0)
     76         {
     77             s_timestamp = result = System.currentTimeMillis ();
     78         }
     79 
     80         return result;
     81     }
     82 
     83 
     84     public static String makeAppVersion (final int major, final int minor, final int build)
     85     {
     86         final StringBuffer buf = new StringBuffer ();
     87 
     88         buf.append (major);
     89         buf.append ('.');
     90         buf.append (minor);
     91         buf.append ('.');
     92         buf.append (build);
     93 
     94         return buf.toString ();
     95     }
     96 
     97 
     98     /**
     99      * Wraps a Properties into a IProperties with the app's standard property
    100      * mapping in place.
    101      *
    102      * @param properties [null results in null result]
    103      */
    104     public static IProperties wrap (final Properties properties)
    105     {
    106         if (properties == null) return null;
    107 
    108         return IProperties.Factory.wrap (properties, ReportProperties.REPORT_PROPERTY_MAPPER);
    109     }
    110 
    111     /**
    112      * Retrieves application properties as classloader resource with a given name.
    113      * [as seen from ClassLoaderResolver.getClassLoader ()]. The result is cached
    114      * using this loader as a weak key.
    115      *
    116      * @return properties [can be null]
    117      */
    118     public static synchronized IProperties getAppProperties ()
    119     {
    120         final ClassLoader loader = ClassLoaderResolver.getClassLoader ();
    121 
    122         return getAppProperties (loader);
    123     }
    124 
    125     public static synchronized IProperties getAppProperties (final ClassLoader loader)
    126     {
    127         IProperties properties = (IProperties) s_properties.get (loader);
    128 
    129         if (properties != null)
    130             return properties;
    131         else
    132         {
    133             final String appName = IAppConstants.APP_NAME_LC;
    134 
    135             // note: this does not use Property.getAppProperties() by design,
    136             // because that mechanism is not property alias-capable
    137 
    138             final IProperties systemRedirects = wrap (Property.getSystemPropertyRedirects (EMMAProperties.SYSTEM_PROPERTY_REDIRECTS));
    139             final IProperties appDefaults = wrap (Property.getProperties (appName + "_default.properties", loader));
    140             final IProperties systemFile;
    141             {
    142                 final String fileName = Property.getSystemProperty (appName + ".properties");
    143                 final File file = fileName != null
    144                     ? new File (fileName)
    145                     : null;
    146 
    147                 systemFile = wrap (Property.getLazyPropertiesFromFile (file));
    148             }
    149             final IProperties system = wrap (Property.getSystemProperties (appName));
    150             final IProperties userOverrides = wrap (Property.getProperties (appName + ".properties", loader));
    151 
    152             // "vertical" inheritance order:
    153             //      (1) user overrides ("emma.properties" classloader resource)
    154             //      (2) system properties (java.lang.System.getProperties(),
    155             //                             filtered by the app prefix)
    156             //      (3) system file properties ("emma.properties" system property,
    157             //                                  interpreted as a property file)
    158             //      (4) app defaults ("emma_default.properties" classloader resource)
    159             //      (5) system property redirects (report.out.encoding->file.encoding,
    160             //                                     report.out.dir->user.dir, etc)
    161 
    162             properties = IProperties.Factory.combine (userOverrides,
    163                          IProperties.Factory.combine (system,
    164                          IProperties.Factory.combine (systemFile,
    165                          IProperties.Factory.combine (appDefaults,
    166                                                       systemRedirects))));
    167 
    168             s_properties.put (loader, properties);
    169 
    170             return properties;
    171         }
    172     }
    173 
    174     // protected: .............................................................
    175 
    176     // package: ...............................................................
    177 
    178     // private: ...............................................................
    179 
    180 
    181     private EMMAProperties () {} // prevent subclassing
    182 
    183 
    184     private static long s_timestamp;
    185 
    186     private static final Map /* ClassLoader->Properties */ s_properties; // set in <clinit>
    187 
    188     static
    189     {
    190         s_properties = new WeakHashMap ();
    191 
    192         final Map redirects = new HashMap ();
    193         redirects.put (IReportProperties.PREFIX.concat (IReportProperties.OUT_ENCODING),
    194                        "file.encoding");
    195         redirects.put (IReportProperties.PREFIX.concat (IReportProperties.OUT_DIR),
    196                        "user.dir");
    197 
    198         SYSTEM_PROPERTY_REDIRECTS = Collections.unmodifiableMap (redirects);
    199     }
    200 
    201 } // end of class
    202 // ----------------------------------------------------------------------------
    203