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 2006/11/21 02:31:28 UTC

svn commit: r477461 - in /incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor: ./ Interceptor.java InterceptorData.java InterceptorStack.java ReflectionInvocationContext.java

Author: dain
Date: Mon Nov 20 17:31:27 2006
New Revision: 477461

URL: http://svn.apache.org/viewvc?view=rev&rev=477461
Log:
Simple EJB 3 invocation context implementation

Added:
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/Interceptor.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorStack.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/ReflectionInvocationContext.java

Added: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/Interceptor.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/Interceptor.java?view=auto&rev=477461
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/Interceptor.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/Interceptor.java Mon Nov 20 17:31:27 2006
@@ -0,0 +1,56 @@
+/**
+ *
+ * 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.interceptor;
+
+import javax.interceptor.InvocationContext;
+import java.lang.reflect.Method;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class Interceptor {
+    private final Object instance;
+    private final Method method;
+
+    public Interceptor(Object instance, String methodName) {
+        if (instance == null) throw new NullPointerException("instance is null");
+        if (methodName == null) throw new NullPointerException("methodName is null");
+        this.instance = instance;
+        Class instanceClass = instance.getClass();
+        try {
+            this.method = instanceClass.getMethod(methodName, InvocationContext.class);
+        } catch (NoSuchMethodException e) {
+            throw new IllegalArgumentException("Intercepor method " + methodName + " not found on insterceptor class " + instanceClass.getName());
+        }
+    }
+
+    public Interceptor(Object instance, Method method) {
+        if (instance == null) throw new NullPointerException("instance is null");
+        if (method == null) throw new NullPointerException("method is null");
+        this.instance = instance;
+        this.method = method;
+    }
+
+    public Object getInstance() {
+        return instance;
+    }
+
+    public Method getMethod() {
+        return method;
+    }
+}

Added: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java?view=auto&rev=477461
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java Mon Nov 20 17:31:27 2006
@@ -0,0 +1,39 @@
+/**
+ *
+ * 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.interceptor;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class InterceptorData {
+    private final String interceptorClass;
+    private final String interceptorMethod;
+
+    public InterceptorData(String interceptorClass, String interceptorMethod) {
+        this.interceptorClass = interceptorClass;
+        this.interceptorMethod = interceptorMethod;
+    }
+
+    public String getInterceptorClass() {
+        return interceptorClass;
+    }
+
+    public String getInterceptorMethod() {
+        return interceptorMethod;
+    }
+}

Added: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorStack.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorStack.java?view=auto&rev=477461
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorStack.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorStack.java Mon Nov 20 17:31:27 2006
@@ -0,0 +1,77 @@
+/**
+ *
+ * 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.interceptor;
+
+import javax.interceptor.InvocationContext;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Collection;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class InterceptorStack {
+    private final Object beanInstance;
+    private final List<Interceptor> interceptors;
+    private final Method method;
+    private boolean lifecycleInvocation;
+
+    public InterceptorStack(Object beanInstance, Method method, boolean lifecycleInvocation, Collection<Object> interceptorInstances, List<InterceptorData> interceptorDatas) {
+        this.beanInstance = beanInstance;
+        this.method = method;
+        this.lifecycleInvocation = lifecycleInvocation;
+
+        Map<String, Object> interceptorsByClass = new HashMap<String, Object>();
+        for (Object interceptor : interceptorInstances) {
+            interceptorsByClass.put(interceptor.getClass().getName(), interceptor);
+        }
+
+        interceptors = new ArrayList<Interceptor>(interceptorDatas.size());
+        for (InterceptorData interceptorData : interceptorDatas) {
+            String interceptorClass = interceptorData.getInterceptorClass();
+            Object interceptorInstance = interceptorsByClass.get(interceptorClass);
+            if (interceptorInstance == null) {
+                throw new IllegalArgumentException("No interceptor of type " + interceptorClass);
+            }
+            Interceptor interceptor = new Interceptor(interceptorInstance, interceptorData.getInterceptorMethod());
+            interceptors.add(interceptor);
+        }
+    }
+
+    public InterceptorStack(Object beanInstance, Method method, boolean lifecycleInvocation, List<Interceptor> interceptors) {
+        this.beanInstance = beanInstance;
+        this.method = method;
+        this.lifecycleInvocation = lifecycleInvocation;
+        this.interceptors = interceptors;
+    }
+
+    public InvocationContext createInvocationContext() {
+        InvocationContext invocationContext = new ReflectionInvocationContext(interceptors, beanInstance, method, lifecycleInvocation);
+        return invocationContext;
+    }
+
+    public Object invoke(Object... parameters) throws Exception {
+        InvocationContext invocationContext = createInvocationContext();
+        invocationContext.setParameters(parameters);
+        Object value = invocationContext.proceed();
+        return value;
+    }
+}

Added: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/ReflectionInvocationContext.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/ReflectionInvocationContext.java?view=auto&rev=477461
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/ReflectionInvocationContext.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/ReflectionInvocationContext.java Mon Nov 20 17:31:27 2006
@@ -0,0 +1,140 @@
+/**
+ *
+ * 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.interceptor;
+
+import javax.interceptor.InvocationContext;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.List;
+import java.util.TreeMap;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ReflectionInvocationContext implements InvocationContext {
+    private final Iterator<Interceptor> interceptors;
+    private final Object target;
+    private final Method method;
+    private final Object[] parameters;
+    private final Map<String, Object> contextData = new TreeMap<String, Object>();
+    private final Class<?>[] parameterTypes;
+
+    private final boolean lifecycleInvocation;
+    private boolean parametersSet;
+
+    public ReflectionInvocationContext(List<Interceptor> interceptors, Object target, Method method, boolean lifecycleInvocation) {
+        if (interceptors == null) throw new NullPointerException("interceptors is null");
+        if (target == null) throw new NullPointerException("target is null");
+
+        this.interceptors = interceptors.iterator();
+        this.target = target;
+        this.method = method;
+        parameterTypes = method.getParameterTypes();
+        parameters = new Object[parameterTypes.length];
+
+        this.lifecycleInvocation = lifecycleInvocation;
+        parametersSet = parameters.length == 0;
+    }
+
+    public Object getTarget() {
+        return target;
+    }
+
+    public Method getMethod() {
+        if (lifecycleInvocation) return null;
+        return method;
+    }
+
+    public Object[] getParameters() {
+        return parameters.clone();
+    }
+
+    public void setParameters(Object[] parameters) {
+        if (parameters == null) throw new NullPointerException("parameters is null");
+        if (parameters.length != this.parameters.length) {
+            throw new IllegalArgumentException("Expected " + this.parameters.length + " parameters, but only got " + parameters.length + " parameters");
+        }
+        for (int i = 0; i < parameters.length; i++) {
+            Object parameter = parameters[i];
+            Class<?> parameterType = parameterTypes[i];
+
+            if (parameter == null) {
+                if (parameterType.isPrimitive()) {
+                    throw new IllegalArgumentException("Parameter " + i + " to be primitive type " + parameterType.getName() +
+                        ", but got a parameter is null");
+                }
+            } else if (!parameterType.isInstance(parameter)) {
+                throw new IllegalArgumentException("Expect parameter " + i + " to be type " + parameterType.getName() +
+                    ", but got a parameter of type " + parameter.getClass().getName());
+            }
+        }
+        System.arraycopy(parameters, 0, this.parameters, 0, parameters.length);
+    }
+
+    public Map<String, Object> getContextData() {
+        return contextData;
+    }
+
+    public Object proceed() throws Exception {
+        if (!parametersSet) throw new IllegalStateException("Parameters have not been set");
+
+        if (interceptors.hasNext()) {
+            Interceptor interceptor = interceptors.next();
+            Object nextInstance = interceptor.getInstance();
+            Method nextMethod = interceptor.getMethod();
+            try {
+                Object value = nextMethod.invoke(nextInstance, this);
+                return value;
+            } catch (InvocationTargetException e) {
+                throw unwrapInvocationTargetException(e);
+            }
+        } else if (method != null) {
+            try {
+                Object value = method.invoke(target, parameters);
+                return value;
+            } catch (InvocationTargetException e) {
+                throw unwrapInvocationTargetException(e);
+            }
+        }
+        return null;
+    }
+
+    // todo verify excpetion types
+
+    /**
+     * Business method interceptors can only throw exception allowed by the target business method.
+     * Lifecycle interceptors can only throw RuntimException.
+     * @param e the invocation target excption of a reflection method invoke
+     * @return the cause of the exception
+     * @throws Error if the cause is not an Exception
+     */
+    private Exception unwrapInvocationTargetException(InvocationTargetException e) {
+        Throwable cause = e.getCause();
+        if (cause == null) {
+            return e;
+        } else if (cause instanceof Exception) {
+            return (Exception) cause;
+        } else if (cause instanceof Error) {
+            throw (Error) cause;
+        } else {
+            throw new AssertionError(cause);
+        }
+    }
+}