Author: rmannibucau
Date: Sun Jul 31 18:09:54 2011
New Revision: 1152606

URL: http://svn.apache.org/viewvc?rev=1152606&view=rev
Log:
adding @Repository - first version - todo: enhance it

Added:
    
openejb/trunk/openejb3/container/openejb-api/src/main/java/org/apache/openejb/api/Repository.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/QueryProxy.java
Modified:
    openejb/trunk/openejb3/container/openejb-api/pom.xml
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbModule.java

Modified: openejb/trunk/openejb3/container/openejb-api/pom.xml
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-api/pom.xml?rev=1152606&r1=1152605&r2=1152606&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-api/pom.xml (original)
+++ openejb/trunk/openejb3/container/openejb-api/pom.xml Sun Jul 31 18:09:54 
2011
@@ -25,10 +25,18 @@
     <groupId>org.apache.openejb</groupId>
     <version>4.0.0-SNAPSHOT</version>
   </parent>
+
   <modelVersion>4.0.0</modelVersion>
   <artifactId>openejb-api</artifactId>
-  <packaging>jar</packaging>
   <name>OpenEJB :: Container :: API</name>
 
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jpa_2.0_spec</artifactId>
+      <version>1.1</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
 </project>
 

Added: 
openejb/trunk/openejb3/container/openejb-api/src/main/java/org/apache/openejb/api/Repository.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-api/src/main/java/org/apache/openejb/api/Repository.java?rev=1152606&view=auto
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-api/src/main/java/org/apache/openejb/api/Repository.java
 (added)
+++ 
openejb/trunk/openejb3/container/openejb-api/src/main/java/org/apache/openejb/api/Repository.java
 Sun Jul 31 18:09:54 2011
@@ -0,0 +1,18 @@
+package org.apache.openejb.api;
+
+import javax.persistence.PersistenceContext;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author rmannibucau
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Repository {
+    PersistenceContext context() default @PersistenceContext;
+    String jndiName() default "";
+}
+

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=1152606&r1=1152605&r2=1152606&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
 Sun Jul 31 18:09:54 2011
@@ -32,6 +32,7 @@ import org.apache.openejb.NoSuchApplicat
 import org.apache.openejb.OpenEJB;
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.UndeployException;
+import org.apache.openejb.api.Repository;
 import org.apache.openejb.cdi.CdiBuilder;
 import org.apache.openejb.core.ConnectorReference;
 import org.apache.openejb.core.CoreContainerSystem;
@@ -54,20 +55,14 @@ import org.apache.openejb.core.transacti
 import org.apache.openejb.javaagent.Agent;
 import org.apache.openejb.loader.Options;
 import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.persistence.JtaEntityManager;
 import org.apache.openejb.persistence.JtaEntityManagerRegistry;
 import org.apache.openejb.persistence.PersistenceClassLoaderHandler;
 import org.apache.openejb.resource.GeronimoConnectionManagerFactory;
-import org.apache.openejb.rest.ThreadLocalContextManager;
 import org.apache.openejb.spi.ApplicationServer;
 import org.apache.openejb.spi.ContainerSystem;
 import org.apache.openejb.spi.SecurityService;
-import org.apache.openejb.util.AsmParameterNameLoader;
-import org.apache.openejb.util.LogCategory;
-import org.apache.openejb.util.Logger;
-import org.apache.openejb.util.Messages;
-import org.apache.openejb.util.OpenEJBErrorHandler;
-import org.apache.openejb.util.References;
-import org.apache.openejb.util.SafeToolkit;
+import org.apache.openejb.util.*;
 import org.apache.openejb.util.proxy.ProxyFactory;
 import org.apache.openejb.util.proxy.ProxyManager;
 import org.apache.webbeans.config.WebBeansContext;
@@ -88,6 +83,10 @@ import javax.naming.NameAlreadyBoundExce
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceContextType;
+import javax.persistence.PersistenceProperty;
+import javax.persistence.metamodel.Type;
 import javax.resource.spi.BootstrapContext;
 import javax.resource.spi.ConnectionManager;
 import javax.resource.spi.ManagedConnectionFactory;
@@ -105,21 +104,11 @@ import java.lang.instrument.ClassFileTra
 import java.lang.instrument.Instrumentation;
 import java.lang.management.ManagementFactory;
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
@@ -152,6 +141,7 @@ public class Assembler extends Assembler
     private final Map<String, AppInfo> deployedApplications = new 
HashMap<String, AppInfo>();
     private final List<DeploymentListener> deploymentListeners = new 
ArrayList<DeploymentListener>();
     private final Set<String> moduleIds = new HashSet<String>();
+    private final Set<String> repositoryNames = new HashSet<String>();
     private static final String GLOBAL_UNIQUE_ID = "global";
 
 
@@ -569,11 +559,13 @@ public class Assembler extends Assembler
             
             // JPA - Persistence Units MUST be processed first since they will 
add ClassFileTransformers
             // to the class loader which must be added before any classes are 
loaded
+            Map<String, String> units = new HashMap<String, String>();
             PersistenceBuilder persistenceBuilder = new 
