1 22 23 24 package com.mchange.v2.naming; 25 26 import java.beans.*; 27 import java.io.*; 28 import java.util.*; 29 import javax.naming.*; 30 import com.mchange.v2.log.*; 31 import java.lang.reflect.Method ; 32 import com.mchange.v2.lang.Coerce; 33 import com.mchange.v2.beans.BeansUtils; 34 import com.mchange.v2.ser.SerializableUtils; 35 import com.mchange.v2.ser.IndirectPolicy; 36 37 public class JavaBeanReferenceMaker implements ReferenceMaker 38 { 39 private final static MLogger logger = MLog.getLogger( JavaBeanReferenceMaker.class ); 40 41 final static String REF_PROPS_KEY = "com.mchange.v2.naming.JavaBeanReferenceMaker.REF_PROPS_KEY"; 42 43 final static Object [] EMPTY_ARGS = new Object [0]; 44 45 final static byte[] NULL_TOKEN_BYTES = new byte[0]; 46 47 String factoryClassName = "com.mchange.v2.naming.JavaBeanObjectFactory"; 48 String defaultFactoryClassLocation = null; 49 50 Set referenceProperties = new HashSet(); 51 52 ReferenceIndirector indirector = new ReferenceIndirector(); 53 54 public Hashtable getEnvironmentProperties() 55 { return indirector.getEnvironmentProperties(); } 56 57 public void setEnvironmentProperties( Hashtable environmentProperties ) 58 { indirector.setEnvironmentProperties( environmentProperties ); } 59 60 public void setFactoryClassName(String factoryClassName) 61 { this.factoryClassName = factoryClassName; } 62 63 public String getFactoryClassName() 64 { return factoryClassName; } 65 66 public String getDefaultFactoryClassLocation() 67 { return defaultFactoryClassLocation; } 68 69 public void setDefaultFactoryClassLocation( String defaultFactoryClassLocation ) 70 { this.defaultFactoryClassLocation = defaultFactoryClassLocation; } 71 72 public void addReferenceProperty( String propName ) 73 { referenceProperties.add( propName ); } 74 75 public void removeReferenceProperty( String propName ) 76 { referenceProperties.remove( propName ); } 77 78 public Reference createReference( Object bean ) 79 throws NamingException 80 { 81 try 82 { 83 BeanInfo bi = Introspector.getBeanInfo( bean.getClass() ); 84 PropertyDescriptor[] pds = bi.getPropertyDescriptors(); 85 List refAddrs = new ArrayList(); 86 String factoryClassLocation = defaultFactoryClassLocation; 87 88 boolean using_ref_props = referenceProperties.size() > 0; 89 90 if (using_ref_props) 92 refAddrs.add( new BinaryRefAddr( REF_PROPS_KEY, SerializableUtils.toByteArray( referenceProperties ) ) ); 93 94 for (int i = 0, len = pds.length; i < len; ++i) 95 { 96 PropertyDescriptor pd = pds[i]; 97 String propertyName = pd.getName(); 98 100 if (using_ref_props && ! referenceProperties.contains( propertyName )) 101 { 102 continue; 104 } 105 106 Class propertyType = pd.getPropertyType(); 107 Method getter = pd.getReadMethod(); 108 Method setter = pd.getWriteMethod(); 109 if (getter != null && setter != null) { 111 Object val = getter.invoke( bean, EMPTY_ARGS ); 112 if (propertyName.equals("factoryClassLocation")) 114 { 115 if (String .class != propertyType) 116 throw new NamingException(this.getClass().getName() + " requires a factoryClassLocation property to be a string, " + 117 propertyType.getName() + " is not valid."); 118 factoryClassLocation = (String ) val; 119 } 120 121 if (val == null) 122 { 123 RefAddr addMe = new BinaryRefAddr( propertyName, NULL_TOKEN_BYTES ); 124 refAddrs.add( addMe ); 125 } 126 else if ( Coerce.canCoerce( propertyType ) ) 127 { 128 RefAddr addMe = new StringRefAddr( propertyName, String.valueOf( val ) ); 129 refAddrs.add( addMe ); 130 } 131 else { 133 RefAddr addMe = null; 134 PropertyEditor pe = BeansUtils.findPropertyEditor( pd ); 135 if (pe != null) 136 { 137 pe.setValue( val ); 138 String textValue = pe.getAsText(); 139 if (textValue != null) 140 addMe = new StringRefAddr( propertyName, textValue ); 141 } 142 if (addMe == null) addMe = new BinaryRefAddr( propertyName, SerializableUtils.toByteArray( val, 144 indirector, 145 IndirectPolicy.INDIRECT_ON_EXCEPTION ) ); 146 refAddrs.add( addMe ); 147 } 148 } 149 else 150 { 151 154 if ( logger.isLoggable( MLevel.WARNING ) ) 155 logger.warning(this.getClass().getName() + ": Skipping " + propertyName + 156 " because it is " + (setter == null ? "read-only." : "write-only.")); 157 } 158 159 } 160 Reference out = new Reference( bean.getClass().getName(), factoryClassName, factoryClassLocation ); 161 for (Iterator ii = refAddrs.iterator(); ii.hasNext(); ) 162 out.add( (RefAddr) ii.next() ); 163 return out; 164 } 165 catch ( Exception e ) 166 { 167 if ( Debug.DEBUG && logger.isLoggable( MLevel.FINE ) ) 169 logger.log( MLevel.FINE, "Exception trying to create Reference.", e); 170 171 throw new NamingException("Could not create reference from bean: " + e.toString() ); 172 } 173 } 174 175 } 176 177 | Popular Tags |