147d431f63a66505a645f282416659a9758a91f1cBrett Chabot/*
247d431f63a66505a645f282416659a9758a91f1cBrett Chabot * Copyright 2003-2009 OFFIS, Henri Tremblay
347d431f63a66505a645f282416659a9758a91f1cBrett Chabot *
447d431f63a66505a645f282416659a9758a91f1cBrett Chabot * Licensed under the Apache License, Version 2.0 (the "License");
547d431f63a66505a645f282416659a9758a91f1cBrett Chabot * you may not use this file except in compliance with the License.
647d431f63a66505a645f282416659a9758a91f1cBrett Chabot * You may obtain a copy of the License at
747d431f63a66505a645f282416659a9758a91f1cBrett Chabot *
847d431f63a66505a645f282416659a9758a91f1cBrett Chabot *     http://www.apache.org/licenses/LICENSE-2.0
947d431f63a66505a645f282416659a9758a91f1cBrett Chabot *
1047d431f63a66505a645f282416659a9758a91f1cBrett Chabot * Unless required by applicable law or agreed to in writing, software
1147d431f63a66505a645f282416659a9758a91f1cBrett Chabot * distributed under the License is distributed on an "AS IS" BASIS,
1247d431f63a66505a645f282416659a9758a91f1cBrett Chabot * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1347d431f63a66505a645f282416659a9758a91f1cBrett Chabot * See the License for the specific language governing permissions and
1447d431f63a66505a645f282416659a9758a91f1cBrett Chabot * limitations under the License.
1547d431f63a66505a645f282416659a9758a91f1cBrett Chabot */
1647d431f63a66505a645f282416659a9758a91f1cBrett Chabotpackage org.easymock.internal;
1747d431f63a66505a645f282416659a9758a91f1cBrett Chabot
1847d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.io.BufferedInputStream;
1947d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.io.IOException;
2047d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.io.InputStream;
2147d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.util.Map;
2247d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.util.Properties;
2347d431f63a66505a645f282416659a9758a91f1cBrett Chabot
2447d431f63a66505a645f282416659a9758a91f1cBrett Chabot/**
2547d431f63a66505a645f282416659a9758a91f1cBrett Chabot * Contains properties used by EasyMock to change its default behavior. The
2647d431f63a66505a645f282416659a9758a91f1cBrett Chabot * loading order is (any step being able to overload the properties of the
2747d431f63a66505a645f282416659a9758a91f1cBrett Chabot * previous step):
2847d431f63a66505a645f282416659a9758a91f1cBrett Chabot * <ul>
2947d431f63a66505a645f282416659a9758a91f1cBrett Chabot * <li>easymock.properties in classpath default package</li>
3047d431f63a66505a645f282416659a9758a91f1cBrett Chabot * <li>System properties</li>
3147d431f63a66505a645f282416659a9758a91f1cBrett Chabot * <li>explicit call to setProperty</li>
3247d431f63a66505a645f282416659a9758a91f1cBrett Chabot * </ul>
3347d431f63a66505a645f282416659a9758a91f1cBrett Chabot */
3447d431f63a66505a645f282416659a9758a91f1cBrett Chabotpublic final class EasyMockProperties {
3547d431f63a66505a645f282416659a9758a91f1cBrett Chabot
3647d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private static final String PREFIX = "easymock.";
3747d431f63a66505a645f282416659a9758a91f1cBrett Chabot
3847d431f63a66505a645f282416659a9758a91f1cBrett Chabot    // volatile for double-checked locking
3947d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private static volatile EasyMockProperties instance;
4047d431f63a66505a645f282416659a9758a91f1cBrett Chabot
4147d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private final Properties properties = new Properties();
4247d431f63a66505a645f282416659a9758a91f1cBrett Chabot
4347d431f63a66505a645f282416659a9758a91f1cBrett Chabot    public static EasyMockProperties getInstance() {
4447d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (instance == null) {
4547d431f63a66505a645f282416659a9758a91f1cBrett Chabot            synchronized (EasyMockProperties.class) {
4647d431f63a66505a645f282416659a9758a91f1cBrett Chabot                // ///CLOVER:OFF
4747d431f63a66505a645f282416659a9758a91f1cBrett Chabot                if (instance == null) {
4847d431f63a66505a645f282416659a9758a91f1cBrett Chabot                    // ///CLOVER:ON
4947d431f63a66505a645f282416659a9758a91f1cBrett Chabot                    instance = new EasyMockProperties();
5047d431f63a66505a645f282416659a9758a91f1cBrett Chabot                }
5147d431f63a66505a645f282416659a9758a91f1cBrett Chabot            }
5247d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
5347d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return instance;
5447d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
5547d431f63a66505a645f282416659a9758a91f1cBrett Chabot
5647d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private EasyMockProperties() {
5747d431f63a66505a645f282416659a9758a91f1cBrett Chabot        // Load the easymock.properties file
5847d431f63a66505a645f282416659a9758a91f1cBrett Chabot        InputStream in = getClassLoader().getResourceAsStream(
5947d431f63a66505a645f282416659a9758a91f1cBrett Chabot                "easymock.properties");
6047d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (in != null) {
6147d431f63a66505a645f282416659a9758a91f1cBrett Chabot            in = new BufferedInputStream(in);
6247d431f63a66505a645f282416659a9758a91f1cBrett Chabot            try {
6347d431f63a66505a645f282416659a9758a91f1cBrett Chabot                properties.load(in);
6447d431f63a66505a645f282416659a9758a91f1cBrett Chabot            } catch (IOException e) {
6547d431f63a66505a645f282416659a9758a91f1cBrett Chabot                throw new RuntimeException(
6647d431f63a66505a645f282416659a9758a91f1cBrett Chabot                        "Failed to read easymock.properties file");
6747d431f63a66505a645f282416659a9758a91f1cBrett Chabot            } finally {
6847d431f63a66505a645f282416659a9758a91f1cBrett Chabot                try {
6947d431f63a66505a645f282416659a9758a91f1cBrett Chabot                    in.close();
7047d431f63a66505a645f282416659a9758a91f1cBrett Chabot                } catch (IOException e) {
7147d431f63a66505a645f282416659a9758a91f1cBrett Chabot                    // Doesn't matter
7247d431f63a66505a645f282416659a9758a91f1cBrett Chabot                }
7347d431f63a66505a645f282416659a9758a91f1cBrett Chabot            }
7447d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
7547d431f63a66505a645f282416659a9758a91f1cBrett Chabot        // Then overload it with system properties
7647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        for (Map.Entry<Object, Object> entry : System.getProperties()
7747d431f63a66505a645f282416659a9758a91f1cBrett Chabot                .entrySet()) {
7847d431f63a66505a645f282416659a9758a91f1cBrett Chabot            if (entry.getKey() instanceof String
7947d431f63a66505a645f282416659a9758a91f1cBrett Chabot                    && entry.getKey().toString().startsWith(PREFIX)) {
8047d431f63a66505a645f282416659a9758a91f1cBrett Chabot                properties.put(entry.getKey(), entry.getValue());
8147d431f63a66505a645f282416659a9758a91f1cBrett Chabot            }
8247d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
8347d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
8447d431f63a66505a645f282416659a9758a91f1cBrett Chabot
8547d431f63a66505a645f282416659a9758a91f1cBrett Chabot    /**
8647d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * Searches for the property with the specified key. If the key is not
8747d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * found, return the default value.
8847d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *
8947d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @param key
9047d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *            key leading to the property
9147d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @param defaultValue
9247d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *            the value to be returned if the key isn't found
9347d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @return the value found for the key or the default value
9447d431f63a66505a645f282416659a9758a91f1cBrett Chabot     */
9547d431f63a66505a645f282416659a9758a91f1cBrett Chabot    public String getProperty(String key, String defaultValue) {
9647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return properties.getProperty(key, defaultValue);
9747d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
9847d431f63a66505a645f282416659a9758a91f1cBrett Chabot
9947d431f63a66505a645f282416659a9758a91f1cBrett Chabot    /**
10047d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * Searches for the property with the specified key. Return null if the key
10147d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * is not found.
10247d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *
10347d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @param key
10447d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *            key leading to the property
10547d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @return the value found for the key or null
10647d431f63a66505a645f282416659a9758a91f1cBrett Chabot     */
10747d431f63a66505a645f282416659a9758a91f1cBrett Chabot    public String getProperty(String key) {
10847d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return properties.getProperty(key);
10947d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
11047d431f63a66505a645f282416659a9758a91f1cBrett Chabot
11147d431f63a66505a645f282416659a9758a91f1cBrett Chabot    /**
11247d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * Add a value referenced by the provided key. A null value will remove the
11347d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * key
11447d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *
11547d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @param key
11647d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *            the key of the new property
11747d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @param value
11847d431f63a66505a645f282416659a9758a91f1cBrett Chabot     *            the value corresponding to <tt>key</tt>.
11947d431f63a66505a645f282416659a9758a91f1cBrett Chabot     * @return the property previous value
12047d431f63a66505a645f282416659a9758a91f1cBrett Chabot     */
12147d431f63a66505a645f282416659a9758a91f1cBrett Chabot    public String setProperty(String key, String value) {
12247d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (!key.startsWith(PREFIX)) {
12347d431f63a66505a645f282416659a9758a91f1cBrett Chabot            throw new IllegalArgumentException("Invalid key (" + key
12447d431f63a66505a645f282416659a9758a91f1cBrett Chabot                    + "), an easymock property starts with \"" + PREFIX + "\"");
12547d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
12647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (value == null) {
12747d431f63a66505a645f282416659a9758a91f1cBrett Chabot            return (String) properties.remove(key);
12847d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
12947d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return (String) properties.setProperty(key, value);
13047d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
13147d431f63a66505a645f282416659a9758a91f1cBrett Chabot
13247d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private ClassLoader getClassLoader() {
13347d431f63a66505a645f282416659a9758a91f1cBrett Chabot        ClassLoader cl = null;
13447d431f63a66505a645f282416659a9758a91f1cBrett Chabot        try {
13547d431f63a66505a645f282416659a9758a91f1cBrett Chabot            cl = Thread.currentThread().getContextClassLoader();
13647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        } catch (Throwable ex) {
13747d431f63a66505a645f282416659a9758a91f1cBrett Chabot            // Cannot access thread context ClassLoader - falling back to system
13847d431f63a66505a645f282416659a9758a91f1cBrett Chabot            // class loader
13947d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
14047d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (cl == null) {
14147d431f63a66505a645f282416659a9758a91f1cBrett Chabot            // No thread context class loader -> use class loader of this class.
14247d431f63a66505a645f282416659a9758a91f1cBrett Chabot            cl = getClass().getClassLoader();
14347d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
14447d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return cl;
14547d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
14647d431f63a66505a645f282416659a9758a91f1cBrett Chabot}
147