All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.autobean.server.impl.ProxyAutoBean Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 2010 Google Inc.
 * 
 * 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 com.google.gwt.autobean.server.impl;

import com.google.gwt.autobean.server.Configuration;
import com.google.gwt.autobean.shared.AutoBean;
import com.google.gwt.autobean.shared.AutoBeanFactory;
import com.google.gwt.autobean.shared.AutoBeanUtils;
import com.google.gwt.autobean.shared.AutoBeanVisitor;
import com.google.gwt.autobean.shared.impl.AbstractAutoBean;
import com.google.gwt.core.client.impl.WeakMapping;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * An implementation of an AutoBean that uses reflection.
 *
 * 

AutoBeans has moved to * com.google.web.bindery.autobeans. This package will be * removed in a future version of GWT.

* * @param the type of interface being wrapped */ @Deprecated public class ProxyAutoBean extends AbstractAutoBean { private static class Data { final List getters = new ArrayList(); final List getterNames = new ArrayList(); final List propertyType = new ArrayList(); } private enum PropertyType { VALUE, REFERENCE, COLLECTION, MAP; } private static final Map, Data> cache = new WeakHashMap, Data>(); /** * Utility method to crete a new {@link Proxy} instance. * * @param the interface type to be implemented by the Proxy * @param intf the Class representing the interface type * @param handler the implementation of the interface * @param extraInterfaces additional interface types the Proxy should * implement * @return a Proxy instance */ public static T makeProxy(Class intf, InvocationHandler handler, Class... extraInterfaces) { Class[] intfs; if (extraInterfaces == null) { intfs = new Class[] {intf}; } else { intfs = new Class[extraInterfaces.length + 1]; intfs[0] = intf; System.arraycopy(extraInterfaces, 0, intfs, 1, extraInterfaces.length); } return intf.cast(Proxy.newProxyInstance(intf.getClassLoader(), intfs, handler)); } private static Data calculateData(Class beanType) { Data toReturn; synchronized (cache) { toReturn = cache.get(beanType); if (toReturn == null) { toReturn = new Data(); for (Method method : beanType.getMethods()) { if (BeanMethod.GET.matches(method)) { toReturn.getters.add(method); String name; PropertyName annotation = method.getAnnotation(PropertyName.class); if (annotation != null) { name = annotation.value(); } else { name = BeanMethod.GET.inferName(method); } toReturn.getterNames.add(name); Class returnType = method.getReturnType(); if (TypeUtils.isValueType(returnType)) { toReturn.propertyType.add(PropertyType.VALUE); } else if (Collection.class.isAssignableFrom(returnType)) { toReturn.propertyType.add(PropertyType.COLLECTION); } else if (Map.class.isAssignableFrom(returnType)) { toReturn.propertyType.add(PropertyType.MAP); } else { toReturn.propertyType.add(PropertyType.REFERENCE); } } } cache.put(beanType, toReturn); } } return toReturn; } private final Class beanType; private final Configuration configuration; private final Data data; private final T shim; // These constructors mirror the generated constructors. @SuppressWarnings("unchecked") public ProxyAutoBean(AutoBeanFactory factory, Class beanType, Configuration configuration) { super(factory); this.beanType = (Class) beanType; this.configuration = configuration; this.data = calculateData(beanType); this.shim = createShim(); } @SuppressWarnings("unchecked") public ProxyAutoBean(AutoBeanFactory factory, Class beanType, Configuration configuration, T toWrap) { super(factory, toWrap); if (Proxy.isProxyClass(toWrap.getClass())) { System.out.println("blah"); } this.beanType = (Class) beanType; this.configuration = configuration; this.data = calculateData(beanType); this.shim = createShim(); } private ProxyAutoBean(ProxyAutoBean toClone, boolean deep) { super(toClone, deep); this.beanType = toClone.beanType; this.configuration = toClone.configuration; this.data = toClone.data; this.shim = createShim(); } @Override public T as() { return shim; } @Override public AutoBean clone(boolean deep) { return new ProxyAutoBean(this, deep); } public Configuration getConfiguration() { return configuration; } public Class getType() { return beanType; } /** * Allow access by {@link ShimHandler}. */ @Override protected void call(String method, Object returned, Object... parameters) { super.call(method, returned, parameters); } /** * Allow access by {@link ShimHandler}. */ @Override protected void checkFrozen() { super.checkFrozen(); } /** * Allow access by {@link ShimHandler}. */ @Override protected void checkWrapped() { super.checkWrapped(); } @Override protected T createSimplePeer() { return ProxyAutoBean.makeProxy(beanType, new SimpleBeanHandler(this)); } /** * Allow access by {@link ShimHandler}. */ @Override protected V get(String method, V toReturn) { return super.get(method, toReturn); } /** * Allow access by {@link BeanMethod}. */ protected Map getValues() { return values; } /** * Allow access by {@link ShimHandler}. */ protected T getWrapped() { return super.getWrapped(); } /** * Allow access by {@link ShimHandler}. */ @Override protected void set(String method, Object value) { super.set(method, value); } // TODO: Port to model-based when class-based TypeOracle is available. @Override protected void traverseProperties(AutoBeanVisitor visitor, OneShotContext ctx) { assert data.getters.size() == data.getterNames.size() && data.getters.size() == data.propertyType.size(); Iterator getterIt = data.getters.iterator(); Iterator nameIt = data.getterNames.iterator(); Iterator typeIt = data.propertyType.iterator(); while (getterIt.hasNext()) { Method getter = getterIt.next(); String name = nameIt.next(); PropertyType propertyType = typeIt.next(); // Use the shim to handle automatic wrapping Object value; try { getter.setAccessible(true); value = getter.invoke(shim); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getCause()); } // Create the context used for the property visitation MethodPropertyContext x = isUsingSimplePeer() ? new BeanPropertyContext( this, getter) : new GetterPropertyContext(this, getter); switch (propertyType) { case VALUE: { if (visitor.visitValueProperty(name, value, x)) { } visitor.endVisitValueProperty(name, value, x); break; } case COLLECTION: { // Workaround for generics bug in mac javac 1.6.0_22 @SuppressWarnings("rawtypes") AutoBean temp = AutoBeanUtils.getAutoBean((Collection) value); @SuppressWarnings("unchecked") AutoBean> bean = (AutoBean>) temp; if (visitor.visitCollectionProperty(name, bean, x)) { if (value != null) { ((ProxyAutoBean) bean).traverse(visitor, ctx); } } visitor.endVisitCollectionProperty(name, bean, x); break; } case MAP: { // Workaround for generics bug in mac javac 1.6.0_22 @SuppressWarnings("rawtypes") AutoBean temp = AutoBeanUtils.getAutoBean((Map) value); @SuppressWarnings("unchecked") AutoBean> bean = (AutoBean>) temp; if (visitor.visitMapProperty(name, bean, x)) { if (value != null) { ((ProxyAutoBean) bean).traverse(visitor, ctx); } } visitor.endVisitMapProperty(name, bean, x); break; } case REFERENCE: { ProxyAutoBean bean = (ProxyAutoBean) AutoBeanUtils.getAutoBean(value); if (visitor.visitReferenceProperty(name, bean, x)) { if (value != null) { bean.traverse(visitor, ctx); } } visitor.endVisitReferenceProperty(name, bean, x); break; } } } } Class getBeanType() { return beanType; } Map getPropertyMap() { return values; } private T createShim() { T toReturn = ProxyAutoBean.makeProxy(beanType, new ShimHandler(this, getWrapped())); WeakMapping.set(toReturn, AutoBean.class.getName(), this); return toReturn; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy