[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