Coverage Report - org.apache.shindig.social.core.util.xstream.GuiceBeanProvider
 
Classes in this File Line Coverage Branch Coverage Complexity
GuiceBeanProvider
72%
49/68
68%
15/22
0
GuiceBeanProvider$Visitor
N/A
N/A
0
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements. See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership. The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License. You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied. See the License for the
 16  
  * specific language governing permissions and limitations under the License.
 17  
  */
 18  
 package org.apache.shindig.social.core.util.xstream;
 19  
 
 20  
 import com.google.common.collect.Lists;
 21  
 
 22  
 import com.google.inject.Injector;
 23  
 
 24  
 import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
 25  
 import com.thoughtworks.xstream.core.util.OrderRetainingMap;
 26  
 
 27  
 import java.beans.BeanInfo;
 28  
 import java.beans.IntrospectionException;
 29  
 import java.beans.Introspector;
 30  
 import java.beans.PropertyDescriptor;
 31  
 import java.lang.reflect.InvocationTargetException;
 32  
 import java.lang.reflect.Method;
 33  
 import java.util.ArrayList;
 34  
 import java.util.Comparator;
 35  
 import java.util.List;
 36  
 import java.util.Map;
 37  
 import java.util.Set;
 38  
 import java.util.TreeSet;
 39  
 import java.util.WeakHashMap;
 40  
 
 41  
 /**
 42  
  * 
 43  
  */
 44  
 public class GuiceBeanProvider {
 45  
 
 46  1
   protected static final Object[] NO_PARAMS = new Object[0];
 47  
   private final Comparator<String> propertyNameComparator;
 48  222
   private final transient Map<Class<?>, Map<String, PropertyDescriptor>> propertyNameCache = new WeakHashMap<Class<?>, Map<String, PropertyDescriptor>>();
 49  
   private Injector injector;
 50  
 
 51  
   public GuiceBeanProvider(Injector injector) {
 52  222
     this(injector, null);
 53  222
   }
 54  
 
 55  
   public GuiceBeanProvider(Injector injector,
 56  222
       final Comparator<String> propertyNameComparator) {
 57  222
     this.propertyNameComparator = propertyNameComparator;
 58  222
     this.injector = injector;
 59  222
   }
 60  
 
 61  
   public Object newInstance(Class<?> type) {
 62  4
     return injector.getInstance(type);
 63  
   }
 64  
 
 65  
   public void visitSerializableProperties(Object object, Visitor visitor) {
 66  73
     PropertyDescriptor[] propertyDescriptors = getSerializableProperties(object);
 67  1051
     for (int i = 0; i < propertyDescriptors.length; i++) {
 68  978
       PropertyDescriptor property = propertyDescriptors[i];
 69  
       try {
 70  978
         Method readMethod = property.getReadMethod();
 71  978
         String name = property.getName();
 72  978
         Class<?> definedIn = readMethod.getDeclaringClass();
 73  978
         if (visitor.shouldVisit(name, definedIn)) {
 74  962
           Object value = readMethod.invoke(object, new Object[0]);
 75  962
           visitor.visit(name, property.getPropertyType(), definedIn, value);
 76  
         }
 77  0
       } catch (IllegalArgumentException e) {
 78  0
         throw new ObjectAccessException("Could not get property "
 79  
             + object.getClass() + "." + property.getName(), e);
 80  0
       } catch (IllegalAccessException e) {
 81  0
         throw new ObjectAccessException("Could not get property "
 82  
             + object.getClass() + "." + property.getName(), e);
 83  0
       } catch (InvocationTargetException e) {
 84  0
         throw new ObjectAccessException("Could not get property "
 85  
             + object.getClass() + "." + property.getName(), e);
 86  978
       }
 87  
     }
 88  73
   }
 89  
 
 90  
   public void writeProperty(Object object, String propertyName, Object value) {
 91  14
     PropertyDescriptor property = getProperty(propertyName, object.getClass());
 92  
     try {
 93  14
       property.getWriteMethod().invoke(object, new Object[] { value });
 94  0
     } catch (IllegalArgumentException e) {
 95  0
       throw new ObjectAccessException("Could not set property "
 96  
           + object.getClass() + "." + property.getName(), e);
 97  0
     } catch (IllegalAccessException e) {
 98  0
       throw new ObjectAccessException("Could not set property "
 99  
           + object.getClass() + "." + property.getName(), e);
 100  0
     } catch (InvocationTargetException e) {
 101  0
       throw new ObjectAccessException("Could not set property "
 102  
           + object.getClass() + "." + property.getName(), e);
 103  14
     }
 104  14
   }
 105  
 
 106  
   public Class<?> getPropertyType(Object object, String name) {
 107  14
     return getProperty(name, object.getClass()).getPropertyType();
 108  
   }
 109  
 
 110  
   public boolean propertyDefinedInClass(String name, Class<?> type) {
 111  14
     return getProperty(name, type) != null;
 112  
   }
 113  
 
 114  
   private PropertyDescriptor[] getSerializableProperties(Object object) {
 115  73
     Map<String, PropertyDescriptor> nameMap = getNameMap(object.getClass());
 116  73
     List<PropertyDescriptor> result = Lists.newArrayListWithExpectedSize(nameMap.size());
 117  73
     Set<String> names = nameMap.keySet();
 118  73
     if (propertyNameComparator != null) {
 119  0
       Set<String> sortedSet = new TreeSet<String>(propertyNameComparator);
 120  0
       sortedSet.addAll(names);
 121  0
       names = sortedSet;
 122  
     }
 123  73
     for (final String name : names) {
 124  978
       final PropertyDescriptor descriptor = nameMap.get(name);
 125  978
       if (canStreamProperty(descriptor)) {
 126  978
         result.add(descriptor);
 127  
       }
 128  978
     }
 129  73
     return result.toArray(new PropertyDescriptor[result.size()]);
 130  
   }
 131  
 
 132  
   protected boolean canStreamProperty(PropertyDescriptor descriptor) {
 133  978
     return descriptor.getReadMethod() != null
 134  
         && descriptor.getWriteMethod() != null;
 135  
   }
 136  
 
 137  
   public boolean propertyWriteable(String name, Class<?> type) {
 138  0
     PropertyDescriptor property = getProperty(name, type);
 139  0
     return property.getWriteMethod() != null;
 140  
   }
 141  
 
 142  
   private PropertyDescriptor getProperty(String name, Class<?> type) {
 143  42
     return (PropertyDescriptor) getNameMap(type).get(name);
 144  
   }
 145  
 
 146  
   private Map<String, PropertyDescriptor> getNameMap(Class<?> type) {
 147  115
     Map<String, PropertyDescriptor> nameMap = propertyNameCache.get(type);
 148  115
     if (nameMap == null) {
 149  
       BeanInfo beanInfo;
 150  
       try {
 151  37
         beanInfo = Introspector.getBeanInfo(type, Object.class);
 152  0
       } catch (IntrospectionException e) {
 153  0
         throw new ObjectAccessException("Cannot get BeanInfo of type "
 154  
             + type.getName(), e);
 155  37
       }
 156  37
       nameMap = new OrderRetainingMap();
 157  37
       propertyNameCache.put(type, nameMap);
 158  37
       PropertyDescriptor[] propertyDescriptors = beanInfo
 159  
           .getPropertyDescriptors();
 160  696
       for (int i = 0; i < propertyDescriptors.length; i++) {
 161  659
         PropertyDescriptor descriptor = propertyDescriptors[i];
 162  659
         nameMap.put(descriptor.getName(), descriptor);
 163  
       }
 164  
     }
 165  115
     return nameMap;
 166  
   }
 167  
 
 168  
   interface Visitor {
 169  
     boolean shouldVisit(String name, Class<?> definedIn);
 170  
 
 171  
     void visit(String name, Class<?> type, Class<?> definedIn, Object value);
 172  
   }
 173  
 
 174  
 }