[jboss-cvs] JBossAS SVN: r57756 - in branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3: clientmodule deployment metamodel

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Oct 20 08:22:24 EDT 2006


Author: wolfc
Date: 2006-10-20 08:22:14 -0400 (Fri, 20 Oct 2006)
New Revision: 57756

Modified:
   branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/clientmodule/ClientENCInjectionContainer.java
   branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/deployment/EJB3ClientDeployer.java
   branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/metamodel/JBossClientDDObjectFactory.java
Log:
JBCTS-329: dependencies via kernel

Modified: branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/clientmodule/ClientENCInjectionContainer.java
===================================================================
--- branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/clientmodule/ClientENCInjectionContainer.java	2006-10-20 05:20:39 UTC (rev 57755)
+++ branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/clientmodule/ClientENCInjectionContainer.java	2006-10-20 12:22:14 UTC (rev 57756)
@@ -31,6 +31,8 @@
 import java.util.List;
 import java.util.Map;
 
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
 import javax.naming.Context;
 import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
@@ -39,6 +41,7 @@
 import org.jboss.ejb3.Container;
 import org.jboss.ejb3.DependencyPolicy;
 import org.jboss.ejb3.EAR;
+import org.jboss.ejb3.Ejb3Module;
 import org.jboss.ejb3.JmxDependencyPolicy;
 import org.jboss.ejb3.JmxEARImpl;
 import org.jboss.ejb3.enc.DeploymentEjbResolver;
@@ -73,6 +76,7 @@
    
    private ApplicationClientDD xml;
    private Class<?> mainClass;
+   private String applicationClientName;
    private ClassLoader classLoader;
    
    // TODO: remove injectors, these are not supported
@@ -84,13 +88,22 @@
    private Context encEnv;
    
    private DeploymentEjbResolver ejbResolver;
+   private ObjectName objectName;
    private DependencyPolicy dependencyPolicy = new JmxDependencyPolicy();
 
-   public ClientENCInjectionContainer(DeploymentInfo di, ApplicationClientDD xml, Class<?> mainClass, String applicationClientName, ClassLoader cl, Context encCtx) throws NamingException
+   public ClientENCInjectionContainer(DeploymentInfo di, ApplicationClientDD xml, Class<?> mainClass, String applicationClientName, ClassLoader classLoader, Context encCtx) throws NamingException
    {
+      if(mainClass == null)
+         throw new NullPointerException("mainClass is mandatory");
+      if(applicationClientName == null)
+         throw new NullPointerException("applicationClientName is mandatory");
+      if(classLoader == null)
+         throw new NullPointerException("classLoader is mandatory");
+      
       this.xml = xml;
       this.mainClass = mainClass;
-      this.classLoader = cl;
+      this.applicationClientName = applicationClientName;
+      this.classLoader = classLoader;
       
       this.enc = encCtx;
       
@@ -115,13 +128,28 @@
       }
       ejbResolver = new ClientEjbResolver(ear, di.shortName);
       
+      String on = Ejb3Module.BASE_EJB3_JMX_NAME + createScopeKernelName(di, ear) + ",name=" + applicationClientName;
+      try
+      {
+         this.objectName = new ObjectName(on);
+      }
+      catch(MalformedObjectNameException e)
+      {
+         // should not happen
+         throw new RuntimeException(e);
+      }
+      
       processMetaData();
-      
-      populateEnc();
-      
-      // Don't run any injectors, they must be run client side
    }
    
