1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockito.internal.configuration;
6
7import org.mockito.configuration.IMockitoConfiguration;
8import org.mockito.exceptions.misusing.MockitoConfigurationException;
9import org.mockito.plugins.MockMaker;
10
11
12/**
13 * Loads configuration or extension points available in the classpath.
14 *
15 * <p>
16 * <ul>
17 *     <li>
18 *         Can load the mockito configuration. The user who want to provide his own mockito configuration
19 *         should write the class <code>org.mockito.configuration.MockitoConfiguration</code> that implements
20 *         {@link IMockitoConfiguration}. For example :
21 *         <pre class="code"><code class="java">
22 * package org.mockito.configuration;
23 *
24 * //...
25 *
26 * public class MockitoConfiguration implements IMockitoConfiguration {
27 *     boolean enableClassCache() { return false; }
28 *
29 *     // ...
30 * }
31 *     </code></pre>
32 *     </li>
33 *     <li>
34 *         Can load available mockito extensions. Currently Mockito only have one extension point the
35 *         {@link MockMaker}. This extension point allows a user to provide his own bytecode engine to build mocks.
36 *         <br>Suppose you wrote an extension to create mocks with some <em>Awesome</em> library, in order to tell
37 *         Mockito to use it you need to put in your classpath
38 *         <ol style="list-style-type: lower-alpha">
39 *             <li>The implementation itself, for example <code>org.awesome.mockito.AwesomeMockMaker</code>.</li>
40 *             <li>A file named <code>org.mockito.plugins.MockMaker</code> in a folder named
41 *             <code>mockito-extensions</code>, the content of this file need to have <strong>one</strong> line with
42 *             the qualified name <code>org.awesome.mockito.AwesomeMockMaker</code>.</li>
43 *         </ol>
44 *     </li>
45 * </ul>
46 * </p>
47 */
48public class ClassPathLoader {
49
50    public static final String MOCKITO_CONFIGURATION_CLASS_NAME = "org.mockito.configuration.MockitoConfiguration";
51
52    /**
53     * @return configuration loaded from classpath or null
54     */
55    @SuppressWarnings({"unchecked"})
56    public IMockitoConfiguration loadConfiguration() {
57        // Trying to get config from classpath
58        Class<?> configClass;
59        try {
60            configClass = Class.forName(MOCKITO_CONFIGURATION_CLASS_NAME);
61        } catch (ClassNotFoundException e) {
62            //that's ok, it means there is no global config, using default one.
63            return null;
64        }
65
66        try {
67            return (IMockitoConfiguration) configClass.newInstance();
68        } catch (ClassCastException e) {
69            throw new MockitoConfigurationException("MockitoConfiguration class must implement " + IMockitoConfiguration.class.getName() + " interface.", e);
70        } catch (Exception e) {
71            throw new MockitoConfigurationException("Unable to instantiate " + MOCKITO_CONFIGURATION_CLASS_NAME +" class. Does it have a safe, no-arg constructor?", e);
72        }
73    }
74}
75