View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.api.config.app;
17  
18  import static de.smartics.properties.api.config.domain.TypeProblemMessageBean.instantiationFailed;
19  import static de.smartics.properties.api.config.domain.TypeProblemMessageBean.noImplementationFound;
20  import de.smartics.properties.core.services.AbstractJndiBackedServiceFactory;
21  import de.smartics.properties.resource.domain.ResourceException;
22  import de.smartics.util.lang.Arg;
23  
24  /**
25   * Creates instances of the {@link ConfigurationPropertiesFactory}.
26   * <p>
27   * Instances of {@link ConfigurationPropertiesFactory} create selected
28   * implementations of the
29   * {@link de.smartics.properties.api.config.domain.ConfigurationProperties}
30   * interface. This static factory of factories allows to create the factories.
31   * </p>
32   * <p>
33   * Factories can be created in two ways:
34   * </p>
35   * <ol>
36   * <li>Use {@link #createDefaultFactory()} if the name of the factory is
37   * supplied by <code>META-INF/services</code></li>
38   * <li>Use {@link #createFactory(Class)} or {@link #createFactory(String)} if
39   * the name is determined by the client code at runtime.</li>
40   * </ol>
41   * {@stickyNote Usually the second way (especially if a class is supplied) is
42   * not really necessary since the constructor can be called by the client code
43   * with the same effect. But using this factory of factories may be more
44   * convenient.}
45   */
46  public final class ConfigurationPropertiesFactoryFactory extends
47      AbstractJndiBackedServiceFactory<ConfigurationPropertiesFactory>
48  {
49    // ********************************* Fields *********************************
50  
51    // --- constants ------------------------------------------------------------
52  
53    /**
54     * The singleton.
55     */
56    public static final ConfigurationPropertiesFactoryFactory INSTANCE =
57        new ConfigurationPropertiesFactoryFactory();
58  
59    // --- members --------------------------------------------------------------
60  
61    // ****************************** Initializer *******************************
62  
63    // ****************************** Constructors ******************************
64  
65    /**
66     * Default constructor.
67     */
68    private ConfigurationPropertiesFactoryFactory()
69    {
70      super(ConfigurationPropertiesFactory.class);
71    }
72  
73    // ****************************** Inner Classes *****************************
74  
75    // ********************************* Methods ********************************
76  
77    // --- init -----------------------------------------------------------------
78  
79    // --- get&set --------------------------------------------------------------
80  
81    // --- business -------------------------------------------------------------
82  
83    /**
84     * Creates the default factory found on the class path. The factory class is
85     * registered in
86     * <code>META-INF/services/de.smartics.properties.api.config.app.ConfigurationPropertiesFactory</code>
87     * .
88     * <p>
89     * Issues a warning if more than one implementation is found. Returns an
90     * instance of the first implementation found.
91     * </p>
92     *
93     * @return the instance of the default factory. Never <code>null</code>.
94     * @throws ConfigurationFactoryException if no factory can be created.
95     */
96    public static ConfigurationPropertiesFactory createDefaultFactory()
97      throws ConfigurationFactoryException
98    {
99      try
100     {
101       try
102       {
103         @SuppressWarnings("rawtypes")
104         final Class defaultImpl =
105             ConfigurationPropertiesFactoryFactory.class
106                 .getClassLoader()
107                 .loadClass(
108                     "de.smartics.properties.impl.config.properties.PropertiesConfigurationPropertiesFactory");
109         @SuppressWarnings("unchecked")
110         final ConfigurationPropertiesFactory factory =
111             INSTANCE.create(defaultImpl);
112         return factory;
113 
114       }
115       catch (final ClassNotFoundException e)
116       {
117         // OK Do nothing
118       }
119       final ConfigurationPropertiesFactory factory = INSTANCE.create();
120       return factory;
121     }
122     catch (final ResourceException e)
123     {
124       throw new ConfigurationFactoryException(noImplementationFound(e,
125           ConfigurationPropertiesFactory.class));
126     }
127   }
128 
129   /**
130    * Creates a factory of the given type.
131    *
132    * @param factoryType the type of the factory to create.
133    * @return the created instance. Never <code>null</code>.
134    * @throws NullPointerException if {@code factoryType} is <code>null</code>.
135    * @throws ConfigurationFactoryException on any problem creating the requested
136    *           factory instance.
137    * @param <T> the type of the factory.
138    */
139   public static <T extends ConfigurationPropertiesFactory> T createFactory(
140       final Class<T> factoryType) throws NullPointerException,
141     ConfigurationFactoryException
142   {
143     Arg.checkNotNull("factoryType", factoryType);
144 
145     try
146     {
147       return factoryType.newInstance();
148     }
149     catch (final Exception e)
150     {
151       throw new ConfigurationFactoryException(instantiationFailed(e,
152           factoryType));
153     }
154   }
155 
156   /**
157    * Creates a factory for the given type name.
158    *
159    * @param factoryTypeName the fully qualified name of a type that implements
160    *          {@link de.smartics.properties.api.config.domain.ConfigurationProperties}
161    *          .
162    * @return the created instance. Never <code>null</code>.
163    * @throws NullPointerException if {@code factoryTypeName} is
164    *           <code>null</code>.
165    * @throws ConfigurationFactoryException on any problem creating the requested
166    *           factory instance.
167    */
168   @SuppressWarnings("unchecked")
169   public static ConfigurationPropertiesFactory createFactory(
170       final String factoryTypeName) throws NullPointerException,
171     ConfigurationFactoryException
172   {
173     Arg.checkNotNull("factoryTypeName", factoryTypeName);
174 
175     try
176     {
177       final Class<? extends ConfigurationPropertiesFactory> factoryType =
178           (Class<? extends ConfigurationPropertiesFactory>) Class
179               .forName(factoryTypeName);
180       return createFactory(factoryType);
181     }
182     catch (final ClassNotFoundException e)
183     {
184       throw new ConfigurationFactoryException(instantiationFailed(e,
185           factoryTypeName));
186     }
187   }
188 
189   // --- object basics --------------------------------------------------------
190 
191 }