Skip to content

Commit

Permalink
rework decoration process, elliminate recursivity, separate handling …
Browse files Browse the repository at this point in the history
…of delegate and non-delegate references inside getInjectableReference
  • Loading branch information
mbogoevici committed Jan 27, 2010
1 parent 0365ad9 commit ef08291
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 119 deletions.
79 changes: 10 additions & 69 deletions impl/src/main/java/org/jboss/weld/bean/AbstractClassBean.java
@@ -1,6 +1,6 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and individual contributors
* 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.
*
Expand Down Expand Up @@ -56,7 +56,7 @@
import org.jboss.interceptor.registry.InterceptorClassMetadataRegistry;
import org.jboss.interceptor.util.InterceptionUtils;
import org.jboss.interceptor.util.proxy.TargetInstanceProxy;
import org.jboss.weld.bean.proxy.DecoratorProxyMethodHandler;
import org.jboss.weld.bean.proxy.DecorationHelper;
import org.jboss.weld.bootstrap.BeanDeployerEnvironment;
import org.jboss.weld.context.SerializableContextualImpl;
import org.jboss.weld.context.SerializableContextualInstanceImpl;
Expand Down Expand Up @@ -140,8 +140,6 @@ private static SerializableContextual[] toSerializableContextualArray(List<Inter
// Decorators
private List<Decorator<?>> decorators;
private Class<T> proxyClassForDecorators;
private final ThreadLocal<Integer> decoratorStackPosition;
private final ThreadLocal<T> decoratedActualInstance = new ThreadLocal<T>();

// Interceptors
private boolean hasSerializationOrInvocationInterceptorMethods;
Expand All @@ -165,16 +163,6 @@ protected AbstractClassBean(WeldClass<T> type, String idSuffix, BeanManagerImpl
{
super(idSuffix, beanManager);
this.annotatedItem = type;
this.decoratorStackPosition = new ThreadLocal<Integer>()
{

@Override
protected Integer initialValue()
{
return 0;
}

};
initStereotypes();
initAlternative();
initInitializerMethods();
Expand Down Expand Up @@ -230,65 +218,18 @@ protected void initProxyClassForDecoratedBean()

protected T applyDecorators(T instance, CreationalContext<T> creationalContext, InjectionPoint originalInjectionPoint)
{
List<SerializableContextualInstance<Decorator<Object>, Object>> decoratorInstances = new ArrayList<SerializableContextualInstance<Decorator<Object>, Object>>();
InjectionPoint ip = originalInjectionPoint;
boolean outside = decoratorStackPosition.get().intValue() == 0;
if (outside)
{
decoratedActualInstance.set(instance);
}
T proxy = null;
DecorationHelper<T> decorationHelper = new DecorationHelper(instance, proxyClassForDecorators, beanManager, decorators);

try
{
int i = decoratorStackPosition.get();
while (i < decorators.size())
{
Decorator<?> decorator = decorators.get(i);
decoratorStackPosition.set(++i);

Object decoratorInstance = getBeanManager().getReference(ip, decorator, creationalContext);
decoratorInstances.add(new SerializableContextualInstanceImpl<Decorator<Object>, Object>((Decorator<Object>) decorator, decoratorInstance, null));
DecorationHelper.getHelperStack().push(decorationHelper);
proxy = decorationHelper.getNextDelegate(originalInjectionPoint, creationalContext);
decorationHelper = (DecorationHelper<T>) DecorationHelper.getHelperStack().pop();

ip = Beans.getDelegateInjectionPoint(decorator);
if (ip == null)
{
throw new ForbiddenStateException(NON_CONTAINER_DECORATOR, decorator);
}
}
}
finally
{
if (outside)
{
decoratorStackPosition.remove();
}
}
try
{
T proxy = SecureReflections.newInstance(proxyClassForDecorators);
// temporary fix for decorators - make sure that the instance wrapped
// by the decorators
// is the contextual instance
// TODO - correct the decoration algorithm to avoid the creation of new
// target class instances
Proxies.attachMethodHandler(proxy, new DecoratorProxyMethodHandler(decoratorInstances, decoratedActualInstance.get()));
return proxy;
}
catch (InstantiationException e)
if (proxy == null)
{
throw new WeldException(PROXY_INSTANTIATION_FAILED, e, this);
}
catch (IllegalAccessException e)
{
throw new WeldException(PROXY_INSTANTIATION_BEAN_ACCESS_FAILED, e, this);
}
finally
{
if (outside)
{
decoratedActualInstance.set(null);
}
throw new WeldException(PROXY_INSTANTIATION_FAILED, this);
}
return proxy;
}

public List<Decorator<?>> getDecorators()
Expand Down
Expand Up @@ -25,7 +25,7 @@
import org.jboss.weld.introspector.WeldClass;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.util.Deployers;
import org.jboss.weld.util.Decorators;

/**
* A wrapper for a decorated instance. Allows to enhance custom decorators with metadata
Expand All @@ -49,7 +49,7 @@ private CustomDecoratorWrapper(Decorator<T> delegate, BeanManagerImpl beanManage
{
this.delegate = delegate;
this.weldClass = beanManager.getServices().get(ClassTransformer.class).loadClass((Class<T>) delegate.getBeanClass());
this.decoratedMethodSignatures = Deployers.getDecoratedMethodSignatures(beanManager, delegate.getDecoratedTypes());
this.decoratedMethodSignatures = Decorators.getDecoratedMethodSignatures(beanManager, delegate.getDecoratedTypes());
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java
Expand Up @@ -52,7 +52,7 @@
import org.jboss.weld.introspector.jlr.WeldConstructorImpl;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.util.Deployers;
import org.jboss.weld.util.Decorators;
import org.jboss.weld.util.Proxies;
import org.jboss.weld.util.reflection.Reflections;

Expand Down Expand Up @@ -135,7 +135,7 @@ protected void initDecoratedTypes()
this.decoratedTypes.addAll(getWeldAnnotated().getInterfaceClosure());
this.decoratedTypes.remove(Serializable.class);

this.decoratedMethodSignatures = Deployers.getDecoratedMethodSignatures(getBeanManager(), this.decoratedTypes);
this.decoratedMethodSignatures = Decorators.getDecoratedMethodSignatures(getBeanManager(), this.decoratedTypes);
}

protected void initDelegateInjectionPoint()
Expand Down
27 changes: 14 additions & 13 deletions impl/src/main/java/org/jboss/weld/bean/ManagedBean.java
Expand Up @@ -217,36 +217,37 @@ public Set<InjectionPoint> getInjectionPoints()

public T produce(final CreationalContext<T> ctx)
{
final T instance = bean.createInstance(ctx);
T instance;
if (!bean.hasDecorators())
{
// This should be safe, but needs verification PLM
// Without this, the chaining of decorators will fail as the
// incomplete instance will be resolved
instance = bean.createInstance(ctx);
ctx.push(instance);
}

T decoratedInstance = new FixInjectionPoint<T>(bean)
else
{

@Override
protected T work()
instance = new FixInjectionPoint<T>(bean)
{
if (bean.hasDecorators())
@Override
protected T work()
{
return bean.applyDecorators(instance, ctx, getOriginalInjectionPoint());
// for decorated beans, creation should use the fixed injection point
// thus ensuring that the innermost decorator is provided as InjectionPoint
T undecoratedInstance = bean.createInstance(ctx);
return bean.applyDecorators(undecoratedInstance, ctx, getOriginalInjectionPoint());
}
return instance;
}

}.run();
}.run();
}
if (bean.isInterceptionCandidate() && (bean.hasCdiBoundInterceptors() || bean.hasDirectlyDefinedInterceptors()))
{
return bean.applyInterceptors(decoratedInstance, ctx);
return bean.applyInterceptors(instance, ctx);
}
else
{
return decoratedInstance;
return instance;
}
}
}
Expand Down
111 changes: 111 additions & 0 deletions impl/src/main/java/org/jboss/weld/bean/proxy/DecorationHelper.java
@@ -0,0 +1,111 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc. and/or its affiliates, 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.bean.proxy;

import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_BEAN_ACCESS_FAILED;
import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_FAILED;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;

import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

import org.jboss.weld.context.SerializableContextualInstanceImpl;
import org.jboss.weld.exceptions.WeldException;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.util.Proxies;
import org.jboss.weld.util.reflection.SecureReflections;

/**
* @author Marius Bogoevici
*/
public class DecorationHelper<T>
{
private static ThreadLocal<Stack<DecorationHelper<?>>> helperStackHolder = new ThreadLocal<Stack<DecorationHelper<?>>>()
{
@Override protected Stack<DecorationHelper<?>> initialValue()
{
return new Stack<DecorationHelper<?>>();
}
};

private Class<T> proxyClassForDecorator;

private T originalInstance;

private T previousDelegate;

private int counter;

private BeanManagerImpl beanManager;

List<Decorator<?>> decorators;

public DecorationHelper(T originalInstance, Class<T> proxyClassForDecorator, BeanManagerImpl beanManager, List<Decorator<?>> decorators)
{
this.originalInstance = originalInstance;
this.beanManager = beanManager;
this.decorators = new LinkedList<Decorator<?>>(decorators);
this.proxyClassForDecorator = proxyClassForDecorator;
counter = 0;
}

public static Stack<DecorationHelper<?>> getHelperStack()
{
return helperStackHolder.get();
}

public DecoratorProxyMethodHandler createMethodHandler(InjectionPoint injectionPoint, CreationalContext<?> creationalContext, Decorator<Object> decorator)
{
Object decoratorInstance = beanManager.getReference(injectionPoint, decorator, creationalContext);
SerializableContextualInstanceImpl<Decorator<Object>, Object> serializableContextualInstance = new SerializableContextualInstanceImpl<Decorator<Object>, Object>(decorator, decoratorInstance, null);
return new DecoratorProxyMethodHandler(serializableContextualInstance, previousDelegate);
}

public T getNextDelegate(InjectionPoint injectionPoint, CreationalContext<?> creationalContext)
{
if (counter == decorators.size())
{
previousDelegate = originalInstance;
return originalInstance;
}
else
{
try
{
T proxy = SecureReflections.newInstance(proxyClassForDecorator);
Proxies.attachMethodHandler(proxy, createMethodHandler(injectionPoint, creationalContext, (Decorator<Object>) decorators.get(counter++)));
previousDelegate = proxy;
return proxy;
}
catch (InstantiationException e)
{
throw new WeldException(PROXY_INSTANTIATION_FAILED, e, this);
}
catch (IllegalAccessException e)
{
throw new WeldException(PROXY_INSTANTIATION_BEAN_ACCESS_FAILED, e, this);
}

}
}

}

0 comments on commit ef08291

Please sign in to comment.