001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.eclipselink; 023 024import java.lang.reflect.Field; 025import java.lang.reflect.Modifier; 026import java.util.ArrayList; 027import java.util.List; 028 029import javax.persistence.Entity; 030 031import org.granite.logging.Logger; 032import org.granite.messaging.amf.io.util.DefaultClassGetter; 033import org.granite.eclipselink.EclipseLinkClassGetter; 034import org.granite.eclipselink.EclipseLinkProxy; 035import org.granite.util.TypeUtil; 036 037import org.eclipse.persistence.indirection.IndirectContainer; 038import org.eclipse.persistence.indirection.ValueHolderInterface; 039 040/** 041 * @author William DRAI 042 */ 043public class EclipseLinkClassGetter extends DefaultClassGetter { 044 045 private final static Logger log = Logger.getLogger(EclipseLinkClassGetter.class); 046 047 @Override 048 public Class<?> getClass(Object o) { 049 050 if (o instanceof ValueHolderInterface) { 051 ValueHolderInterface holder = (ValueHolderInterface)o; 052 053 String className = ( 054 holder.isInstantiated() ? 055 holder.getValue().getClass().getName() : 056 Object.class.getName() 057 ); 058 059 if (className != null && className.length() > 0) { 060 try { 061 return TypeUtil.forName(className); 062 } catch (Exception e) { 063 log.warn(e, "Could not get class with initializer: %s for: %s", className, className); 064 } 065 } 066 // fallback... 067 return Object.class; 068 } 069 else if (o instanceof EclipseLinkProxy) { 070 return ((EclipseLinkProxy)o).getProxiedClass(); 071 } 072 073 return super.getClass(o); 074 } 075 076 @Override 077 public boolean isEntity(Object o) { 078 return o.getClass().isAnnotationPresent(Entity.class); 079 } 080 081 @Override 082 public boolean isInitialized(Object owner, String propertyName, Object propertyValue) { 083 Object value = propertyValue; 084 if (owner != null) { 085 Field vhf = null; 086 Class<?> c = owner.getClass(); 087 while (c != null && c != Object.class) { 088 for (Field f : c.getDeclaredFields()) { 089 if (f.getName().equals("_persistence_" + propertyName + "_vh")) { 090 vhf = f; 091 break; 092 } 093 } 094 if (vhf != null) 095 break; 096 c = c.getSuperclass(); 097 } 098 if (vhf != null) { 099 try { 100 vhf.setAccessible(true); 101 value = vhf.get(owner); 102 } 103 catch (Exception e) { 104 log.error(e, "Could not get persistence ValueHolder " + propertyName + " for class " + owner.getClass()); 105 } 106 } 107 } 108 if (value instanceof ValueHolderInterface) 109 return ((ValueHolderInterface)value).isInstantiated(); 110 else if (value instanceof IndirectContainer) 111 return ((IndirectContainer)value).isInstantiated(); 112 113 return true; 114 } 115 116 @Override 117 public void initialize(Object owner, String propertyName, Object propertyValue) { 118 if (propertyValue instanceof ValueHolderInterface) 119 ((ValueHolderInterface)propertyValue).getValue().toString(); 120 else if (propertyValue instanceof IndirectContainer) 121 ((IndirectContainer)propertyValue).getValueHolder().getValue().toString(); 122 } 123 124 @Override 125 public List<Object 126 []> getFieldValues(Object obj, Object dest) { 127 List<Object[]> fieldValues = new ArrayList<Object[]>(); 128 129 List<String> topLinkVhs = new ArrayList<String>(); 130 131 // Merges field values 132 try { 133 Class<?> clazz = obj.getClass(); 134 while (clazz != null) { 135 Field[] fields = clazz.getDeclaredFields(); 136 for (Field field : fields) { 137 if ((field.getModifiers() & Modifier.STATIC) != 0 138 || (field.getModifiers() & Modifier.FINAL) != 0 139 || (field.getModifiers() & Modifier.VOLATILE) != 0 140 || (field.getModifiers() & Modifier.NATIVE) != 0 141 || (field.getModifiers() & Modifier.TRANSIENT) != 0) 142 continue; 143 144 if (ValueHolderInterface.class.isAssignableFrom(field.getType())) { 145 field.setAccessible(true); 146 ValueHolderInterface vh = (ValueHolderInterface)field.get(obj); 147 if (!vh.isInstantiated()) { 148 topLinkVhs.add(field.getName()); 149 field.set(dest, vh); 150 } 151 } 152 else if (!topLinkVhs.contains("_persistence_" + field.getName() + "_vh")) { 153 field.setAccessible(true); 154 Object o = field.get(obj); 155 if (dest != null) { 156 Object d = field.get(dest); 157 fieldValues.add(new Object[] { field, o, d }); 158 } 159 else 160 fieldValues.add(new Object[] { field, o }); 161 } 162 } 163 clazz = clazz.getSuperclass(); 164 } 165 } 166 catch (Exception e) { 167 throw new RuntimeException("Could not merge entity ", e); 168 } 169 170 return fieldValues; 171 } 172}