You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2007/08/10 22:23:23 UTC

svn commit: r564749 - in /openejb/trunk/openejb3: assembly/openejb-tomcat/ container/openejb-core/src/main/java/org/apache/openejb/config/ container/openejb-core/src/main/java/org/apache/openejb/core/cmp/ container/openejb-core/src/main/resources/META-...

Author: dain
Date: Fri Aug 10 13:23:22 2007
New Revision: 564749

URL: http://svn.apache.org/viewvc?view=rev&rev=564749
Log:
Fix agent extension code for JPA
Fixed some unenhanced JPA class bugs with CMP

Added:
    openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.javaagent.AgentExtention/EmbeddedJpaEnhancher
    openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/cmp/jpa/JpaEnhancedTest.java
    openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/AgentExtensionInitializer.java
Modified:
    openejb/trunk/openejb3/assembly/openejb-tomcat/maven.xml
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EmbeddedJpaEnhancher.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java
    openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/Agent.java

Modified: openejb/trunk/openejb3/assembly/openejb-tomcat/maven.xml
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/maven.xml?view=diff&rev=564749&r1=564748&r2=564749
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/maven.xml (original)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/maven.xml Fri Aug 10 13:23:22 2007
@@ -215,6 +215,22 @@
     <!--   Testing profiles   -->
     <!--======================-->
 
+    <goal name="launch">
+      <attainGoal name="tomcat6"/>
+      <attainGoal name="setup:tomcat"/>
+      <attainGoal name="setup:loader-webapp"/>
+      <attainGoal name="setup:itests"/>
+      <attainGoal name="start:tomcat"/>
+    </goal>
+
+    <goal name="launch-debug">
+      <attainGoal name="tomcat6"/>
+      <attainGoal name="setup:tomcat"/>
+      <attainGoal name="setup:loader-webapp"/>
+      <attainGoal name="setup:itests"/>
+      <attainGoal name="start:tomcat-debug"/>
+    </goal>
+
     <goal name="test:tomcat">
       <attainGoal name="setup:tomcat"/>
       <attainGoal name="setup:loader-webapp"/>

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EmbeddedJpaEnhancher.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EmbeddedJpaEnhancher.java?view=diff&rev=564749&r1=564748&r2=564749
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EmbeddedJpaEnhancher.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EmbeddedJpaEnhancher.java Fri Aug 10 13:23:22 2007
@@ -16,21 +16,24 @@
  */
 package org.apache.openejb.config;
 
-import org.apache.openejb.javaagent.AgentExtention;
-import org.apache.openejb.core.TemporaryClassLoader;
-import org.apache.openejb.loader.SystemInstance;
-import org.apache.openejb.assembler.classic.Assembler;
-import org.apache.openejb.assembler.classic.AppInfo;
 import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.assembler.classic.PersistenceBuilder;
+import org.apache.openejb.assembler.classic.PersistenceUnitInfo;
+import org.apache.openejb.core.TemporaryClassLoader;
+import org.apache.openejb.javaagent.Agent;
+import org.apache.openejb.javaagent.AgentExtention;
+import org.apache.openejb.jee.jpa.unit.Persistence;
+import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
+import org.apache.openejb.jee.jpa.unit.Property;
+import org.apache.openejb.persistence.PersistenceClassLoaderHandler;
 import org.apache.xbean.finder.ResourceFinder;
 
-import javax.naming.NamingException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.ClassFileTransformer;
 import java.io.IOException;
