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