Skip to content

Commit

Permalink
apply stuarts changes
Browse files Browse the repository at this point in the history
  • Loading branch information
pmuir committed Jul 26, 2010
2 parents 3a46da1 + 16dfd9e commit d1f1423
Show file tree
Hide file tree
Showing 16 changed files with 735 additions and 0 deletions.
@@ -0,0 +1,52 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.weld.extensions.servicehandler;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Meta annotation that is used to specify an invocation handler for an
* automatically implmented bean.
*
* If the annotation that is annotated with this meta-annotation is applied to
* an interface or abstract class then the container will automatically provide
* a concrete implementation of the class/interface, and delegate all calls to
* abstract methods through the handler class specified by this annotations.
*
* The handler class must have a method with the following signature:
*
* <pre>
* @AroundInvoke public Object aroundInvoke(final InvocationContext invocation) throws Exception
* </pre>
*
* This is the same as an intercepter class. This handler can be injected into
* and use initializer methods, however @PreDestory methods are not availble
*
* @author Stuart Douglas <stuart.w.douglas@gmail.com>
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@Documented
public @interface ServiceHandler
{
Class<?> value();
}
@@ -0,0 +1,93 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.weld.extensions.servicehandler;

import java.lang.reflect.Method;

import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;

import org.jboss.weld.extensions.bean.BeanLifecycle;

/**
* Bean lifecycle for ServiceHandler beans
*
* @author Stuart Douglas
*
* @param <T>
* @param <H>
*/
public class ServiceHandlerBeanLifecycle<T, H> implements BeanLifecycle<T>
{
private final ProxyFactory factory;
private final Class<? extends T> proxyClass;
private final ServiceHandlerManager<H> handler;

public ServiceHandlerBeanLifecycle(Class<? extends T> classToImplement, Class<H> handlerClass, BeanManager manager)
{
handler = new ServiceHandlerManager<H>(handlerClass, manager);

// create the proxy
factory = new ProxyFactory();
if (classToImplement.isInterface())
{
Class<?>[] interfaces = new Class[1];
interfaces[0] = classToImplement;
factory.setInterfaces(interfaces);
}
else
{
factory.setSuperclass(classToImplement);
}
factory.setFilter(new MethodFilter()
{
public boolean isHandled(Method m)
{
// ignore finalize()
return !m.getName().equals("finalize");
}
});
proxyClass = factory.createClass();
}

public T create(Bean<T> bean, CreationalContext<T> creationalContext)
{
try
{
H handlerInstance = handler.create((CreationalContext) creationalContext); //not sure if this is ok
ServiceHandlerMethodHandler<T, H> methodHandler = new ServiceHandlerMethodHandler<T, H>(handler, handlerInstance);
T instance = proxyClass.newInstance();
((ProxyObject) instance).setHandler(methodHandler);
return instance;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}

public void destroy(Bean<T> bean, T instance, CreationalContext<T> creationalContext)
{
// handler.dispose(instance);
}

}
@@ -0,0 +1,69 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.weld.extensions.servicehandler;

import java.util.HashSet;
import java.util.Set;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;

import org.jboss.weld.extensions.bean.BeanBuilder;
import org.jboss.weld.extensions.util.AnnotationInspector;

/**
* This extension automatically implements interfaces and abstract classes.
*
* @author Stuart Douglas
*
*/
public class ServiceHandlerExtension implements Extension
{
Set<Bean<?>> beans = new HashSet<Bean<?>>();

public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event, BeanManager beanManager)
{
ServiceHandler annotation = AnnotationInspector.getMetaAnnotation(event.getAnnotatedType(), ServiceHandler.class);
if (annotation != null)
{
Class<?> handlerClass = annotation.value();
try
{
BeanBuilder builder = new BeanBuilder(beanManager);
builder.defineBeanFromAnnotatedType(event.getAnnotatedType());
builder.setBeanLifecycle(new ServiceHandlerBeanLifecycle(event.getAnnotatedType().getJavaClass(), handlerClass, beanManager));
beans.add(builder.create());
}
catch (IllegalArgumentException e)
{
throw new RuntimeException(e);
}
}
}

public void afterBeanDiscovery(@Observes AfterBeanDiscovery event)
{
for (Bean<?> b : beans)
{
event.addBean(b);
}
}
}
@@ -0,0 +1,97 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.weld.extensions.servicehandler;

import java.lang.reflect.Method;
import java.util.Set;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

import org.jboss.weld.extensions.annotated.AnnotatedTypeBuilder;
import org.jboss.weld.extensions.util.Reflections;

/**
* Manages the handler class for the service handler extension. This class is
* responsible for managing the lifecycle of the handler class instances
*
* @author Stuart Douglas
*
*/
public class ServiceHandlerManager<T>
{
private final Class<T> handlerClass;
private final Method handlerMethod;
private final InjectionTarget<T> injectionTarget;

/**
* Creates a wrapper around an AutoProxy handler class
*
* @param handlerClass The handler class
* @throws IllegalArgumentException if the handler class is does not have a
* suitable @AroundInvoke method
*/
public ServiceHandlerManager(Class<T> handlerClass, BeanManager beanManager) throws IllegalArgumentException
{
this.handlerClass = handlerClass;
Set<Method> methods = Reflections.getAllMethods(handlerClass);
Method handler = null;
//search for the handler method
for (Method m : methods)
{
if (m.isAnnotationPresent(AroundInvoke.class))
{
if (m.getParameterTypes().length != 1 || m.getParameterTypes()[0] != InvocationContext.class)
{
throw new IllegalArgumentException("Could not find suitable AroundInvoke method on class " + handlerClass + " methods denoted @AroundInvoke must have a single InvokationContext parameter");
}
handler = m;
break;
}
}
if (handler == null)
{
throw new IllegalArgumentException("Could not find suitable AroundInvoke method on class " + handlerClass);
}
handlerMethod = handler;
//now create the InjectionTarget
AnnotatedTypeBuilder<T> typeBuilder = new AnnotatedTypeBuilder<T>().readFromType(handlerClass);
injectionTarget = beanManager.createInjectionTarget(typeBuilder.create());
}

public T create(CreationalContext<T> ctx)
{
T instance = injectionTarget.produce(ctx);
injectionTarget.inject(instance, ctx);
injectionTarget.postConstruct(instance);
return instance;
}

public Object invoke(Object instance, InvocationContext ctx) throws Exception
{
return handlerMethod.invoke(instance, ctx);
}

public Class<?> getHandlerClass()
{
return handlerClass;
}

}

0 comments on commit d1f1423

Please sign in to comment.