Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   * JBoss, Home of Professional Open Source
   * Copyright 2008, 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
  * 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 java.util.List;
 import java.util.Set;
Proxy factory that generates client proxies, it uses optimizations that are not valid for other proxy types.

Stuart Douglas
Marius Bogoevici
 public class ClientProxyFactory<T> extends ProxyFactory<T> {
     private static final Set<Class<? extends Annotation>> CACHEABLE_SCOPES;
     public static final String CLIENT_PROXY_SUFFIX = "ClientProxy";
     private static final String CACHE_FIELD = "BEAN_INSTANCE_CACHE";
     private static final String HASH_CODE_METHOD = "hashCode";
     private static final String EMPTY_PARENTHESES = "()";
     private static final String END_INTERCEPTOR_CONTEXT_METHOD_NAME = "endInterceptorContext";
     private static final String START_INTERCEPTOR_CONTEXT_METHOD_NAME = "startInterceptorContext";

It is possible although very unlikely that two different beans will end up with the same proxy class (generally this will only happen in test situations where weld is being started/stopped multiple times in the same class loader, such as during unit tests)

To avoid this causing serialization problems we explicitly set the bean id on creation, and store it in this field.

     private static final String BEAN_ID_FIELD = "BEAN_ID_FIELD";
     private final BeanIdentifier beanId;
     private volatile Field beanIdField;
     private volatile Field threadLocalCacheField;
     static {
         Set<Class<? extends Annotation>> scopes = new HashSet<Class<? extends Annotation>>();
         = Collections.unmodifiableSet(scopes);
    public ClientProxyFactory(String contextIdClass<?> proxiedBeanTypeSet<? extends TypetypeClosureBean<?> bean) {
         = Container.instance(contextId).services().get(ContextualStore.class).putIfAbsent(bean);
    public T create(BeanInstance beanInstance) {
        try {
            final T instance = super.create(beanInstance);
            if ( == null) {
                final Field f = AccessController.doPrivileged(new GetDeclaredFieldAction(instance.getClass(), ));
                 = f;
            if ( == null && isUsingUnsafeInstantiators()) {
                final Field f = AccessController.doPrivileged(new GetDeclaredFieldAction(instance.getClass(),  ));
                 = f;
            if(isUsingUnsafeInstantiators()) {
                .set(instancenew ThreadLocal());
            return instance;
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (PrivilegedActionException e) {
            throw new RuntimeException(e.getCause());
    protected void addFields(final ClassFile proxyClassTypeList<DeferredBytecodeinitialValueBytecode) {
        if (.contains(getBean().getScope())) {
            try {
                proxyClassType.addField(. | .);
                initialValueBytecode.add(new DeferredBytecode() {
                    public void apply(final CodeAttribute codeAttribute) {
                        codeAttribute.invokespecial(ThreadLocal.class.getName(),  + .);
                        codeAttribute.putfield(proxyClassType.getName(), );
            } catch (DuplicateMemberException e) {
                throw new RuntimeException(e);
        proxyClassType.addField(. | .BeanIdentifier.class);
    protected void addSerializationSupport(ClassFile proxyClassType) {
        final Class<Exception>[] exceptions = new Class[]{ObjectStreamException.class};
        final ClassMethod writeReplace = proxyClassType.addMethod(."writeReplace");
        CodeAttribute b = writeReplace.getCodeAttribute();
        b.getfield(proxyClassType.getName(), BeanIdentifier.class);

Calls methodHandler.invoke with a null method parameter in order to get the underlying instance. The invocation is then forwarded to this instance with generated bytecode.
    protected void createForwardingMethodBody(ClassMethod classMethodMethodInformation methodInfoClassMethod staticConstructor) {
        Method method = methodInfo.getMethod();
        // we can only use bytecode based invocation for some methods
        // at the moment we restrict it solely to public methods with public
        // return and parameter types
        boolean bytecodeInvocationAllowed = Modifier.isPublic(method.getModifiers()) && Modifier.isPublic(method.getReturnType().getModifiers());
        for (Class<?> paramType : method.getParameterTypes()) {
            if (!Modifier.isPublic(paramType.getModifiers())) {
                bytecodeInvocationAllowed = false;
        if (!bytecodeInvocationAllowed) {
        final CodeAttribute b = classMethod.getCodeAttribute();
        // create a new interceptor invocation context whenever we invoke a method on a client proxy
        // we use a try-catch block in order to make sure that endInterceptorContext() is invoked regardless whether
        // the method has succeeded or not
        final ExceptionHandler start = b.exceptionBlockStart(Throwable.class.getName());
        final Class<? extends Annotationscope = getBean().getScope();
        if (.contains(scope)) {
            loadCacheableBeanInstance(classMethod.getClassFile(), methodInfob);
        } else {
            loadBeanInstance(classMethod.getClassFile(), methodInfob);
        //now we should have the target bean instance on top of the stack
        // we need to dup it so we still have it to compare to the return value
        //lets create the method invocation
        String methodDescriptor = methodInfo.getDescriptor();
        if (method.getDeclaringClass().isInterface()) {
            b.invokeinterface(methodInfo.getDeclaringClass(), methodInfo.getName(), methodDescriptor);
        } else {
            b.invokevirtual(methodInfo.getDeclaringClass(), methodInfo.getName(), methodDescriptor);
        // end the interceptor context, everything was fine
        // jump over the catch block
        BranchEnd gotoEnd = b.gotoInstruction();
        // create catch block
        // update the correct address to jump over the catch block
        // if this method returns a primitive we just return
        if (method.getReturnType().isPrimitive()) {
        } else {
            // otherwise we have to check that the proxy is not returning 'this;
            // now we need to check if the proxy has return 'this' and if so return
            // an
            // instance of the proxy.
            // currently we have result, beanInstance on the stack.
            // now we have result, beanInstance, result
            // we need to compare result and beanInstance
            // first we need to build up the inner conditional that just returns
            // the
            // result
            final BranchEnd returnInstruction = b.ifAcmpeq();
            // now add the case where the proxy returns 'this';

If the bean is part of a well known scope then this code caches instances in a thread local for the life of the request, as a performance enhancement.
    private void loadCacheableBeanInstance(ClassFile fileMethodInformation methodInfoCodeAttribute b) {
        //first we need to see if the scope is active
        //if it is not active we just get the bean directly
        final BranchEnd returnInstruction = b.ifeq();
        //get the bean from the cache
        b.invokevirtual(ThreadLocal.class.getName(), "get" + );
        final BranchEnd createNewInstance = b.ifnull();
        //so we have a not-null bean instance in the cache
        final BranchEnd loadedFromCache = b.gotoInstruction();
        //we need to get a bean instance and cache it
        //first clear the null off the top of the stack
        b.invokevirtual(ThreadLocal.class.getName(), "set""(" +  + ")" + .);
        final BranchEnd endOfIfStatement = b.gotoInstruction();
    private void loadBeanInstance(ClassFile fileMethodInformation methodInfoCodeAttribute b) {
        b.getfield(file.getName(), "methodHandler", DescriptorUtils.classToStringRepresentation(MethodHandler.class));
        //pass null arguments to methodHandler.invoke
        // now we have all our arguments on the stack
        // lets invoke the method

Client proxies use the following hashCode: MyProxyName.class.hashCode()
    protected void generateHashCodeMethod(ClassFile proxyClassType) {
        final ClassMethod method = proxyClassType.addMethod(..);
        final CodeAttribute b = method.getCodeAttribute();
        // MyProxyName.class.hashCode()
        // now we have the class object on top of the stack
        // now we have the hashCode

Client proxies are equal to other client proxies for the same bean.

The corresponding java code: return other instanceof MyProxyClassType.class

    protected void generateEqualsMethod(ClassFile proxyClassType) {
        ClassMethod method = proxyClassType.addMethod(."equals".);
        CodeAttribute b = method.getCodeAttribute();
    protected String getProxyNameSuffix() {
        return ;
New to GrepCode? Check out our FAQ X