/* * Copyright 2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.impl.bean.spring; import org.rioproject.impl.bean.BeanFactory; import org.rioproject.impl.servicebean.DefaultServiceBeanManager; import org.rioproject.servicebean.ServiceBeanContext; import org.rioproject.servicebean.ServiceBeanManager; import org.rioproject.deploy.ServiceBeanInstantiationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; /** * Instantiates a Plain Old Java Object (POJO) using Spring, providing support * for remote invocations and administration by adapting the POJO into the * framework using the Spring framework. * * @see org.rioproject.servicebean.ServiceBeanFactory * @see org.rioproject.impl.bean.BeanFactory * * @author Dennis Reedy */ @SuppressWarnings("unused") public class SpringBeanFactory extends BeanFactory { /** Codebase token to be replaced by the service's actual token */ static final String CODEBASE_TOK = "$codebase"; /** Codebase token to be replaced by the service's actual token */ static final String CLASSPATH_TOK = "$classpath"; private boolean useCodebase; /** A Logger */ static final Logger logger = LoggerFactory.getLogger(SpringBeanFactory.class); /** * Get the bean object */ protected Object getBean(ServiceBeanContext context) throws Exception { String[] configs = (String[])context.getConfiguration().getEntry("spring", "config", String[].class, new String[]{""}); if(configs.length==0) { throw new ServiceBeanInstantiationException("No Spring service configuration"); } String codebase = context.getServiceElement().getExportBundles()[0].getCodebase(); for(int i=0; i<configs.length; i++) { if(configs[i].contains(CODEBASE_TOK + "/")) { configs[i] = replace(configs[i], CODEBASE_TOK+"/", codebase); useCodebase = true; logger.debug("Loading application context [{}]", configs[i]); } else if (configs[i].contains(CLASSPATH_TOK + "/")) { configs[i] = replace(configs[i], CLASSPATH_TOK+"/", codebase); logger.debug("Loading application context [{}]", configs[i]); } else { configs[i] = replace(configs[i], CODEBASE_TOK, codebase); logger.debug("Loading application context [{}]", configs[i]); } } final Thread currentThread = Thread.currentThread(); ClassLoader cCL = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { public ClassLoader run() { return (currentThread.getContextClassLoader()); } }); /* * Reflection is used here because Spring technology classes may be * loaded by a child classloader of the the classloader which loaded * this class. If this is the case then we will be facing * NoClassDefFoundError exceptions. */ /* GenericApplicationContext ctx = new GenericApplicationContext(); ctx.setClassLoader(cCL); */ Class<?> ctxClass = Class.forName( "org.springframework.context.support.GenericApplicationContext", true, cCL); Object ctx = ctxClass.newInstance(); Method ctx_setClassLoader = ctxClass.getMethod("setClassLoader", ClassLoader.class); ctx_setClassLoader.invoke(ctx, cCL); //XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx); Class xmlReaderClass = Class.forName( "org.springframework.beans.factory.xml.XmlBeanDefinitionReader", true, cCL); Constructor[] cons = xmlReaderClass.getConstructors(); Object xmlReader = null; for (Constructor con : cons) { Class[] types = con.getParameterTypes(); if (types.length == 1 && types[0].getName().contains("BeanDefinitionRegistry")) { xmlReader = con.newInstance(ctx); break; } } Method[] methods = xmlReaderClass.getMethods(); Method xmlReader_loadBeanDefinitions = null; for (Method method : methods) { if (method.getName().equals("loadBeanDefinitions")) { Class[] types = method.getParameterTypes(); for (Class type : types) { if (type.getName().equals("org.springframework.core.io.Resource")) { xmlReader_loadBeanDefinitions = method; break; } } if (xmlReader_loadBeanDefinitions != null) break; } } String resourceClassName; if(useCodebase) { resourceClassName = "org.springframework.core.io.UrlResource"; } else { resourceClassName = "org.springframework.core.io.ClassPathResource"; } Class<?> resourceClass = Class.forName(resourceClassName, true, cCL); Constructor resourceCons = resourceClass.getConstructor(String.class); for (String config : configs) { Object resource = resourceCons.newInstance(config); assert xmlReader_loadBeanDefinitions != null; xmlReader_loadBeanDefinitions.invoke(xmlReader, resource); } /* for(int i=0; i<configs.length; i++) { xmlReader.loadBeanDefinitions(new UrlResource(configs[i])); } ctx.refresh(); */ Method ctx_refresh = ctxClass.getMethod("refresh", (Class[])null); ctx_refresh.invoke(ctx, (Object[])null); ServiceBeanManager mgr = context.getServiceBeanManager(); if(mgr instanceof DefaultServiceBeanManager) { SpringDiscardManager sdm = new SpringDiscardManager(ctx, context.getServiceBeanManager().getDiscardManager()); ((DefaultServiceBeanManager)mgr).setDiscardManager(sdm); } else { logger.warn("Unable to set Spring DiscardManager, unrecognized ServiceBeanManager"); } String beanName = context.getServiceElement().getName(); Method ctx_getBean = ctxClass.getMethod("getBean", String.class); Object bean = ctx_getBean.invoke(ctx, beanName); return(bean); //return(ctx.getBean(context.getServiceElement().getName())); } /* * Regular Expression Search and Replace */ String replace(String str, String pattern, String replace) { int s = 0; int e; StringBuilder result = new StringBuilder(); while((e = str.indexOf(pattern, s)) >= 0) { result.append(str.substring(s, e)); result.append(replace); s = e+pattern.length(); } result.append(str.substring(s)); return result.toString(); } }