[Jboss-cvs] JBossAS SVN: r55498 - trunk/tomcat/src/main/org/jboss/web/tomcat/tc6
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu Aug 10 15:12:15 EDT 2006
Author: bill.burke at jboss.com
Date: 2006-08-10 15:12:14 -0400 (Thu, 10 Aug 2006)
New Revision: 55498
Added:
trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/TomcatInjectionContainer.java
trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/WarEjbResolver.java
Log:
implementation and some testing of injeciton annotations for WAR components
Added: trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/TomcatInjectionContainer.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/TomcatInjectionContainer.java 2006-08-10 19:11:32 UTC (rev 55497)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/TomcatInjectionContainer.java 2006-08-10 19:12:14 UTC (rev 55498)
@@ -0,0 +1,526 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.web.tomcat.tc6;
+
+import org.jboss.deployment.DeploymentInfo;
+import org.jboss.ejb3.Container;
+import org.jboss.ejb3.DependencyPolicy;
+import org.jboss.ejb3.EAR;
+import org.jboss.ejb3.JmxDependencyPolicy;
+import org.jboss.ejb3.JmxEARImpl;
+import org.jboss.ejb3.enc.DeploymentPersistenceUnitResolver;
+import org.jboss.ejb3.entity.PersistenceUnitDeployment;
+import org.jboss.injection.EncInjector;
+import org.jboss.injection.InjectionContainer;
+import org.jboss.injection.Injector;
+import org.jboss.injection.InjectionHandler;
+import org.jboss.injection.EJBHandler;
+import org.jboss.injection.DependsHandler;
+import org.jboss.injection.JndiInjectHandler;
+import org.jboss.injection.PersistenceContextHandler;
+import org.jboss.injection.PersistenceUnitHandler;
+import org.jboss.injection.ResourceHandler;
+import org.jboss.injection.WebServiceHandler;
+import org.jboss.injection.InjectionUtil;
+import org.jboss.logging.Logger;
+import org.jboss.web.WebApplication;
+import org.jboss.web.AbstractWebContainer;
+import org.jboss.web.metamodel.descriptor.WebDD;
+import org.jboss.web.metamodel.descriptor.WebDDObjectFactory;
+import org.jboss.web.metamodel.descriptor.JBossWebDDObjectFactory;
+import org.jboss.web.metamodel.descriptor.Servlet;
+import org.jboss.web.metamodel.descriptor.Filter;
+import org.jboss.xb.binding.JBossXBException;
+import org.jboss.metamodel.descriptor.Listener;
+import org.apache.AnnotationProcessor;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Comment
+ *
+ * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @version $Revision: 1.17 $
+ */
+public class TomcatInjectionContainer implements InjectionContainer, AnnotationProcessor
+{
+ private static final Logger log = Logger.getLogger(TomcatInjectionContainer.class);
+
+ private static class EncMap extends HashMap<String, EncInjector>
+ {
+ private HashMap<String, EncInjector> added;
+
+ public void recordAdded()
+ {
+ added = new HashMap<String, EncInjector>();
+ }
+
+ public void clearAdded()
+ {
+ added = null;
+ }
+
+ public Map<String, EncInjector> getAdded() { return added; }
+
+
+ @Override
+ public EncInjector put(String key, EncInjector value)
+ {
+ if (added != null) added.put(key, value);
+ return super.put(key, value);
+ }
+
+ @Override
+ public void putAll(Map<? extends String, ? extends EncInjector> m)
+ {
+ if (added != null) added.putAll(m);
+ super.putAll(m);
+ }
+ }
+
+ protected EncMap encInjectors = new EncMap();
+ protected Map<String, Map<AccessibleObject, Injector>> encInjections = new HashMap<String, Map<AccessibleObject, Injector>>();
+ protected Map<String, Map<AccessibleObject, Injector>> resolvedClassInjections = new HashMap<String, Map<AccessibleObject, Injector>>();
+
+
+ protected List<PersistenceUnitDeployment> persistenceUnitDeployments = new ArrayList<PersistenceUnitDeployment>();
+ protected LinkedHashMap ejbContainers = new LinkedHashMap(); // will always be empty.
+ protected DeploymentPersistenceUnitResolver persistenceUnitResolver;
+ protected WarEjbResolver ejbResolver;
+ protected DependencyPolicy dependencyPolicy = new JmxDependencyPolicy();
+ protected Collection<InjectionHandler> handlers;
+ protected DeploymentInfo di;
+ protected ClassLoader webLoader;
+ protected AbstractWebContainer.WebDescriptorParser parser;
+ protected WebApplication appInfo;
+
+ public TomcatInjectionContainer(AbstractWebContainer.WebDescriptorParser parser, WebApplication appInfo)
+ {
+ this.di = appInfo.getDeploymentInfo();
+ EAR ear = null;
+ this.parser = parser;
+ this.appInfo = appInfo;
+
+ if (di.parent != null)
+ {
+ if (di.parent.shortName.endsWith(".ear") || di.parent.shortName.endsWith(".ear/"))
+ {
+ synchronized (di.parent.context)
+ {
+ ear = (EAR) di.parent.context.get("EJB3_EAR_METADATA");
+ if (ear == null)
+ {
+ ear = new JmxEARImpl(di.parent.shortName);
+ di.parent.context.put("EJB3_EAR_METADATA", ear);
+ }
+ }
+ }
+ }
+ persistenceUnitResolver = new DeploymentPersistenceUnitResolver(persistenceUnitDeployments, ear, ejbContainers);
+ ejbResolver = new WarEjbResolver(ear, di.shortName);
+ }
+
+ public void postConstruct(Object object) throws IllegalAccessException, InvocationTargetException
+ {
+ // ignore for now
+ }
+
+ public void preDestroy(Object object) throws IllegalAccessException, InvocationTargetException
+ {
+ // ignore for now
+ }
+
+ /**
+ * When we get here, we are assuming that any XML defined ENC has been set up. We will set up more here
+ * if the class being processed is a JSP
+ *
+ *
+ * @param object
+ * @throws IllegalAccessException
+ * @throws InvocationTargetException
+ * @throws NamingException
+ */
+ public void processAnnotations(Object object) throws IllegalAccessException, InvocationTargetException, NamingException
+ {
+ Map<AccessibleObject, Injector> injectors = resolvedClassInjections.get(object.getClass().getName());
+ if (injectors == null)
+ {
+ encInjectors.recordAdded();
+ // let's assume this is a JSP or some other artifact that cannot be found within XML
+ injectors = InjectionUtil.processAnnotations(this, handlers, object.getClass());
+ resolvedClassInjections.put(object.getClass().getName(), injectors);
+
+ // only execute injectors that were added additionally
+ if (encInjectors.getAdded().size() > 0)
+ {
+ for (EncInjector encInjector : encInjectors.getAdded().values())
+ {
+ encInjector.inject(this);
+ }
+ encInjectors.clearAdded();
+ }
+ }
+ if (injectors == null || injectors.size() == 0) return;
+
+ for (Injector injector : injectors.values())
+ {
+ injector.inject(object);
+ }
+ }
+
+ public void populateEnc()
+ {
+ for (EncInjector injector : encInjectors.values())
+ {
+ injector.inject(this);
+ }
+ }
+
+ private static InputStream[] getInputStreams(URL warURL)
+ {
+ InputStream jbossWebIS = null;
+ InputStream webIS = null;
+
+ try
+ {
+ // See if the warUrl is a directory
+ File warDir = new File(warURL.getFile());
+ if( warURL.getProtocol().equals("file") && warDir.isDirectory() == true )
+ {
+ File webDD = new File(warDir, "WEB-INF/web.xml");
+ if( webDD.exists() == true )
+ webIS = new FileInputStream(webDD);
+ File jbossWebDD = new File(warDir, "WEB-INF/jboss-web.xml");
+ if( jbossWebDD.exists() == true )
+ jbossWebIS = new FileInputStream(jbossWebDD);
+ }
+ else
+ {
+ // First check for a WEB-INF/web.xml and a WEB-INF/jboss-web.xml
+ InputStream warIS = warURL.openStream();
+ java.util.zip.ZipInputStream zipIS = new java.util.zip.ZipInputStream(warIS);
+ java.util.zip.ZipEntry entry;
+ byte[] buffer = new byte[512];
+ int bytes;
+ while( (entry = zipIS.getNextEntry()) != null )
+ {
+ if( entry.getName().equals("WEB-INF/web.xml") )
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ while( (bytes = zipIS.read(buffer)) > 0 )
+ {
+ baos.write(buffer, 0, bytes);
+ }
+ webIS = new ByteArrayInputStream(baos.toByteArray());
+ }
+ else if( entry.getName().equals("WEB-INF/jboss-web.xml") )
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ while( (bytes = zipIS.read(buffer)) > 0 )
+ {
+ baos.write(buffer, 0, bytes);
+ }
+ jbossWebIS = new ByteArrayInputStream(baos.toByteArray());
+ }
+ }
+ zipIS.close();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ InputStream[] streams = {webIS, jbossWebIS};
+ return streams;
+ }
+
+ /**
+ * introspects EJB container to find all dependencies
+ * and initialize any extra metadata.
+ * <p/>
+ * This must be called before container is registered with any microcontainer
+ *
+ * @param dependencyPolicy
+ */
+ public void processMetadata()
+ {
+ URL warURL = di.localUrl != null ? di.localUrl : di.url;
+ WebDD xml = null;
+ InputStream[] streams = getInputStreams(warURL);
+ if (streams[0] != null)
+ {
+ try
+ {
+ xml = WebDDObjectFactory.parse(streams[0]);
+ if (streams[1] != null)
+ {
+ xml = JBossWebDDObjectFactory.parse(xml, streams[1]);
+ }
+ }
+ catch (JBossXBException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ else
+ {
+ throw new RuntimeException("web.xml is required");
+ }
+
+ // XML must be done first so that any annotation overrides are initialized
+
+ // todo injection handlers should be pluggable from XML
+ handlers = new ArrayList<InjectionHandler>();
+ handlers.add(new EJBHandler());
+ handlers.add(new DependsHandler());
+ handlers.add(new JndiInjectHandler());
+ handlers.add(new PersistenceContextHandler());
+ handlers.add(new PersistenceUnitHandler());
+ handlers.add(new ResourceHandler());
+ handlers.add(new WebServiceHandler());
+
+ ClassLoader old = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(getClassloader());
+ try
+ {
+ for (InjectionHandler handler : handlers) handler.loadXml(xml, this);
+
+ for (Object obj : xml.getServlets())
+ {
+ Servlet servlet = (Servlet)obj;
+ try
+ {
+ if (servlet.getServletClass() == null) continue; // jsp
+ if (resolvedClassInjections.containsKey(servlet.getServletClass())) continue;
+ Class servletClass = getClassloader().loadClass(servlet.getServletClass());
+ Map<AccessibleObject, Injector> tmp = InjectionUtil.processAnnotations(this, handlers, servletClass);
+ resolvedClassInjections.put(servlet.getServletClass(), tmp);
+ }
+ catch (ClassNotFoundException e)
+ {
+ log.warn("could not find servlet class " + servlet.getServletClass() + " in classpath when processing annotations.");
+ }
+
+ }
+ for (Object obj : xml.getFilters())
+ {
+ Filter filter = (Filter)obj;
+ try
+ {
+ if (resolvedClassInjections.containsKey(filter.getFilterClass())) continue;
+ Class servletClass = getClassloader().loadClass(filter.getFilterClass());
+ Map<AccessibleObject, Injector> tmp = InjectionUtil.processAnnotations(this, handlers, servletClass);
+ resolvedClassInjections.put(filter.getFilterClass(), tmp);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException("could not find filter class in classpath", e);
+ }
+ }
+ for (Object obj : xml.getListeners())
+ {
+ Listener listener = (Listener)obj;
+ try
+ {
+ if (resolvedClassInjections.containsKey(listener.getListenerClass())) continue;
+ Class servletClass = getClassloader().loadClass(listener.getListenerClass());
+ Map<AccessibleObject, Injector> tmp = InjectionUtil.processAnnotations(this, handlers, servletClass);
+ resolvedClassInjections.put(listener.getListenerClass(), tmp);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException("could not find listener class in classpath", e);
+ }
+ }
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(old);
+ }
+
+ // We need to establish the JNDI ENC prior to the start
+ // of the web container so that init on startup servlets are able
+ // to interact with their ENC. We hook into the context lifecycle
+ // events to be notified of the start of the
+ // context as this occurs before the servlets are started.
+ if (appInfo.getAppData() == null)
+ {
+ try
+ {
+ parser.parseWebAppDescriptors(getClassloader(), appInfo.getMetaData());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("failed to load ENC", e);
+ }
+ }
+ }
+
+ public Map<String, EncInjector> getEncInjectors()
+ {
+ return encInjectors;
+ }
+
+ public Map<String, Map<AccessibleObject, Injector>> getEncInjections()
+ {
+ return encInjections;
+ }
+
+ // EncInjectors/Handlers may need to add extra instance injectors
+ public List<Injector> getInjectors()
+ {
+ return new ArrayList<Injector>(); // no equivalent in WAR
+ }
+
+
+ public String getIdentifier()
+ {
+ return di.shortName;
+ }
+
+ public String getDeploymentDescriptorType()
+ {
+ return "web.xml";
+ }
+
+ public ClassLoader getClassloader()
+ {
+ return webLoader;
+ }
+
+ public void setClassLoader(ClassLoader loader)
+ {
+ this.webLoader = loader;
+ }
+
+ public Context getEnc()
+ {
+ ClassLoader old = Thread.currentThread().getContextClassLoader();
+ try
+ {
+ Thread.currentThread().setContextClassLoader(getClassloader());
+ try
+ {
+ return (Context) new InitialContext().lookup("java:comp");
+ }
+ catch (NamingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(old);
+ }
+ }
+
+ public Context getEncEnv()
+ {
+ ClassLoader old = Thread.currentThread().getContextClassLoader();
+ try
+ {
+ Thread.currentThread().setContextClassLoader(getClassloader());
+ try
+ {
+ return (Context) new InitialContext().lookup("java:comp/env");
+ }
+ catch (NamingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(old);
+ }
+ }
+
+ public PersistenceUnitDeployment getPersistenceUnitDeployment(String unitName) throws NameNotFoundException
+ {
+ return persistenceUnitResolver.getPersistenceUnitDeployment(unitName);
+ }
+
+ public Container resolveEjbContainer(String link, Class businessIntf)
+ {
+ return ejbResolver.getEjbContainer(link, businessIntf);
+ }
+
+ public Container resolveEjbContainer(Class businessIntf) throws NameNotFoundException
+ {
+ return ejbResolver.getEjbContainer(businessIntf);
+ }
+
+ public String getEjbJndiName(Class businessInterface) throws NameNotFoundException
+ {
+ return ejbResolver.getEjbJndiName(businessInterface);
+ }
+
+ public String getEjbJndiName(String link, Class businessInterface)
+ {
+ return ejbResolver.getEjbJndiName(link, businessInterface);
+ }
+
+ public <T> T getAnnotation(Class<T> annotationType, Class clazz)
+ {
+ return (T) clazz.getAnnotation(annotationType);
+ }
+
+ public <T> T getAnnotation(Class<T> annotationType, Class clazz, Method method)
+ {
+ Class t = annotationType;
+ Object o = method.getAnnotation(t);
+ return (T) o;
+ }
+
+ public <T> T getAnnotation(Class<T> annotationType, Class clazz, Field field)
+ {
+ Class t = annotationType;
+ Object o = field.getAnnotation(t);
+ return (T) o;
+ }
+
+ public DependencyPolicy getDependencyPolicy()
+ {
+ return dependencyPolicy;
+ }
+
+}
Added: trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/WarEjbResolver.java
===================================================================
--- trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/WarEjbResolver.java 2006-08-10 19:11:32 UTC (rev 55497)
+++ trunk/tomcat/src/main/org/jboss/web/tomcat/tc6/WarEjbResolver.java 2006-08-10 19:12:14 UTC (rev 55498)
@@ -0,0 +1,52 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.web.tomcat.tc6;
+
+import org.jboss.ejb3.enc.DeploymentEjbResolver;
+import org.jboss.ejb3.EJBContainer;
+import org.jboss.ejb3.EAR;
+
+import javax.naming.NameNotFoundException;
+
+/**
+ * Comment
+ *
+ * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @version $Revision: 1.17 $
+ */
+public class WarEjbResolver extends DeploymentEjbResolver
+{
+ public WarEjbResolver(EAR ear, String errorName)
+ {
+ super(ear, errorName);
+ }
+
+ protected EJBContainer searchDeploymentInternally(String ejbLink, Class businessIntf)
+ {
+ return null;
+ }
+
+ protected EJBContainer searchForEjbContainerInternally(Class businessIntf) throws NameNotFoundException
+ {
+ return null;
+ }
+}
More information about the jboss-cvs-commits
mailing list