001/* 002 * Copyright 2013 Christopher Pheby 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.jadira.reflection.access.portable; 017 018import java.lang.reflect.Field; 019import java.lang.reflect.Method; 020import java.util.concurrent.ConcurrentHashMap; 021 022import org.jadira.reflection.access.AbstractClassAccess; 023import org.jadira.reflection.access.api.ClassAccess; 024import org.jadira.reflection.access.api.FieldAccess; 025import org.jadira.reflection.access.api.MethodAccess; 026import org.objenesis.Objenesis; 027import org.objenesis.ObjenesisStd; 028 029/** 030 * ClassAccess implementation which should be portable across most JVMs. 031 * Uses Reflection to access methods, and Objenesis to invoke constructors. 032 * @param <C> The Class to be accessed 033 */ 034public class PortableClassAccess<C> extends AbstractClassAccess<C> implements ClassAccess<C> { 035 036 private static final ConcurrentHashMap<Class<?>, PortableClassAccess<?>> CLASS_ACCESSES = new ConcurrentHashMap<Class<?>, PortableClassAccess<?>>(); 037 038 private static final Objenesis OBJENESIS = new ObjenesisStd(); 039 040 private PortableClassAccess(Class<C> clazz) { 041 super(clazz); 042 } 043 044 @Override 045 public C newInstance() { 046 return (C) OBJENESIS.newInstance(getType()); 047 } 048 049 /** 050 * Get a new instance that can access the given Class. If the ClassAccess for this class 051 * has not been obtained before, then the specific PortableClassAccess is created by generating 052 * a specialised subclass of this class and returning it. 053 * @param clazz Class to be accessed 054 * @param <C> The type of class 055 * @return New PortableClassAccess instance 056 */ 057 public static <C> PortableClassAccess<C> get(Class<C> clazz) { 058 059 @SuppressWarnings("unchecked") 060 PortableClassAccess<C> access = (PortableClassAccess<C>) CLASS_ACCESSES.get(clazz); 061 if (access != null) { 062 return access; 063 } 064 access = new PortableClassAccess<C>(clazz); 065 CLASS_ACCESSES.putIfAbsent(clazz, access); 066 return access; 067 } 068 069 @Override 070 protected MethodAccess<C> constructMethodAccess(Method method) { 071 return PortableMethodAccess.get(method); 072 } 073 074 @Override 075 protected FieldAccess<C> constructFieldAccess(Field field) { 076 return PortableFieldAccess.get(field); 077 } 078 079 @Override 080 protected <X> ClassAccess<X> constructClassAccess(Class<X> clazz) { 081 return PortableClassAccess.get(clazz); 082 } 083}