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
  * 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 java.util.List;
 import java.util.Set;
 
 
Proxy factory that generates client proxies, it uses optimizations that are not valid for other proxy types.

Author(s):
Stuart Douglas
Marius Bogoevici
 
 public class ClientProxyFactory<T> extends ProxyFactory<T> {
 
     private static final String CLIENT_PROXY_SUFFIX = "ClientProxy";
 
     private static final String HASH_CODE_METHOD = "hashCode";
     private static final String EMPTY_PARENTHESES = "()";

    
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;
 
     public ClientProxyFactory(String contextIdClass<?> proxiedBeanTypeSet<? extends TypetypeClosureBean<?> bean) {
         super(contextIdproxiedBeanTypetypeClosurebean);
          = Container.instance(contextId).services().get(ContextualStore.class).putIfAbsent(bean);
     }
 
     @Override
     public T create(BeanInstance beanInstance) {
         try {
             final T instance = super.create(beanInstance);
             if ( == null) {
                 final Field f = AccessController.doPrivileged(new GetDeclaredFieldAction(instance.getClass(), ));
                 AccessController.doPrivileged(SetAccessibleAction.of(f));
                  = f;
             }
             .set(instance);
             return instance;
         } catch (IllegalAccessException e) {
             throw new RuntimeException(e);
         } catch (PrivilegedActionException e) {
             throw new RuntimeException(e.getCause());
         }
     }
 
     @Override
     protected void addFields(final ClassFile proxyClassTypeList<DeferredBytecodeinitialValueBytecode) {
        super.addFields(proxyClassTypeinitialValueBytecode);
        proxyClassType.addField(. | .BeanIdentifier.class);
    }
    @Override
    protected Class<? extends MethodHandlergetMethodHandlerType() {
        return ProxyMethodHandler.class;
    }
    @Override
    protected void addSerializationSupport(ClassFile proxyClassType) {
        final Class<Exception>[] exceptions = new Class[]{ObjectStreamException.class};
        final ClassMethod writeReplace = proxyClassType.addMethod(."writeReplace");
        writeReplace.addCheckedExceptions(exceptions);
        CodeAttribute b = writeReplace.getCodeAttribute();
        b.dup();
        b.aload(0);
        b.getfield(proxyClassType.getName(), BeanIdentifier.class);
        b.ldc(getContextId());
        b.returnInstruction();
    }


    
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.
    @Override
    protected void createForwardingMethodBody(ClassMethod classMethodfinal MethodInformation methodInfoClassMethod staticConstructor) {
        final 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;
                break;
            }
        }
        if (!bytecodeInvocationAllowed) {
            createInterceptorBody(classMethodmethodInfostaticConstructor);
            return;
        }
        // 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
        new RunWithinInterceptionDecorationContextGenerator(classMethodthis) {
            @Override
            void doWork(CodeAttribute bClassMethod classMethod) {
                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
                b.dup();
                //lets create the method invocation
                String methodDescriptor = methodInfo.getDescriptor();
                b.loadMethodParameters();
                if (method.getDeclaringClass().isInterface()) {
                    b.invokeinterface(methodInfo.getDeclaringClass(), methodInfo.getName(), methodDescriptor);
                } else {
                    b.invokevirtual(methodInfo.getDeclaringClass(), methodInfo.getName(), methodDescriptor);
                }
            }
            @Override
            void doReturn(CodeAttribute bClassMethod classMethod) {
                // assumes doWork() result is on top of the stack
                // if this method returns a primitive we just return
                if (method.getReturnType().isPrimitive()) {
                    b.returnInstruction();
                } 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.
                    b.dupX1();
                    // 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();
                    b.returnInstruction();
                    b.branchEnd(returnInstruction);
                    // now add the case where the proxy returns 'this';
                    b.aload(0);
                    b.checkcast(methodInfo.getMethod().getReturnType().getName());
                    b.returnInstruction();
                }
            }
        }.runStartIfNotEmpty();
    }
    private void loadBeanInstance(ClassFile fileMethodInformation methodInfoCodeAttribute b) {
        b.aload(0);
        getMethodHandlerField(fileb);
        // lets invoke the method
        b.invokevirtual(ProxyMethodHandler.class.getName(), "getInstance" + );
        b.checkcast(methodInfo.getDeclaringClass());
    }

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

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

The corresponding java code: return other instanceof MyProxyClassType.class

    @Override
    protected void generateEqualsMethod(ClassFile proxyClassType) {
        ClassMethod method = proxyClassType.addMethod(."equals".);
        CodeAttribute b = method.getCodeAttribute();
        b.aload(1);
        b.instanceofInstruction(proxyClassType.getName());
        b.returnInstruction();
    }
    @Override
    protected String getProxyNameSuffix() {
        return ;
    }
New to GrepCode? Check out our FAQ X