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 }