+   private String createScopeKernelName(DeploymentInfo di, EAR ear)
+   {
+      String scopedKernelName = "";
+      if (ear != null) scopedKernelName += ",ear=" + ear.getShortName();
+      scopedKernelName += ",jar=" + di.shortName;
+      return scopedKernelName;
+   }
+   
    public <T extends Annotation> T getAnnotation(Class<T> annotationType, Class<?> clazz)
    {
       return clazz.getAnnotation(annotationType);
@@ -199,7 +227,7 @@
 
    public String getIdentifier()
    {
-      throw new RuntimeException("NYI");
+      return applicationClientName;
    }
 
    /**
@@ -217,6 +245,11 @@
       return mainClass;
    }
    
+   public ObjectName getObjectName()
+   {
+      return objectName;
+   }
+   
    public PersistenceUnitDeployment getPersistenceUnitDeployment(String unitName) throws NameNotFoundException
    {
       throw new RuntimeException("NYI");
@@ -284,4 +317,17 @@
       return ejbResolver.getEjbContainer(businessIntf);
    }
 
+   public void start()
+   {
+      log.trace("start");
+      
+      populateEnc();
+      
+      // Don't run any injectors, they must be run client side
+   }
+   
+   public void stop()
+   {
+      log.trace("stop");
+   }
 }

Modified: branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/deployment/EJB3ClientDeployer.java
===================================================================
--- branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/deployment/EJB3ClientDeployer.java	2006-10-20 05:20:39 UTC (rev 57755)
+++ branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/deployment/EJB3ClientDeployer.java	2006-10-20 12:22:14 UTC (rev 57756)
@@ -21,28 +21,42 @@
   */
 package org.jboss.ejb3.deployment;
 
+import java.io.DataInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.util.Iterator;
+import java.util.List;
 import java.util.jar.Attributes;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 
+import javassist.bytecode.AnnotationsAttribute;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.FieldInfo;
+import javassist.bytecode.MethodInfo;
+
+import javax.annotation.Resource;
+import javax.ejb.EJB;
 import javax.naming.Context;
 import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
 
 import org.jboss.deployment.DeploymentException;
 import org.jboss.deployment.DeploymentInfo;
 import org.jboss.deployment.SubDeployer;
 import org.jboss.deployment.SubDeployerSupport;
+import org.jboss.ejb3.JmxKernelAbstraction;
+import org.jboss.ejb3.KernelAbstraction;
 import org.jboss.ejb3.clientmodule.ClientENCInjectionContainer;
 import org.jboss.ejb3.metamodel.ApplicationClientDD;
 import org.jboss.ejb3.metamodel.ApplicationClientDDObjectFactory;
 import org.jboss.ejb3.metamodel.JBossClientDDObjectFactory;
 import org.jboss.metadata.XmlFileLoader;
 import org.jboss.naming.Util;
+import org.jboss.util.file.ArchiveBrowser;
 import org.w3c.dom.Element;
 
 /**
@@ -66,7 +80,7 @@
    @Override
    public boolean accepts(DeploymentInfo di)
    {
-      log.debug("accepts " + di.shortName);
+      log.debug("checks " + di.shortName);
       
       String urlStr = di.url.getFile();
       // To be accepted the deployment's root name must end in jar
@@ -78,10 +92,16 @@
       
       if(has50ApplicationClientXml(di))
       {
-         log.info("accepted " + di.shortName);
+         log.trace("found application xml in " + di.shortName);
          return true;
       }
       
+      if(hasAnnotations(di))
+      {
+         log.trace("found annotations in " + di.shortName);
+         return true;
+      }
+      
       return false;
    }
    
@@ -105,6 +125,73 @@
       super.destroy(di);
    }
    
+   /**
+    * If there is no deployment descriptor, or it doesn't specify a JNDI name, then we make up one.
+    * We use the basename from di.shortName.
+    * 
+    * @param di
+    * @param dd
+    * @return   a good JNDI name
+    */
+   private String getJndiName(DeploymentInfo di, ApplicationClientDD dd)
+   {
+      String jndiName = dd.getJndiName();
+      if(jndiName != null)
+         return jndiName;
+      
+      if(di.shortName.endsWith(".jar/"))
+         jndiName = di.shortName.substring(0, di.shortName.length() - 5);
+      else if(di.shortName.endsWith(".jar"))
+         jndiName = di.shortName.substring(0, di.shortName.length() - 4);
+      else
+         throw new IllegalStateException("Expected either '.jar' or '.jar/' at the end of " + di.shortName);
+      
+      return jndiName;
+   }
+   
+   private KernelAbstraction getKernelAbstraction(DeploymentInfo di)
+   {
+      return new JmxKernelAbstraction(di);
+   }
+   
+   protected String getMainClassName(DeploymentInfo di, boolean fail) throws Exception
+   {
+      log.trace("parsing " + di.localCl.findResource(JarFile.MANIFEST_NAME));
+      
+      URL url = di.localCl.findResource(JarFile.MANIFEST_NAME);
+      if(url == null)
+      {
+         if(fail)
+            throw new DeploymentException("Can't find " + JarFile.MANIFEST_NAME);
+         else
+            return null;
+      }
+      InputStream is = url.openStream();
+      Manifest mf;
+      try
+      {
+         mf = new Manifest(is);
+      }
+      finally
+      {
+         is.close();
+      }
+      Attributes attrs = mf.getMainAttributes();
+      String mainClassName = attrs.getValue("Main-Class");
+      // TODO: workaround: TCK uses main-class as key
+      if(mainClassName == null)
+         mainClassName = attrs.getValue("main-class");
+      if(mainClassName == null)
+      {
+         if(fail)
+            throw new Exception("Main-Class is null");
+         else
+            return null;
+      }
+      
+      return mainClassName;
+   }
+   
    protected boolean has50ApplicationClientXml(DeploymentInfo di)
    {
       try
@@ -118,7 +205,7 @@
             XmlFileLoader xfl = new XmlFileLoader(true);
             Element appClient = xfl.getDocument(in, "META-INF/application-client.xml").getDocumentElement();
             String version = appClient.getAttribute("version");
-            if(!version.equals("5"))
+            if(!"5".equals(version))
             {
                log.debug("wrong version application-client.xml in " + di.shortName);
                // it will be picked up by the normal client deployer
@@ -143,6 +230,64 @@
       }
    }
 
+   protected boolean hasAnnotations(DeploymentInfo di)
+   {
+      try
+      {
+         String mainClassName = getMainClassName(di, false);
+         if(mainClassName == null)
+            return false;
+         
+         final String mainClassFileName = mainClassName.replace('.', '/') + ".class";
+         ArchiveBrowser.Filter filter = new ArchiveBrowser.Filter() 
+         {
+            public boolean accept(String fileName)
+            {
+               return fileName != null && fileName.equals(mainClassFileName);
+            }
+         };
+         Iterator it = ArchiveBrowser.getBrowser(di.url, filter);
+         while(it.hasNext())
+         {
+            DataInputStream in = new DataInputStream((InputStream) it.next());
+            try
+            {
+               log.trace("analyzing class " + mainClassName);
+               
+               ClassFile cf = new ClassFile(in);
+               @SuppressWarnings("unchecked")
+               List<FieldInfo> fields = cf.getFields();
+               for(FieldInfo fi : fields)
+               {
+                  AnnotationsAttribute visible = (AnnotationsAttribute) fi.getAttribute(AnnotationsAttribute.visibleTag);
+                  if(hasSupportedAnnotation(visible))
+                     return true;
+               }
+               
+               @SuppressWarnings("unchecked")
+               List<MethodInfo> methods = cf.getMethods();
+               for(MethodInfo mi : methods)
+               {
+                  // TODO: check method signature
+                  
+                  AnnotationsAttribute visible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.visibleTag);
+                  if(hasSupportedAnnotation(visible));
+               }
+            }
+            finally
+            {
+               in.close();
+            }
+         }
+         return false;
+      }
+      catch(Exception e)
+      {
+         log.warn("failure", e);
+         return false;
+      }
+   }
+   
    // TODO: integrate with EJB3Deployer.hasFile
    protected boolean hasFile(DeploymentInfo di, String filePath)
    {
@@ -175,6 +320,21 @@
       return false;
    }
 
