View Javadoc
1 package org.jadetower.dao.impl; 2 3 /* 4 Copyright (c) 2003, J Aaron Farr 5 All rights reserved. 6 7 This software is published under the terms of the JadeTower Software License, 8 a BSD derived license, a copy of which has been included with this 9 distribution in the LICENSE file. <http://www.jadetower.org> 10 */ 11 12 13 import org.jadetower.dao.DaoManager; 14 import org.jadetower.dao.exception.DaoException; 15 import org.jadetower.resolver.Resolver; 16 import org.jadetower.resolver.ResolverUtils; 17 18 import org.apache.avalon.framework.container.ContainerUtil; 19 import org.apache.avalon.framework.configuration.Configurable; 20 import org.apache.avalon.framework.configuration.Configuration; 21 import org.apache.avalon.framework.configuration.ConfigurationException; 22 import org.apache.avalon.framework.parameters.Parameters; 23 import org.apache.avalon.framework.activity.Initializable; 24 import org.apache.avalon.framework.service.Serviceable; 25 import org.apache.avalon.framework.service.ServiceManager; 26 import org.apache.avalon.framework.service.ServiceException; 27 import org.apache.avalon.framework.logger.Logger; 28 import org.apache.avalon.framework.logger.AbstractLogEnabled; 29 import org.apache.avalon.framework.context.Contextualizable; 30 import org.apache.avalon.framework.context.Context; 31 import org.apache.avalon.framework.context.ContextException; 32 import org.apache.avalon.framework.context.DefaultContext; 33 34 import org.apache.commons.beanutils.BeanUtils; 35 36 import org.picocontainer.defaults.DefaultPicoContainer; 37 import org.picocontainer.defaults.DefaultComponentAdapterFactory; 38 import org.picocontainer.defaults.ConstantParameter; 39 import org.picocontainer.defaults.ComponentParameter; 40 import org.picocontainer.Parameter; 41 42 import java.util.HashMap; 43 import java.util.Set; 44 import java.util.Iterator; 45 import java.io.IOException; 46 import java.util.Map; 47 import java.lang.reflect.Constructor; 48 import java.util.ArrayList; 49 import bsh.Interpreter; 50 import bsh.EvalError; 51 52 53 /*** 54 * The Default DAO Manager. 55 * Handles Bean, Pico, and Avalon lifecycles. Uses a PicoContainer as the 56 * basic internal DAO container. 57 * 58 * Part of this class was taken from org.apache.excalibur.configuration.ContextFactory 59 * and is copyrighted by the Apache Software Foundation 60 * 61 * @avalon.component name="dao-manager" lifestyle="singleton" 62 * @avalon.service type="org.jadetower.dao.DaoManager" 63 */ 64 public class DefaultDaoManager 65 extends AbstractLogEnabled 66 implements DaoManager, Configurable, Initializable, Serviceable, Contextualizable 67 { 68 69 private DefaultPicoContainer m_lookup = null; 70 private DefaultComponentAdapterFactory m_factory = null; 71 private Resolver m_resolver = null; 72 private DaoServiceManager m_manager = null; 73 private Map m_context = new HashMap(); 74 private Context m_parent = null; 75 private HashMap m_configurations = new HashMap(); 76 77 public DefaultDaoManager(){ 78 } 79 80 public DefaultDaoManager(Resolver resolver, Logger logger, Configuration config, Map context) throws InstantiationException { 81 m_resolver = resolver; 82 m_factory = new DefaultComponentAdapterFactory(); 83 m_lookup = new DefaultPicoContainer( m_factory ); 84 m_manager = new DaoServiceManager(null,m_lookup); 85 m_parent = new DefaultContext(context); 86 enableLogging(logger); 87 try { 88 configure(config); 89 initialize(); 90 } 91 catch (Exception ex) { 92 throw new InstantiationException(ex.getMessage()); 93 } 94 } 95 96 public Object getDao(String name) throws DaoException 97 { 98 if(getLogger().isDebugEnabled()) 99 getLogger().debug("getting dao: "+name); 100 return m_lookup.getComponentInstance(name); 101 } 102 103 public void release(Object object){ 104 /*** @todo work out release code */ 105 } 106 107 public void contextualize(Context context) { 108 if(m_parent == null) 109 m_parent = context; 110 } 111 112 /*** 113 * @avalon.dependency type="org.jadetower.resolver.Resolver" 114 */ 115 public void service(ServiceManager serviceManager) throws ServiceException { 116 if(m_factory == null) 117 m_factory = new DefaultComponentAdapterFactory(); 118 119 if(m_lookup == null) 120 m_lookup = new DefaultPicoContainer(m_factory); 121 122 if(m_manager == null) 123 m_manager = new DaoServiceManager(serviceManager,m_lookup); 124 125 if(m_resolver == null) 126 m_resolver = (Resolver) m_manager.lookup(Resolver.ROLE); 127 128 } 129 130 public void configure(Configuration configuration) throws ConfigurationException 131 { 132 m_context = createContextFromConfiguration(m_parent, configuration.getChild("context",true), getLogger()); 133 Configuration d = configuration.getChild("daos",true); 134 Configuration[] daos = d.getChildren("dao"); 135 for (int i = 0; i < daos.length; i++) { 136 String name = null; 137 try { 138 Configuration dao = daos[i]; 139 name = dao.getAttribute("name", null); 140 String uri = dao.getAttribute("uri", null); 141 Object object = m_resolver.resolve(uri); 142 registerDAO(name, object); 143 m_configurations.put(name, dao); 144 } 145 catch (Exception ex) { 146 getLogger().error("Error configuring "+name,ex); 147 } 148 } 149 } 150 151 public void initialize() throws Exception { 152 Object proxy = m_lookup.getComponentMulticaster(); 153 handleProxyLifecycle(proxy); 154 ArrayList keys = new ArrayList(m_lookup.getComponentKeys()); 155 for(int i=0; i < keys.size(); i++){ 156 String name = (String) keys.get(i); 157 Object component = m_lookup.getComponentInstance(name); 158 handleInstanceLifecycle(name,component); 159 } 160 161 handleStartup(proxy); 162 if(getLogger().isDebugEnabled()){ 163 getLogger().debug("dao-manager successfully initialized"); 164 } 165 } 166 167 protected void registerDAO(String name, Object dao) throws Exception { 168 if(dao instanceof Class){ 169 Class daoClazz = (Class) dao; 170 171 // first get the largest constructor 172 Constructor[] cons = daoClazz.getConstructors(); 173 Constructor c = null; 174 int maxParameters = 0; 175 for(int i=0; i < cons.length; i++){ 176 if(cons[i].getParameterTypes().length >= maxParameters){ 177 maxParameters = cons[i].getParameterTypes().length; 178 c = cons[i]; 179 } 180 } 181 Class[] classes = c.getParameterTypes(); 182 Parameter[] params = new Parameter[classes.length]; 183 for (int j = 0; j < params.length; j++) { 184 if (classes[j].isAssignableFrom(Map.class)) { 185 params[j] = new ConstantParameter(m_context); 186 } 187 else { 188 params[j] = new ComponentParameter(classes[j]); 189 } 190 } 191 192 m_lookup.registerComponentImplementation(name,daoClazz,params); 193 194 } 195 else{ 196 m_lookup.registerComponentInstance(name,dao); 197 } 198 if(getLogger().isDebugEnabled()) 199 getLogger().debug("registered DAO: "+name); 200 } 201 202 protected void handleProxyLifecycle(Object dao) throws Exception { 203 ContainerUtil.enableLogging(dao,getLogger()); 204 ContainerUtil.contextualize(dao, new DefaultContext(m_context)); 205 ContainerUtil.service(dao,m_manager); 206 } 207 208 protected void handleInstanceLifecycle(String name, Object dao) throws Exception { 209 Configuration conf = (Configuration) m_configurations.get(name); 210 ContainerUtil.configure(dao,conf); 211 ContainerUtil.parameterize(dao,Parameters.fromConfiguration(conf)); 212 BeanUtils.populate(dao,m_context); 213 } 214 215 protected void handleStartup(Object proxy) throws Exception { 216 ContainerUtil.initialize(proxy); 217 ContainerUtil.start(proxy); 218 } 219 220 /*** 221 * Create context-attributes from entrys within <context/>-tag in config 222 * (Copyright ASF). Modified to handle URI's instead of types. 223 * @param parent the parent context 224 * @param config the configuration element describing the context parameters 225 * @param log a logging channel 226 * @return Context a context instance 227 * @exception ConfigurationException if a context related error occurs 228 */ 229 protected Map createContextFromConfiguration( 230 Context parent, Configuration config, Logger log ) 231 throws ConfigurationException 232 { 233 234 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 235 HashMap map = new HashMap(); 236 237 Configuration[] scripts = config.getChildren("script"); 238 Interpreter shell = new Interpreter(); 239 for (int i = 0; i < scripts.length; i++) { 240 try { 241 Configuration script = scripts[i]; 242 String scriptFile = script.getAttribute("file", null); 243 Object result = null; 244 if (scriptFile != null) { 245 result = shell.source(scriptFile); 246 } 247 else { 248 String bshScript = script.getValue(null); 249 if (bshScript != null) { 250 result = shell.eval(bshScript); 251 } 252 } 253 if (result != null && result instanceof Map) { 254 map.putAll( (Map) result); 255 } 256 } 257 catch (EvalError ex) { 258 if(getLogger().isErrorEnabled()) 259 getLogger().error("Error during context script evaluation",ex); 260 } 261 catch (IOException ex) { 262 if(getLogger().isErrorEnabled()) 263 getLogger().error("Error reading context script",ex); 264 } 265 } 266 267 final Configuration[] entrys = config.getChildren("entry"); 268 269 for (int i = 0; i < entrys.length; i++) { 270 Configuration c = entrys[i]; 271 final String paramName = entrys[i].getAttribute( 272 "name", null); 273 final String uri = entrys[i].getAttribute("uri", 274 "class://java.lang.String"); 275 276 if (paramName == null) { 277 throw new ConfigurationException( 278 "missing name for context-entry"); 279 } 280 try { 281 282 if (ResolverUtils.getScheme(uri).equalsIgnoreCase("parent")) { 283 String name = ResolverUtils.getPath(uri); 284 map.put(name, m_parent.get(name)); 285 286 } 287 else { 288 289 Object object = m_resolver.resolve(uri); 290 291 if (object instanceof Class) { 292 final String className = ResolverUtils.getPath(uri); 293 294 Class[] params; 295 Object[] values; 296 Configuration entry = entrys[i]; 297 298 if (entry.getAttribute("value", null) != null) { 299 // Single argument String-constructor 300 params = new Class[1]; 301 params[0] = Class.forName("java.lang.String"); 302 Class[] consObjects = { 303 Class.forName("java.lang.String")}; 304 Constructor cons = params[0].getConstructor(consObjects); 305 values = new Object[1]; 306 Object[] consValues = { 307 getContextValue(map, entry.getAttribute("value")) 308 }; 309 values[0] = cons.newInstance(consValues); 310 311 if (log != null) { 312 log.debug("add context-attr '" + paramName 313 + "' class '" + className 314 + "' with value '" + consValues[0] + "'"); 315 } 316 } 317 else { 318 // Multiple argument constructor 319 Configuration[] entryChilds = entry.getChildren("parameter"); 320 321 params = new Class[entryChilds.length]; 322 values = new Object[entryChilds.length]; 323 324 if (log != null) { 325 log.debug("add context-attr '" + paramName 326 + "' class '" + className + "' with " 327 + entryChilds.length + " values"); 328 } 329 330 for (int p = 0; p < entryChilds.length; p++) { 331 String paramClassName = entryChilds[p].getAttribute( 332 "type", "java.lang.String"); 333 String paramValue = entryChilds[p].getAttribute("value", null); 334 335 if (paramValue == null) { 336 if (log != null) { 337 log.debug("value" + (p + 1) + ": class '" 338 + paramClassName + "' no value"); 339 } 340 } 341 else { 342 paramValue = getContextValue(map, paramValue); 343 if (log != null) { 344 log.debug("value" + (p + 1) + ": class '" 345 + paramClassName + "' value '" + paramValue + "'"); 346 } 347 } 348 349 try { 350 params[p] = loader.loadClass(paramClassName); 351 352 if (paramValue == null) { 353 values[p] = params[p].newInstance(); 354 } 355 else { 356 Class[] consObjects = { 357 Class.forName("java.lang.String")}; 358 Constructor cons = params[p].getConstructor(consObjects); 359 Object[] consValues = { 360 paramValue}; 361 values[p] = cons.newInstance(consValues); 362 } 363 } 364 catch (ClassNotFoundException e) { 365 // Class not found 366 // -> perhaps a primitve class? 367 if (paramClassName.equals("int")) { 368 params[p] = int.class; 369 values[p] = new Integer(paramValue); 370 } 371 else if (paramClassName.equals("short")) { 372 params[p] = short.class; 373 values[p] = new Short(paramValue); 374 } 375 else if (paramClassName.equals("long")) { 376 params[p] = long.class; 377 values[p] = new Long(paramValue); 378 } 379 else if (paramClassName.equals("byte")) { 380 params[p] = byte.class; 381 values[p] = new Byte(paramValue); 382 } 383 else if (paramClassName.equals("double")) { 384 params[p] = double.class; 385 values[p] = new Double(paramValue); 386 } 387 else if (paramClassName.equals("float")) { 388 params[p] = float.class; 389 values[p] = new Float(paramValue); 390 } 391 else if (paramClassName.equals("char")) { 392 params[p] = char.class; 393 values[p] = new Character(paramValue.charAt(0)); 394 } 395 else if (paramClassName.equals("boolean")) { 396 params[p] = boolean.class; 397 values[p] = new Boolean(paramValue); 398 } 399 else { 400 throw new ConfigurationException( 401 "incorrect type '" + paramClassName 402 + "' for context-attribute '" + paramName + "'", e); 403 } 404 } 405 } 406 } 407 408 Class paramClass; 409 try { 410 paramClass = loader.loadClass(className); 411 } 412 catch (final ClassNotFoundException e) { 413 throw new ConfigurationException( 414 "incorrect type '" + className 415 + "' for context-attribute '" + paramName + "'", 416 e); 417 } 418 419 Object paramInstance; 420 421 if (params.length > 0) { 422 // using param contructor 423 Constructor cons = paramClass.getConstructor(params); 424 paramInstance = cons.newInstance(values); 425 } 426 else { 427 // using default constructor 428 paramInstance = paramClass.newInstance(); 429 } 430 431 map.put(paramName, paramInstance); 432 } 433 else { 434 map.put(paramName, object); 435 } 436 } 437 } 438 catch (ConfigurationException e) { 439 throw e; 440 } 441 catch (Exception e) { 442 throw new ConfigurationException( 443 "Error add context-attribute '" + paramName 444 + "' from Configuration", e); 445 } 446 } 447 448 return map; 449 } 450 451 /*** 452 * Resolving an attribute value by replacing ${context-param} with 453 * the corresponding param out of current context. 454 * (Copyright AFS) 455 * @param map a map 456 * @param rawValue a raw value 457 * @return String the context attribute value 458 * @exception ConfigurationException if context-param does not exists 459 */ 460 private static String getContextValue( Map map, String rawValue ) 461 throws ConfigurationException 462 { 463 StringBuffer result = new StringBuffer( "" ); 464 int i = 0; 465 int j = -1; 466 while( ( j = rawValue.indexOf( "${", i ) ) > -1 ) 467 { 468 if( i < j ) 469 { 470 result.append( rawValue.substring( i, j ) ); 471 } 472 int k = rawValue.indexOf( '}', j ); 473 final String ctxName = rawValue.substring( j + 2, k ); 474 final Object ctx = map.get( ctxName ); 475 if( ctx == null ) 476 { 477 throw new ConfigurationException( 478 "missing entry '" + ctxName + "' in Context" ); 479 } 480 result.append( ctx.toString() ); 481 i = k + 1; 482 } 483 if( i < rawValue.length() ) 484 { 485 result.append( rawValue.substring( i, rawValue.length() ) ); 486 } 487 return result.toString(); 488 } 489 490 }

This page was automatically generated by Maven