001 package org.apache.ojb.broker.metadata.fieldaccess;
002
003 /* Copyright 2002-2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 import java.io.Serializable;
019
020 import org.apache.ojb.broker.metadata.MetadataException;
021 import org.apache.ojb.broker.util.ClassHelper;
022
023 /**
024 * PeristentField implementation that attempts to detect the nature of
025 * the field it is persisting.
026 * <p>
027 * First checks to see if it is a Field, then Property, then DynaBean
028 * <p>
029 * It will match in that order.
030 */
031 public class PersistentFieldAutoProxyImpl extends PersistentFieldBase
032 {
033 static final long serialVersionUID = 6286229945422476325L;
034
035 /**
036 * Define the number and ordering of the used {@link PersistentField}
037 * implementaions. Override this field to add new classes or to change
038 * setection order.
039 */
040 protected Class[] persistentFieldClasses = new Class[]{
041 PersistentFieldDirectImpl.class
042 , PersistentFieldIntrospectorImpl.class
043 , PersistentFieldPrivilegedImpl.class
044 , PersistentFieldDynaBeanImpl.class};
045
046 private PersistentField currentPF;
047 private ExceptionWrapper latestException;
048 int index = 0;
049
050 public PersistentFieldAutoProxyImpl()
051 {
052 }
053
054 public PersistentFieldAutoProxyImpl(Class clazz, String fieldname)
055 {
056 super(clazz, fieldname);
057 }
058
059 private PersistentField getCurrent()
060 {
061 if (currentPF == null)
062 {
063 if(index >= persistentFieldClasses.length)
064 {
065 index = 0;
066 currentPF = null;
067 throw new AutoDetectException("Can't autodetect valid PersistentField implementation: "
068 + latestException.message, latestException.exception);
069 }
070 try
071 {
072 currentPF = createPersistentFieldForIndex();
073 }
074 catch (Exception e)
075 {
076 throw new AutoDetectException("Can't create instance for " + persistentFieldClasses[index], e);
077 }
078 }
079 return currentPF;
080 }
081
082 private void handleException(String message, Exception e)
083 {
084 latestException = new ExceptionWrapper(message, e);
085 currentPF = null;
086 ++index;
087 }
088
089
090 public Object get(Object anObject) throws MetadataException
091 {
092 try
093 {
094 return getCurrent().get(anObject);
095 }
096 catch (Exception e)
097 {
098 if(e instanceof AutoDetectException)
099 {
100 throw (MetadataException) e;
101 }
102 else
103 {
104 handleException("Can't extract field value for field " + getName()
105 + " from object " + (anObject != null ? anObject.getClass() : null), e);
106 return get(anObject);
107 }
108 }
109 }
110
111 public void set(Object obj, Object value) throws MetadataException
112 {
113 try
114 {
115 getCurrent().set(obj, value);
116 }
117 catch (Exception e)
118 {
119 if(e instanceof AutoDetectException)
120 {
121 throw (MetadataException) e;
122 }
123 else
124 {
125 handleException("Can't set value for field " + getName()
126 + " to object " + (obj != null ? obj.getClass() : null), e);
127 set(obj, value);
128 }
129 }
130 }
131
132 public Class getType()
133 {
134 try
135 {
136 return getCurrent().getType();
137 }
138 catch (Exception e)
139 {
140 if(e instanceof AutoDetectException)
141 {
142 throw (MetadataException) e;
143 }
144 else
145 {
146 handleException("Can't identify field type for field " + getName(), null);
147 return getType();
148 }
149 }
150 }
151
152 protected boolean makeAccessible()
153 {
154 return false;
155 }
156
157 public boolean usesAccessorsAndMutators()
158 {
159 return false;
160 }
161
162 private PersistentField createPersistentFieldForIndex() throws Exception
163 {
164 return newInstance(persistentFieldClasses[index]);
165 }
166
167 private PersistentField newInstance(Class pfClass) throws Exception
168 {
169 Class[] types = new Class[]{Class.class, String.class};
170 Object[] args = new Object[]{getDeclaringClass(), getName()};
171 return (PersistentField) ClassHelper.newInstance(pfClass, types, args);
172 }
173
174 static class ExceptionWrapper implements Serializable
175 {
176 private static final long serialVersionUID = 3691042088451912249L;
177 Exception exception;
178 String message;
179
180 public ExceptionWrapper(String message, Exception exception)
181 {
182 this.message = message;
183 this.exception = exception;
184 }
185 }
186
187 static class AutoDetectException extends MetadataException
188 {
189 private static final long serialVersionUID = 3257290223049585970L;
190
191 public AutoDetectException()
192 {
193 super();
194 }
195
196 public AutoDetectException(Throwable t)
197 {
198 super(t);
199 }
200
201 public AutoDetectException(String message)
202 {
203 super(message);
204 }
205
206 public AutoDetectException(String message, Throwable t)
207 {
208 super(message, t);
209 }
210 }
211 }