001 package org.apache.ojb.broker.util.factory;
002
003 /* Copyright 2002-2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 import org.apache.commons.lang.SystemUtils;
019 import org.apache.ojb.broker.PersistenceBrokerException;
020 import org.apache.ojb.broker.util.ClassHelper;
021 import org.apache.ojb.broker.util.configuration.Configurable;
022 import org.apache.ojb.broker.util.configuration.Configuration;
023 import org.apache.ojb.broker.util.configuration.ConfigurationException;
024 import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
025 import org.apache.ojb.broker.util.interceptor.InterceptorFactory;
026 import org.apache.ojb.broker.util.logging.Logger;
027 import org.apache.ojb.broker.util.logging.LoggerFactory;
028
029 /**
030 * ConfigurableFactory is an abstract baseclass for OJB factory classes.
031 * It provides all infrastructure for configuration through OJB.properties.
032 * A derived class must implement the getConfigurationKey() method.
033 * The returned configuration key is used to lookup the class to be instantiated
034 * by the derived factory.
035 * The lookup is performed in the configure() method and uses the OJB.properties
036 * information.
037 *
038 * @author Thomas Mahler
039 */
040 public abstract class ConfigurableFactory implements Configurable
041 {
042 private Logger log = LoggerFactory.getLogger(this.getClass());
043
044 /**
045 * the class to be served
046 */
047 private Class classToServe = null;
048
049
050 /**
051 * the public constructor calls configure() to perform configuration
052 * of the factory instance.
053 */
054 public ConfigurableFactory()
055 {
056 OjbConfigurator.getInstance().configure(this);
057 }
058
059 /**
060 * must be implemented in the concrete factory classes.
061 * the configuration key is used to lookup the Class to serve
062 * from the OjbConfiguration in configure().
063 */
064 protected abstract String getConfigurationKey();
065
066 /**
067 * @see org.apache.ojb.broker.util.configuration.Configurable#configure(Configuration)
068 * looks up the the key getConfigurationKey() in the OjbConfiguration
069 * to determine the Class to be served.
070 */
071 public void configure(Configuration pConfig) throws ConfigurationException
072 {
073 if (getConfigurationKey() == null)
074 {
075 getLogger().error("ConfigurableFactory configuration key is 'null'");
076 throw new PersistenceBrokerException("ConfigurableFactory configuration key is 'null'");
077 }
078 Class clazz = pConfig.getClass(getConfigurationKey(), null);
079 if (clazz == null)
080 {
081 getLogger().error("ConfigurableFactory configuration key class for key'" + getConfigurationKey() + "' does not exist.");
082 throw new PersistenceBrokerException(
083 "ConfigurableFactory configuration key class for key'" + getConfigurationKey() + "' does not exist.");
084 }
085 this.setClassToServe(clazz);
086 }
087
088 /**
089 * factory method for creating new instances
090 * the Class to be instantiated is defined by getClassToServe().
091 * @return Object the created instance
092 */
093 public Object createNewInstance(Class[] types, Object[] args)
094 {
095 try
096 {
097 Object result;
098 // create an instance of the target class
099 if (types != null)
100 {
101 result = ClassHelper.newInstance(getClassToServe(), types, args, true);
102 }
103 else
104 {
105 result = ClassHelper.newInstance(getClassToServe(), true);
106 }
107 // if defined in OJB.properties all instances are wrapped by an interceptor
108 result = InterceptorFactory.getInstance().createInterceptorFor(result);
109 return result;
110
111 }
112 catch (InstantiationException e)
113 {
114 getLogger().error("ConfigurableFactory can't instantiate class " +
115 getClassToServe() + buildArgumentString(types, args), e);
116 throw new PersistenceBrokerException(e);
117 }
118 catch (IllegalAccessException e)
119 {
120 getLogger().error("ConfigurableFactory can't access constructor for class " +
121 getClassToServe() + buildArgumentString(types, args), e);
122 throw new PersistenceBrokerException(e);
123 }
124 catch (Exception e)
125 {
126 getLogger().error("ConfigurableFactory instantiation failed for class " +
127 getClassToServe() + buildArgumentString(types, args), e);
128 throw new PersistenceBrokerException(e);
129 }
130 }
131
132 protected String buildArgumentString(Class[] types, Object[] args)
133 {
134 StringBuffer buf = new StringBuffer();
135 String eol = SystemUtils.LINE_SEPARATOR;
136 buf.append(eol + "* Factory types: ");
137 if (types != null)
138 {
139 for (int i = 0; i < types.length; i++)
140 {
141 Class type = types[i];
142 buf.append(eol + (i + 1) + " - Type: " + (type != null ? type.getName() : null));
143 }
144 }
145 else
146 buf.append(eol + "none");
147
148 buf.append(eol + "* Factory arguments: ");
149 if (args != null)
150 {
151 for (int i = 0; i < args.length; i++)
152 {
153 Object obj = args[i];
154 buf.append(eol + (i + 1) + " - Argument: " + obj);
155 }
156 }
157 else
158 buf.append(eol + "none");
159 return buf.toString();
160 }
161
162 /**
163 * factory method for creating new instances
164 * the Class to be instantiated is defined by getClassToServe().
165 * @return Object the created instance
166 */
167 public Object createNewInstance()
168 {
169 return createNewInstance((Class) null, (Object) null);
170 }
171
172
173 /**
174 * factory method for creating new instances
175 * the Class to be instantiated is defined by getClassToServe().
176 * @return Object the created instance
177 */
178 public Object createNewInstance(Class type, Object arg)
179 {
180 if (type != null)
181 return createNewInstance(new Class[]{type}, new Object[]{arg});
182 else
183 return createNewInstance((Class[]) null, (Object[]) null);
184 }
185
186 /**
187 * Returns the classToServe.
188 * @return Class
189 */
190 public Class getClassToServe()
191 {
192 return classToServe;
193 }
194
195 /**
196 * Sets the classToServe.
197 * <br/>
198 * Normally this is done by the factory using
199 * {@link #getConfigurationKey}.
200 * <br/>
201 * <b>Note:</b> For internal use only!
202 * @param classToServe The classToServe to set
203 */
204 public void setClassToServe(Class classToServe)
205 {
206 this.classToServe = classToServe;
207 }
208
209 /**
210 * the logger for the ConfigurableFactory
211 */
212 protected Logger getLogger()
213 {
214 return log;
215 }
216 }