-import java.io.File;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
 import java.net.URL;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -53,18 +56,75 @@
         }
 
         try {
-            ConfigurationFactory configFactory = new ConfigurationFactory();
-            AppInfo appInfo = configFactory.configureApplication(appModule);
-
-            Assembler assembler = SystemInstance.get().getComponent(Assembler.class);
-            if (assembler == null) {
-                assembler = new Assembler();
+            // read the persistence.xml files
+            ReadDescriptors readDescriptors = new ReadDescriptors();
+            readDescriptors.deploy(appModule);
+
+            // convert the xml to info objects
+            Collection<PersistenceUnitInfo> infos = createPersistenceUnitInfos(appModule);
+
+
+            // create the factories
+            PersistenceBuilder persistenceBuilder = new PersistenceBuilder(new PersistenceClassLoaderHandlerImpl());
+            for (PersistenceUnitInfo info : infos) {
+                try {
+                    // For OpenJPA we only need to create the EMF to cause the enhancer to
+                    // be added.  This may not work for other JPA implementations.
+                    persistenceBuilder.createEntityManagerFactory(info, classLoader);
+                } catch (Exception e) {
+                    throw new OpenEJBException(e);
+                }
             }
-
-            assembler.createApplication(appInfo);
-            assembler.destroyApplication(appInfo.jarPath);
         } catch (Exception e) {
             throw new IllegalStateException("Enhancement failed: "+ e.getMessage(), e);
+        }
+    }
+
+    private Collection<PersistenceUnitInfo> createPersistenceUnitInfos(AppModule appModule) {
+        Collection<PersistenceUnitInfo> persistenceUnits = new ArrayList<PersistenceUnitInfo>();
+        for (PersistenceModule persistenceModule : appModule.getPersistenceModules()) {
+            String rootUrl = persistenceModule.getRootUrl();
+            Persistence persistence = persistenceModule.getPersistence();
+            for (PersistenceUnit persistenceUnit : persistence.getPersistenceUnit()) {
+                PersistenceUnitInfo info = new PersistenceUnitInfo();
+                info.name = persistenceUnit.getName();
+                info.persistenceUnitRootUrl = rootUrl;
+                info.provider = persistenceUnit.getProvider();
+                info.transactionType = persistenceUnit.getTransactionType().toString();
+
+                Boolean excludeUnlistedClasses = persistenceUnit.isExcludeUnlistedClasses();
+                info.excludeUnlistedClasses = excludeUnlistedClasses != null && excludeUnlistedClasses;
+
+                info.jarFiles.addAll(persistenceUnit.getJarFile());
+                info.classes.addAll(persistenceUnit.getClazz());
+                info.mappingFiles.addAll(persistenceUnit.getMappingFile());
+
+                // Handle Properties
+                // todo Do we really want the properties?  This could cause the engine to do bad things
+                org.apache.openejb.jee.jpa.unit.Properties puiProperties = persistenceUnit.getProperties();
+                if (puiProperties != null) {
+                    for (Property property : puiProperties.getProperty()) {
+                        info.properties.put(property.getName(), property.getValue());
+                    }
+                }
+
+                // Persistence Unit Root Url
+                persistenceUnits.add(info);
+            }
+        }
+        return persistenceUnits;
+    }
+
+    private static class PersistenceClassLoaderHandlerImpl implements PersistenceClassLoaderHandler {
+        public void addTransformer(ClassLoader classLoader, ClassFileTransformer classFileTransformer) {
+            Instrumentation instrumentation = Agent.getInstrumentation();
+            if (instrumentation != null) {
+                instrumentation.addTransformer(classFileTransformer);
+            }
+        }
+
+        public ClassLoader getNewTempClassLoader(ClassLoader classLoader) {
+            return new TemporaryClassLoader(classLoader);
         }
     }
 }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java?view=diff&rev=564749&r1=564748&r2=564749
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java Fri Aug 10 13:23:22 2007
@@ -136,8 +136,14 @@
         return deploymentsById.get(deploymentID);
     }
 