+   private boolean hasSupportedAnnotation(AnnotationsAttribute aa)
+   {
+      if(aa == null)
+         return false;
+      
+      // TODO: match supporting annotations
+      
+      if(aa.getAnnotation(EJB.class.getName()) != null)
+         return true;
+      if(aa.getAnnotation(Resource.class.getName()) != null)
+         return true;
+      
+      return false;
+   }
+   
    private Class<?> loadClass(DeploymentInfo di, String className) throws ClassNotFoundException
    {
       ClassLoader old = Thread.currentThread().getContextClassLoader();
@@ -202,60 +362,29 @@
          // Look for a jboss-client.xml descriptor
          URL jbossClientURL = di.localCl.findResource("META-INF/jboss-client.xml");
          xml = JBossClientDDObjectFactory.parse(jbossClientURL, xml);
-//         if(jbossClientURL != null)
-//         {
-//            InputStream in = jbossClientURL.openStream();
-//            try
-//            {
-//               XmlFileLoader xfl = new XmlFileLoader(true);
-//               Element jbossClient = xfl.getDocument(in, "META-INF/jboss-client.xml").getDocumentElement();
-//               
-//               String jndiName = MetaData.getOptionalChildContent(jbossClient, "jndi-name");
-//               xml.setJndiName(jndiName);
-//            }
-//            finally
-//            {
-//               in.close();
-//            }
-//         }
          
          di.metaData = xml;
          
-         String appClientName = xml.getJndiName();
+         // TODO: semanticly incorrect
+         //String appClientName = xml.getJndiName();
+         String appClientName = getJndiName(di, xml);
+         
          // I create the namespace here, because I destroy it in stop
          InitialContext iniCtx = new InitialContext();
          Context encCtx = Util.createSubcontext(iniCtx, appClientName);
-         log.debug("Creating client ENC binding under: " + appClientName);
+         log.info("Creating client ENC binding under: " + appClientName);
          
-         log.trace("parsing " + di.localCl.findResource(JarFile.MANIFEST_NAME));
+         String mainClassName = getMainClassName(di, true);
          
-         URL url = di.localCl.findResource(JarFile.MANIFEST_NAME);
-         InputStream is = url.openStream();
-         if(is == null)
-            throw new DeploymentException("Can't find " + JarFile.MANIFEST_NAME);
-         Manifest mf;
-         try
-         {
-            mf = new Manifest(is);
-         }
-         finally
-         {
-            is.close();
-         }
-         Attributes attrs = mf.getMainAttributes();
-         String mainClassName = attrs.getValue("Main-Class");
-         // TODO: workaround: TCK uses main-class as key
-         if(mainClassName == null)
-            mainClassName = attrs.getValue("main-class");
-         if(mainClassName == null)
-            throw new Exception("Main-Class is null");
-         
          //Class<?> mainClass = di.ucl.loadClass(mainClassName);
          //Class<?> mainClass = di.annotationsCl.loadClass(mainClassName);
          Class<?> mainClass = loadClass(di, mainClassName);
          
          @SuppressWarnings("unused")
          ClientENCInjectionContainer container = new ClientENCInjectionContainer(di, xml, mainClass, appClientName, di.ucl, encCtx);
+         
+         di.deployedObject = container.getObjectName();
+         getKernelAbstraction(di).install(di.deployedObject.getCanonicalName(), container.getDependencyPolicy(), container);
       }
       catch(Exception e)
       {
@@ -273,17 +402,25 @@
    {
       log.debug("stop " + di.shortName);
       
+      if(di.deployedObject != null)
+         getKernelAbstraction(di).uninstall(di.deployedObject.getCanonicalName());
+      
       // Teardown the JNDI context
       ApplicationClientDD metaData = (ApplicationClientDD) di.metaData;
       if (metaData != null)
       {
-         String appClientName = metaData.getJndiName();
-         log.info("Removing client ENC from: " + appClientName);
+         String jndiName = getJndiName(di, metaData);
+         log.info("Removing client ENC from: " + jndiName);
          try
          {
             InitialContext iniCtx = new InitialContext();
-            Util.unbind(iniCtx, appClientName);
+            Util.unbind(iniCtx, jndiName);
          }
+         catch(NameNotFoundException e)
+         {
+            // make sure stop doesn't fail for no reason
+            log.debug("Could not find client ENC");
+         }
          catch (NamingException e)
          {
             throw new DeploymentException("Failed to remove client ENC", e);

Modified: branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/metamodel/JBossClientDDObjectFactory.java
===================================================================
--- branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/metamodel/JBossClientDDObjectFactory.java	2006-10-20 05:20:39 UTC (rev 57755)
+++ branches/JEE5_TCK/ejb3/src/main/org/jboss/ejb3/metamodel/JBossClientDDObjectFactory.java	2006-10-20 12:22:14 UTC (rev 57756)
@@ -54,6 +54,10 @@
    public static ApplicationClientDD parse(URL ddResource, ApplicationClientDD dd)
       throws JBossXBException, IOException
    {
+      // TODO: how to properly fix this
+      if(dd == null)
+         dd = new ApplicationClientDD();
+      
       if(ddResource == null)
          return dd;
       




More information about the jboss-cvs-commits mailing list