summaryrefslogtreecommitdiff
path: root/core/java12/com/vladium/emma/EMMAProperties.java
blob: 14bfba453e7b4d87b7ca00e9951744e942440a3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
 * 
 * This program and the accompanying materials are made available under
 * the terms of the Common Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v10.html
 * 
 * $Id: EMMAProperties.java,v 1.1.1.1.2.3 2004/07/16 23:32:03 vlad_r Exp $
 */
package com.vladium.emma;

import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;

import com.vladium.util.ClassLoaderResolver;
import com.vladium.util.IProperties;
import com.vladium.util.Property;
import com.vladium.emma.report.IReportProperties;
import com.vladium.emma.report.ReportProperties;

// ----------------------------------------------------------------------------
/**
 * A reflection of "${IAppConstants.APP_PROPERTY_RES_NAME}.properties" resource
 * as viewed by a given classloader.
 * 
 * @author Vlad Roubtsov, (C) 2003
 */
public
abstract class EMMAProperties
{
    // public: ................................................................
    
    public static final String GENERIC_PROPERTY_OVERRIDE_PREFIX = "D";

    // [the DEFAULT_xxx settings duplicate the defaults in APP_DEFAULT_PROPERTIES_RES_NAME
    // resource to provide a safe fallback option if that resource cannot be loaded]
    
    public static final String DEFAULT_META_DATA_OUT_FILE       = "coverage.em";
    public static final Boolean DEFAULT_META_DATA_OUT_MERGE     = Boolean.TRUE;
    public static final String PREFIX_META_DATA                 = "metadata.";
    public static final String PROPERTY_META_DATA_OUT_FILE      = PREFIX_META_DATA + "out.file";
    public static final String PROPERTY_META_DATA_OUT_MERGE     = PREFIX_META_DATA + "out.merge";
    
    public static final String DEFAULT_COVERAGE_DATA_OUT_FILE   = "coverage.ec";
    public static final Boolean DEFAULT_COVERAGE_DATA_OUT_MERGE = Boolean.TRUE;
    public static final String PREFIX_COVERAGE_DATA             = "coverage.";
    public static final String PROPERTY_COVERAGE_DATA_OUT_FILE  = PREFIX_COVERAGE_DATA + "out.file";
    public static final String PROPERTY_COVERAGE_DATA_OUT_MERGE = PREFIX_COVERAGE_DATA + "out.merge";

    public static final String DEFAULT_SESSION_DATA_OUT_FILE    = "coverage.es";
    public static final Boolean DEFAULT_SESSION_DATA_OUT_MERGE  = Boolean.TRUE;
    public static final String PREFIX_SESSION_DATA              = "session.";
    public static final String PROPERTY_SESSION_DATA_OUT_FILE   = PREFIX_SESSION_DATA + "out.file";
    public static final String PROPERTY_SESSION_DATA_OUT_MERGE  = PREFIX_SESSION_DATA + "out.merge";
    
    public static final String PROPERTY_TEMP_FILE_EXT           = ".et";
    
    public static final Map SYSTEM_PROPERTY_REDIRECTS; // set in <clinit>
    
    
    /**
     * Global method used to create an appearance that all app work has been
     * done at the same point in time (useful for setting archive and report
     * timestamps etc).
     * 
     * @return the result of System.currentTimeMillis (), evaluated on the
     * first call only
     */
    public static synchronized long getTimeStamp ()
    {
        long result = s_timestamp;
        if (result == 0)
        {
            s_timestamp = result = System.currentTimeMillis ();
        }

        return result; 
    }
    
    
    public static String makeAppVersion (final int major, final int minor, final int build)
    {
        final StringBuffer buf = new StringBuffer ();
        
        buf.append (major);
        buf.append ('.');
        buf.append (minor);
        buf.append ('.');
        buf.append (build);
        
        return buf.toString ();
    }
    
    
    /**
     * Wraps a Properties into a IProperties with the app's standard property
     * mapping in place.
     * 
     * @param properties [null results in null result]
     */
    public static IProperties wrap (final Properties properties)
    {
        if (properties == null) return null;
        
        return IProperties.Factory.wrap (properties, ReportProperties.REPORT_PROPERTY_MAPPER);
    }
   
    /**
     * Retrieves application properties as classloader resource with a given name.
     * [as seen from ClassLoaderResolver.getClassLoader ()]. The result is cached
     * using this loader as a weak key.
     * 
     * @return properties [can be null]
     */
    public static synchronized IProperties getAppProperties ()
    {
        final ClassLoader loader = ClassLoaderResolver.getClassLoader ();
        
        return getAppProperties (loader);
    }

    public static synchronized IProperties getAppProperties (final ClassLoader loader)
    {
        IProperties properties = (IProperties) s_properties.get (loader);

        if (properties != null)
            return properties;
        else
        {
            final String appName = IAppConstants.APP_NAME_LC;
            
            // note: this does not use Property.getAppProperties() by design,
            // because that mechanism is not property alias-capable
            
            final IProperties systemRedirects = wrap (Property.getSystemPropertyRedirects (EMMAProperties.SYSTEM_PROPERTY_REDIRECTS));
            final IProperties appDefaults = wrap (Property.getProperties (appName + "_default.properties", loader));
            final IProperties systemFile;
            {
                final String fileName = Property.getSystemProperty (appName + ".properties");
                final File file = fileName != null
                    ? new File (fileName)
                    : null;

                systemFile = wrap (Property.getLazyPropertiesFromFile (file));
            }
            final IProperties system = wrap (Property.getSystemProperties (appName));
            final IProperties userOverrides = wrap (Property.getProperties (appName + ".properties", loader));
            
            // "vertical" inheritance order:
            //      (1) user overrides ("emma.properties" classloader resource)
            //      (2) system properties (java.lang.System.getProperties(),
            //                             filtered by the app prefix)
            //      (3) system file properties ("emma.properties" system property,
            //                                  interpreted as a property file)
            //      (4) app defaults ("emma_default.properties" classloader resource)
            //      (5) system property redirects (report.out.encoding->file.encoding,
            //                                     report.out.dir->user.dir, etc)
        
            properties = IProperties.Factory.combine (userOverrides,
                         IProperties.Factory.combine (system,
                         IProperties.Factory.combine (systemFile,
                         IProperties.Factory.combine (appDefaults,
                                                      systemRedirects))));

            s_properties.put (loader, properties);
            
            return properties;
        }
    }
    
    // protected: .............................................................

    // package: ...............................................................
    
    // private: ...............................................................
    
    
    private EMMAProperties () {} // prevent subclassing
        
    
    private static long s_timestamp;
    
    private static final Map /* ClassLoader->Properties */ s_properties; // set in <clinit>
    
    static
    {
        s_properties = new WeakHashMap ();
        
        final Map redirects = new HashMap ();
        redirects.put (IReportProperties.PREFIX.concat (IReportProperties.OUT_ENCODING),
                       "file.encoding");
        redirects.put (IReportProperties.PREFIX.concat (IReportProperties.OUT_DIR),
                       "user.dir");
                       
        SYSTEM_PROPERTY_REDIRECTS = Collections.unmodifiableMap (redirects);
    }

} // end of class
// ----------------------------------------------------------------------------