PersistenceBuilder(persistenceClassLoaderHandler);
             for (PersistenceUnitInfo info : appInfo.persistenceUnits) {
                 try {
                     EntityManagerFactory factory = 
persistenceBuilder.createEntityManagerFactory(info, classLoader);
                     
containerSystem.getJNDIContext().bind(PERSISTENCE_UNIT_NAMING_CONTEXT + 
info.id, factory);
+                    units.put(info.name, PERSISTENCE_UNIT_NAMING_CONTEXT + 
info.id);
                 } catch (NameAlreadyBoundException e) {
                     throw new OpenEJBException("PersistenceUnit already 
deployed: " + info.persistenceUnitRootUrl);
                 } catch (Exception e) {
@@ -696,6 +688,48 @@ public class Assembler extends Assembler
                     }
                 }
 
+                // @Repository
+                JtaEntityManagerRegistry jtaEntityManagerRegistry = 
SystemInstance.get().getComponent(JtaEntityManagerRegistry.class);
+                for (String repository : ejbJar.repositories) {
+                    try {
+                        Class<?> proxied = classLoader.loadClass(repository);
+                        // TODO: move it in config
+                        Repository annotation = 
proxied.getAnnotation(Repository.class);
+                        PersistenceContext pc = annotation.context();
+
+                        // create the em
+                        Context context = 
SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
+                        EntityManagerFactory factory;
+                        try {
+                            factory = (EntityManagerFactory) 
context.lookup(units.get(pc.unitName()));
+                        } catch (NamingException e) {
+                            throw new OpenEJBException("PersistenceUnit '" + 
pc.unitName() + "' not found");
+                        }
+                        Map<String, String> properties = new 
LinkedHashMap<String, String>();
+                        for (PersistenceProperty property : pc.properties()) {
+                            properties.put(property.name(), property.value());
+                        }
+
+                        JtaEntityManager jtaEntityManager = new 
JtaEntityManager(pc.unitName(), jtaEntityManagerRegistry, factory, properties, 
pc.type() == PersistenceContextType.EXTENDED);
+
+                        Object proxy = Proxy.newProxyInstance(classLoader,
+                                new Class<?>[] { proxied },
+                                new QueryProxy(jtaEntityManager));
+
+                        String jndi = annotation.jndiName();
+                        if (jndi == null || jndi.isEmpty()) {
+                            jndi = "openejb/Repository/" + repository;
+                        }
+                        containerSystemContext.bind(jndi, proxy); // TODO in a 
better way
+                        repositoryNames.add(jndi);
+                        logger.info("Bound @Repository " + repository + " to " 
+ jndi);
+                        appContext.getGlobalJndiContext().bind("global/" + 
jndi, proxy);
+                        logger.info("Bound @Repository " + repository + " to 
global/" + jndi);
+                    } catch (ClassNotFoundException cnfe) {
+                        logger.error("cant' instantiate repository interface " 
+ repository, cnfe);
+                    }
+                }
+
                 allDeployments.addAll(deployments.values());
             }
 
@@ -1096,6 +1130,16 @@ public class Assembler extends Assembler
         }
         moduleIds.clear();
 
+        for (String repoName : repositoryNames) {
+            try {
+                globalContext.unbind(repoName);
+                appContext.getGlobalJndiContext().unbind("global/" + repoName);
+            } catch (NamingException e) {
+                undeployException.getCauses().add(new Exception("repository: " 
+ repoName + ": " + e.getMessage(), e));
+            }
+        }
+        repositoryNames.clear();
+
 
         try {
             if (globalContext instanceof IvmContext) {

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java?rev=1152606&r1=1152605&r2=1152606&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java
 Sun Jul 31 18:09:54 2011
@@ -43,5 +43,6 @@ public class EjbJarInfo extends Validati
     public final Set<String> watchedResources = new TreeSet<String>();
     public final JndiEncInfo moduleJndiEnc = new JndiEncInfo();
 
-    public BeansInfo beans;    
+    public BeansInfo beans;
+    public Set<String> repositories = new TreeSet<String>();
 }

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java?rev=1152606&r1=1152605&r2=1152606&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
 Sun Jul 31 18:09:54 2011
@@ -129,6 +129,7 @@ import org.apache.openejb.BeanContext;
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.api.LocalClient;
 import org.apache.openejb.api.RemoteClient;
+import org.apache.openejb.api.Repository;
 import org.apache.openejb.cdi.CdiBeanInfo;
 import org.apache.openejb.core.webservices.JaxWsUtils;
 import org.apache.openejb.jee.ActivationConfig;
@@ -1260,6 +1261,14 @@ public class AnnotationDeployer implemen
                 }
             }
 
+            //
+            // @Repository
+            //
+            List<Annotated<Class<?>>> repositories = 
finder.findMetaAnnotatedClasses(Repository.class);
+            for (Annotated<Class<?>> clazz : repositories) {
+                ejbModule.getRepositories().add(clazz.get().getName());
+            }
+
             return ejbModule;
         }
 

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java?rev=1152606&r1=1152605&r2=1152606&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
 Sun Jul 31 18:09:54 2011