-    private DeploymentInfo getDeploymentInfoByClass(Class beanType) {
-        return deploymentsByClass.get(beanType);
+    private DeploymentInfo getDeploymentInfoByClass(Class type) {
+        DeploymentInfo deploymentInfo = null;
+        while (type != null && deploymentInfo == null) {
+            deploymentInfo = deploymentsByClass.get(type);
+            type = type.getSuperclass();
+        }
+
+        return deploymentInfo;
     }
 
     public void deploy(DeploymentInfo deploymentInfo) throws OpenEJBException {
@@ -802,7 +808,7 @@
                 if (value instanceof EntityBean) {
                     EntityBean entityBean = (EntityBean) value;
                     if (proxyFactory == null) {
-                        CoreDeploymentInfo resultInfo = (CoreDeploymentInfo) deploymentsByClass.get(entityBean.getClass());
+                        CoreDeploymentInfo resultInfo = (CoreDeploymentInfo) getDeploymentInfoByClass(entityBean.getClass());
                         if (resultInfo != null) {
                             proxyFactory = new ProxyFactory(resultInfo);
                         }

Added: openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.javaagent.AgentExtention/EmbeddedJpaEnhancher
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.javaagent.AgentExtention/EmbeddedJpaEnhancher?view=auto&rev=564749
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.javaagent.AgentExtention/EmbeddedJpaEnhancher (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.javaagent.AgentExtention/EmbeddedJpaEnhancher Fri Aug 10 13:23:22 2007
@@ -0,0 +1 @@
+org.apache.openejb.config.EmbeddedJpaEnhancher
\ No newline at end of file

Added: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/cmp/jpa/JpaEnhancedTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/cmp/jpa/JpaEnhancedTest.java?view=auto&rev=564749
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/cmp/jpa/JpaEnhancedTest.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/cmp/jpa/JpaEnhancedTest.java Fri Aug 10 13:23:22 2007
@@ -0,0 +1,281 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.openejb.core.cmp.jpa;
+
+import junit.framework.TestCase;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
+import org.apache.openejb.core.TemporaryClassLoader;
+import org.apache.openejb.javaagent.Agent;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.persistence.PersistenceClassLoaderHandler;
+import org.apache.openejb.persistence.PersistenceUnitInfoImpl;
+import org.apache.openejb.resource.SharedLocalConnectionManager;
+import org.apache.openejb.resource.jdbc.JdbcManagedConnectionFactory;
+import org.apache.xbean.naming.context.ImmutableContext;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+public class JpaEnhancedTest extends TestCase {
+//    private static final String PERSISTENCE_PROVIDER = "org.apache.cayenne.jpa.Provider";
+    private static final String PERSISTENCE_PROVIDER = "org.apache.openjpa.persistence.PersistenceProviderImpl";
+
+    private PersistenceUnitTransactionType transactionType;
+    private GeronimoTransactionManager transactionManager;
+    private DataSource jtaDs;
+    private DataSource nonJtaDs;
+    private EntityManagerFactory entityManagerFactory;
+
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // setup tx mgr
+        transactionManager = new GeronimoTransactionManager();
+        SystemInstance.get().setComponent(TransactionSynchronizationRegistry.class, transactionManager);
+
+        // setup naming
+        MockInitialContextFactory.install(Collections.singletonMap("java:comp/TransactionSynchronizationRegistry", transactionManager));
+        assertSame(transactionManager, new InitialContext().lookup("java:comp/TransactionSynchronizationRegistry"));
+
+        // Put tx mgr into SystemInstance so OpenJPA can find it
+        SystemInstance.get().setComponent(TransactionManager.class, transactionManager);
+
+        // init databases
+        jtaDs = createJtaDataSource(transactionManager);
+        nonJtaDs = createNonJtaDataSource();
+        initializeDatabase(jtaDs);
+    }
+
+    public static class MockInitialContextFactory implements InitialContextFactory {
+        private static ImmutableContext immutableContext;
+
+        public static void install(Map bindings) throws NamingException {
+            MockInitialContextFactory.immutableContext = new ImmutableContext(bindings);
+            System.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName());
+            new InitialContext();
+        }
+
+        public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+            return MockInitialContextFactory.immutableContext;
+        }
+    }
+
+    public void tearDown() throws Exception {
+        if (entityManagerFactory != null && entityManagerFactory.isOpen()) {
+            entityManagerFactory.close();
+        }
+
+        if (nonJtaDs != null) {
+            Connection connection = nonJtaDs.getConnection();
+            Statement statement = connection.createStatement();
+            statement.execute("SHUTDOWN");
+            close(statement);
+            close(connection);
+        }
+
+        nonJtaDs = null;
+        jtaDs = null;
+
+        super.tearDown();
+    }
+
+    public void testJta() throws Exception {
+        transactionType = PersistenceUnitTransactionType.JTA;
+        entityManagerFactory = createEntityManagerFactory();
+
+        JpaTestObject jpaTestObject = new JpaTestObject();
+        jpaTestObject.setEntityManagerFactory(entityManagerFactory);
+        jpaTestObject.setTransactionManager(transactionManager);
+        jpaTestObject.setNonJtaDs(nonJtaDs);
+        jpaTestObject.setUp();
+        try {
+            jpaTestObject.jpaLifecycle();
+        } finally {
+            jpaTestObject.tearDown();
+        }
+    }
+
+    public void testResourceLocal() throws Exception {
+        transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
+        entityManagerFactory = createEntityManagerFactory();
+
+        JpaTestObject jpaTestObject = new JpaTestObject();
+        jpaTestObject.setEntityManagerFactory(entityManagerFactory);
+        jpaTestObject.setNonJtaDs(nonJtaDs);
+        jpaTestObject.setUp();
+        try {
+            jpaTestObject.jpaLifecycle();
+        } finally {
+            jpaTestObject.tearDown();
+        }
+    }
+
+    private EntityManagerFactory createEntityManagerFactory() throws Exception {
+        PersistenceClassLoaderHandler persistenceClassLoaderHandler = new PersistenceClassLoaderHandler() {
+            public void addTransformer(ClassLoader classLoader, ClassFileTransformer classFileTransformer) {
+                Instrumentation instrumentation = Agent.getInstrumentation();
+                if (instrumentation != null) {
+                    instrumentation.addTransformer(classFileTransformer);
+                }
+            }
+
+            public ClassLoader getNewTempClassLoader(ClassLoader classLoader) {
+                return new TemporaryClassLoader(classLoader);
+            }
+        };
+
+        PersistenceUnitInfoImpl unitInfo = new PersistenceUnitInfoImpl(persistenceClassLoaderHandler);
+        unitInfo.setPersistenceUnitName("CMP");
+        unitInfo.setPersistenceProviderClassName(PERSISTENCE_PROVIDER);
+        unitInfo.setClassLoader(getClass().getClassLoader());
+        unitInfo.setExcludeUnlistedClasses(false);
+        unitInfo.setJtaDataSource(jtaDs);
+        unitInfo.setNonJtaDataSource(nonJtaDs);
+        unitInfo.addManagedClassName("org.apache.openejb.core.cmp.jpa.Employee");
+        unitInfo.addManagedClassName("org.apache.openejb.core.cmp.jpa.Bill");
+        unitInfo.addManagedClassName("org.apache.openejb.core.cmp.jpa.EmbeddedBill");
+        unitInfo.addManagedClassName("org.apache.openejb.core.cmp.jpa.Person");
+        unitInfo.getMappingFileNames().add("META-INF/jpa-test-mappings.xml");
+
+        // Handle Properties
+        Properties properties = new Properties();
+        properties.setProperty("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)");
+        properties.setProperty("openjpa.Log", "DefaultLevel=WARN");
+        unitInfo.setProperties(properties);
+
+        unitInfo.setTransactionType(transactionType);
+
+        unitInfo.getManagedClassNames().add("org.apache.openejb.core.cmp.jpa.Employee");
+
+        PersistenceProvider persistenceProvider = (PersistenceProvider) getClass().getClassLoader().loadClass(PERSISTENCE_PROVIDER).newInstance();
+        EntityManagerFactory emf = persistenceProvider.createContainerEntityManagerFactory(unitInfo, new HashMap());
+
+        return emf;
+    }
+
+    private void initializeDatabase(DataSource dataSource) throws SQLException {
+        // employee
+        createTable(dataSource, "employee", "CREATE TABLE employee ( id IDENTITY PRIMARY KEY, first_name VARCHAR(255), last_name VARCHAR(255))");
+        execute(dataSource, "INSERT INTO employee (first_name, last_name) VALUES ('David', 'Blevins')");
+
+        // bill
+        createTable(dataSource, "bill", "CREATE TABLE bill ( billNumber BIGINT NOT NULL, billVersion BIGINT NOT NULL, billRevision BIGINT NOT NULL, billDescription VARCHAR(255) )");
+        execute(dataSource, "INSERT INTO bill (billNumber, billVersion, billRevision, billDescription) VALUES (1, 0, 0, 'Basic Model')");
+
+        // embedded bill
+        createTable(dataSource, "embeddedBill", "CREATE TABLE embeddedBill ( billNumber BIGINT NOT NULL, billVersion BIGINT NOT NULL, billRevision BIGINT NOT NULL, billDescription VARCHAR(255) )");
+        execute(dataSource, "INSERT INTO embeddedBill (billNumber, billVersion, billRevision, billDescription) VALUES (2, 0, 0, 'Advanced Model')");
+
+        // relationship bean
+        createTable(dataSource, "OneToOneA", "CREATE TABLE OneToOneA(A1 INTEGER, A2 VARCHAR(255))");
+        createTable(dataSource, "OneToOneB", " CREATE TABLE OneToOneB(B1 INTEGER, B2 VARCHAR(255), B3 INTEGER, B4 VARCHAR(255), FKA1 INTEGER)");
+        execute(dataSource, "INSERT INTO OneToOneA(A1, A2) VALUES(1, 'value1')");
+        execute(dataSource, "INSERT INTO OneToOneA(A1, A2) VALUES(2, 'value2')");
+        execute(dataSource, "INSERT INTO OneToOneB(B1, B2, FKA1) VALUES(11, 'value11', 1)");
+    }
+
+    private void createTable(DataSource dataSource, String tableName, String create) throws SQLException {
+        try {
+            execute(dataSource, "DROP TABLE " + tableName);
+        } catch (Exception e) {
+            // not concerned
+        }
+        execute(dataSource, create);
+    }
+
+    private DataSource createJtaDataSource(TransactionManager transactionManager) throws Exception {
+        JdbcManagedConnectionFactory mcf = new JdbcManagedConnectionFactory("org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:JpaTest", "sa", "", false);
+
+        SharedLocalConnectionManager connectionManager = new SharedLocalConnectionManager(transactionManager);
+
+        DataSource connectionFactory = (DataSource) mcf.createConnectionFactory(connectionManager);
+        return connectionFactory;
+    }
+
+    private DataSource createNonJtaDataSource() throws Exception {
+        BasicDataSource ds = new BasicDataSource();
+        ds.setDriverClassName("org.hsqldb.jdbcDriver");
+        ds.setUrl("jdbc:hsqldb:mem:JpaTest");
+        ds.setUsername("sa");
+        ds.setPassword("");
+        ds.setMaxActive(100);
+        ds.setMaxWait(10000);
+        ds.setTestOnBorrow(true);
+        return ds;
+    }
+
+
+    public boolean execute(DataSource ds, String statement) throws SQLException {
+        boolean retval;
+        Connection connection = null;
+        try {
+            connection = ds.getConnection();
+
+            Statement stmt = connection.createStatement();
+            try {
+                retval = stmt.execute(statement);
+            } finally {
+                close(stmt);
+            }
+        } finally {
+            if (connection != null) {
+                close(connection);
+            }
+        }
+        return retval;
+    }
+
+    private static void close(Statement statement) {
+        if (statement == null) {
+            return;
+        }
+        try {
+            statement.close();
+        } catch (SQLException e) {
+        }
+    }
+
+    private static void close(Connection connection) {
+        if (connection == null) {
+            return;
+        }
+        try {
+            connection.close();
+        } catch (SQLException e) {
+        }
+    }
+}

Modified: openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/Agent.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/Agent.java?view=diff&rev=564749&r1=564748&r2=564749
==============================================================================
--- openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/Agent.java (original)
+++ openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/Agent.java Fri Aug 10 13:23:22 2007
@@ -18,18 +18,9 @@
 package org.apache.openejb.javaagent;
 
 import java.lang.instrument.Instrumentation;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.reflect.ReflectPermission;
 import java.lang.reflect.Field;
+import java.lang.reflect.ReflectPermission;
 import java.security.Permission;
-import java.security.ProtectionDomain;
-import java.net.URL;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Map;
-import java.io.IOException;
 
 public class Agent {
     private static final Permission ACCESS_PERMISSION = new ReflectPermission("suppressAccessChecks");
@@ -41,43 +32,6 @@
         Agent.agentArgs = agentArgs;
         Agent.instrumentation = instrumentation;
         initialized = true;
-//        System.out.println("Agent startup");
-
-//        ClassFileTransformer transformer = new SurefireTransformer();
-//        instrumentation.addTransformer(transformer);
-
-        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-        executeExtentions(classLoader, agentArgs, instrumentation);
-    }
-
-    private static void executeExtentions(ClassLoader classLoader, String agentArgs, Instrumentation instrumentation) {
-        try {
-            ResourceFinder finder = new ResourceFinder("META-INF", classLoader);
-            Map<String, Class> extentions = finder.mapAvailableImplementations(AgentExtention.class);
-//            System.out.println("Agents found: " + extentions.size());
-            List<String> resourcesNotLoaded = finder.getResourcesNotLoaded();
-            for (String className : resourcesNotLoaded) {
-                System.out.println("Agent not loaded: " + className);
-            }
-
-
-            for (Map.Entry<String, Class> entry : extentions.entrySet()) {
-                AgentExtention extention = null;
-                try {
-                    extention = (AgentExtention) entry.getValue().newInstance();
-                } catch (Throwable e) {
-                    new RuntimeException("AgentExtention instantiation failed: AgentExtention(name="+entry.getKey()+", class="+entry.getValue().getName()+")", e).printStackTrace();
-                }
-
-                try {
-                    extention.premain(agentArgs, instrumentation);
-                } catch (Throwable e) {
-                    new RuntimeException("AgentExtention premain failed: AgentExtention(name="+entry.getKey()+", class="+entry.getValue().getName()+")", e).printStackTrace();
-                }
-            }
-        } catch (IOException e) {
-            new RuntimeException("Failed searching for AgentExtentions: "+e.getMessage(), e).printStackTrace();
-        }
     }
 
     public static synchronized String getAgentArgs() {
@@ -119,16 +73,4 @@
         }
     }
 
-    private static class SurefireTransformer implements ClassFileTransformer {
-        private boolean surefirePathEnhanced;
-
-        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
-            if (!surefirePathEnhanced && loader.getClass().getName().equals("org.apache.maven.surefire.booter.IsolatedClassLoader")){
-                surefirePathEnhanced = true;
-                executeExtentions(loader, agentArgs, instrumentation);
-            }
-
-            return classfileBuffer;
-        }
-    }
 }