@@ -169,6 +169,7 @@ class AppInfoBuilder {
                 ejbJarInfo.validationInfo = 
ValidatorBuilder.getInfo(ejbModule.getValidationConfig());
                 
ejbJarInfo.portInfos.addAll(configureWebservices(ejbModule.getWebservices()));
                 ejbJarInfo.uniqueId = ejbModule.getUniqueId();
+                ejbJarInfo.repositories = ejbModule.getRepositories();
                 configureWebserviceSecurity(ejbJarInfo, ejbModule);
 
                 ejbJarInfos.put(ejbModule, ejbJarInfo);

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbModule.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbModule.java?rev=1152606&r1=1152605&r2=1152606&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbModule.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbModule.java
 Sun Jul 31 18:09:54 2011
@@ -55,6 +55,8 @@ public class EjbModule extends Module im
     private ClientModule clientModule;
     private ID id;
 
+    private final Set<String> repositories = new TreeSet<String>();
+
     public EjbModule(EjbJar ejbJar) {
         this(Thread.currentThread().getContextClassLoader(), null, ejbJar, 
null);
     }
@@ -182,6 +184,10 @@ public class EjbModule extends Module im
         return watchedResources;
     }
 
+    public Set<String> getRepositories() {
+        return repositories;
+    }
+
     @Override
     public String toString() {
         return "EjbModule{" +

Added: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/QueryProxy.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/QueryProxy.java?rev=1152606&view=auto
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/QueryProxy.java
 (added)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/QueryProxy.java
 Sun Jul 31 18:09:54 2011
@@ -0,0 +1,109 @@
+package org.apache.openejb.util;
+
+import org.apache.commons.lang.StringUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.persistence.criteria.*;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.SingularAttribute;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author rmannibucau
+ */
+public class QueryProxy implements InvocationHandler {
+    public static final String FIND_PREFIX = "find";
+
+    private final Map<String, Class<?>> RETURN_TYPES = new 
ConcurrentHashMap<String, Class<?>>();
+    private final Map<String, List<String>> CONDITIONS = new 
ConcurrentHashMap<String, List<String>>();
+
+    private EntityManager em;
+
+    public QueryProxy(EntityManager entityManager) {
+        em = entityManager;
+    }
+
+    public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
+        if (!method.getName().startsWith(FIND_PREFIX)) {
+            throw new IllegalArgumentException("finder should start with 
find");
+        }
+
+        final String methodName = method.getName();
+        Class<?> type;
+        if (RETURN_TYPES.containsKey(methodName)) {
+            type = RETURN_TYPES.get(methodName);
+        } else {
+            type =  getGenericType(method.getGenericReturnType());
+        }
+        Query query = getQuery(em, methodName, type, args);
+        if (Collection.class.isAssignableFrom(method.getReturnType())) {
+            return query.getResultList();
+        }
+        return query.getSingleResult();
+    }
+
+    private Class<?> getGenericType(Type type) {
+        if (type instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType) type;
+            if ( pt.getActualTypeArguments().length == 1) {
+                return (Class<?>) pt.getActualTypeArguments()[0];
+            }
+        }
+        return (Class<?>) type;
+    }
+
+    private <T> Query getQuery(EntityManager entityManager, String methodName, 
Class<T> entityType, Object[] args) {
+        final List<String> conditions = parseMethodName(methodName);
+        final EntityType<T> et = 
entityManager.getMetamodel().entity(entityType);
+        final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
+
+        CriteriaQuery<Object> query = cb.createQuery();
+        Root<T> from = query.from(entityType);
+        query = query.select(from);
+
+        int i = 0;
+        for (String condition : conditions) {
+            SingularAttribute<? super T, ?> attribute = 
et.getSingularAttribute(condition);
+            Path<?> path = from.get(attribute);
+            Class<?> javaType = attribute.getType().getJavaType();
+            if (javaType.equals(String.class)) {
+                query = query.where(cb.like((Expression<String>) path, 
(String) args[i++]));
+            } else if (Number.class.isAssignableFrom(javaType) || 
javaType.isPrimitive()) {
+                query = query.where(cb.equal(path, args[i++]));
+            }
+        }
+
+        return entityManager.createQuery(query);
+    }
+
+    private List<String> parseMethodName(final String methodName) {
+        List<String> parsed;
+        if (CONDITIONS.containsKey(methodName)) {
+            parsed = CONDITIONS.get(methodName);
+        } else {
+            parsed = new ArrayList<String>();
+            String toParse = methodName.substring(FIND_PREFIX.length());
+            // TODO: parsing
+            if (toParse.startsWith("By")) {
+                toParse = StringUtils.uncapitalize(toParse.substring(2));
+                parsed.add(toParse);
+            }
+            CONDITIONS.put(methodName, parsed);
+        }
+        return parsed;
+    }
+
+    @Override
+    public String toString() {
+        return "OpenEJB :: QueryProxy";
+    }
+}


Reply via email to