Added: openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/AgentExtensionInitializer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/AgentExtensionInitializer.java?view=auto&rev=564749
==============================================================================
--- openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/AgentExtensionInitializer.java (added)
+++ openejb/trunk/openejb3/container/openejb-javaagent/src/main/java/org/apache/openejb/javaagent/AgentExtensionInitializer.java Fri Aug 10 13:23:22 2007
@@ -0,0 +1,93 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.openejb.javaagent;
+
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+
+class AgentExtensionInitializer implements ClassFileTransformer {
+    private final WeakHashMap<ClassLoader,Boolean> knownClassLoaders = new WeakHashMap<ClassLoader,Boolean>();
+    private final Set<String> installedExtensions = new TreeSet<String>();
+
+    public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+        String classLoaderName = loader.getClass().getName();
+        boolean shouldExecuteExtentions = false;
+        if (!classLoaderName.equals("org.apache.openejb.core.TemporaryClassLoader")){
+            synchronized(knownClassLoaders) {
+                if (!knownClassLoaders.containsKey(loader)) {
+                    knownClassLoaders.put(loader, true);
+                    shouldExecuteExtentions = true;
+                }
+            }
+        }
+
+        if (shouldExecuteExtentions) {
+            AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                public Object run() {
+                    executeExtentions(loader, Agent.getAgentArgs(), Agent.getInstrumentation());
+                    return null;
+                }
+            });
+        }
+
+        return classfileBuffer;
+    }
+
+    private void executeExtentions(ClassLoader classLoader, String agentArgs, Instrumentation instrumentation) {
+        Map<String, Class> extentions = null;
+
+        try {
+            ResourceFinder finder = new ResourceFinder("META-INF", classLoader);
+            // todo don't load extension classess that have already been processed
+            extentions = finder.mapAvailableImplementations(AgentExtention.class);
+        } catch (IOException e) {
+            new RuntimeException("Failed searching for AgentExtentions: "+e.getMessage(), e).printStackTrace();
+        }
+
+        for (Map.Entry<String, Class> entry : extentions.entrySet()) {
+            if (!installedExtensions.contains(entry.getKey())) {
+                // construct extension object
+                AgentExtention extention = null;
+                try {
+                    extention = (AgentExtention) entry.getValue().newInstance();
+                } catch (Throwable e) {
+                    new RuntimeException("AgentExtention instantiation failed: AgentExtention(name="+entry.getKey()+", class="+entry.getValue().getName()+")", e).printStackTrace();
+                }
+
+                // call premain
+                try {
+                    extention.premain(agentArgs, instrumentation);
+                } catch (Throwable e) {
+                    new RuntimeException("AgentExtention premain failed: AgentExtention(name="+entry.getKey()+", class="+entry.getValue().getName()+")", e).printStackTrace();
+                }
+
+                // extension installed
+                installedExtensions.add(entry.getKey());
+            }
+        }
+    }
+}