KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc > bridge > JDBCAbstractCMPFieldBridge


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.cmp.jdbc.bridge;
23
24 import java.lang.reflect.Field JavaDoc;
25
26 import java.sql.PreparedStatement JavaDoc;
27 import java.sql.ResultSet JavaDoc;
28 import java.sql.SQLException JavaDoc;
29
30 import javax.ejb.EJBException JavaDoc;
31
32 import org.jboss.deployment.DeploymentException;
33 import org.jboss.ejb.EntityEnterpriseContext;
34
35 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCCMPFieldMetaData;
36
37 import org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager;
38 import org.jboss.ejb.plugins.cmp.jdbc.JDBCType;
39 import org.jboss.ejb.plugins.cmp.jdbc.CMPFieldStateFactory;
40 import org.jboss.ejb.plugins.cmp.jdbc.JDBCTypeFactory;
41 import org.jboss.ejb.plugins.cmp.jdbc.LockingStrategy;
42 import org.jboss.ejb.plugins.cmp.jdbc.JDBCEntityPersistenceStore;
43 import org.jboss.ejb.plugins.cmp.jdbc.JDBCResultSetReader;
44
45 import org.jboss.logging.Logger;
46
47 /**
48  * JDBCAbstractCMPFieldBridge is the default implementation of
49  * JDBCCMPFieldBridge. Most of the heavy lifting of this command is handled
50  * by JDBCUtil. It is left to subclasses to implement the logic for getting
51  * and setting instance values and dirty checking, as this is dependent on
52  * the CMP version used.
53  *
54  * Life-cycle:
55  * Tied to the EntityBridge.
56  *
57  * Multiplicity:
58  * One for each entity bean cmp field.
59  *
60  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
61  * @author <a HREF="mailto:loubyansky@ua.fm">Alex Loubyansky</a>
62  * @author <a HREF="mailto:heiko.rupp@cellent.de">Heiko W.Rupp</a>
63  * @version $Revision: 38123 $
64  *
65  * <p><b>Revisions:</b>
66  *
67  * <p><b>20021023 Steve Coy:</b>
68  * <ul>
69  * <li>Changed {@link #loadArgumentResults} so that it passes the jdbc type to
70  * </ul>
71  */

72 public abstract class JDBCAbstractCMPFieldBridge implements JDBCCMPFieldBridge
73 {
74    protected final Logger log;
75    protected final JDBCStoreManager manager;
76    private final JDBCType jdbcType;
77    protected final String JavaDoc fieldName;
78    private final Class JavaDoc fieldType;
79    protected final boolean readOnly;
80    protected final long readTimeOut;
81    protected final boolean primaryKeyMember;
82    private final Class JavaDoc primaryKeyClass;
83    private final Field JavaDoc primaryKeyField;
84    protected final int jdbcContextIndex;
85    protected final int tableIndex;
86    protected CMPFieldStateFactory stateFactory;
87    protected boolean checkDirtyAfterGet;
88
89    protected byte defaultFlags = 0;
90
91    private LockingStrategy lockingStrategy = LockingStrategy.NONE;
92
93    public JDBCAbstractCMPFieldBridge(JDBCStoreManager manager,
94                                      JDBCCMPFieldMetaData metadata)
95       throws DeploymentException
96    {
97       this(manager, metadata, manager.getJDBCTypeFactory().getJDBCType(metadata));
98    }
99
100    public JDBCAbstractCMPFieldBridge(JDBCStoreManager manager,
101                                      JDBCCMPFieldMetaData metadata,
102                                      JDBCType jdbcType)
103       throws DeploymentException
104    {
105       this.manager = manager;
106       this.fieldName = metadata.getFieldName();
107       this.fieldType = metadata.getFieldType();
108       this.jdbcType = jdbcType;
109       this.readOnly = metadata.isReadOnly();
110       this.readTimeOut = metadata.getReadTimeOut();
111       this.primaryKeyMember = metadata.isPrimaryKeyMember();
112       this.primaryKeyClass = metadata.getEntity().getPrimaryKeyClass();
113       this.primaryKeyField = metadata.getPrimaryKeyField();
114
115       final JDBCEntityBridge entityBridge = (JDBCEntityBridge)manager.getEntityBridge();
116       this.jdbcContextIndex = entityBridge.getNextJDBCContextIndex();
117
118       if(!metadata.isRelationTableField())
119          tableIndex = entityBridge.addTableField(this);
120       else
121          tableIndex = -1;
122
123       final JDBCTypeFactory typeFactory = manager.getJDBCTypeFactory();
124       stateFactory = JDBCTypeFactory.getCMPFieldStateFactory(
125          typeFactory, metadata.getStateFactory(), fieldType
126       );
127       checkDirtyAfterGet = JDBCTypeFactory.checkDirtyAfterGet(
128          typeFactory, metadata.getCheckDirtyAfterGet(), fieldType
129       );
130
131       this.log = createLogger(manager, fieldName);
132    }
133
134    public JDBCAbstractCMPFieldBridge(JDBCStoreManager manager,
135                                      String JavaDoc fieldName,
136                                      Class JavaDoc fieldType,
137                                      JDBCType jdbcType,
138                                      boolean readOnly,
139                                      long readTimeOut,
140                                      Class JavaDoc primaryKeyClass,
141                                      Field JavaDoc primaryKeyField,
142                                      int jdbcContextIndex,
143                                      int tableIndex,
144                                      boolean checkDirtyAfterGet,
145                                      CMPFieldStateFactory stateFactory)
146    {
147       this.manager = manager;
148       this.fieldName = fieldName;
149       this.fieldType = fieldType;
150       this.jdbcType = jdbcType;
151       this.readOnly = readOnly;
152       this.readTimeOut = readTimeOut;
153       this.primaryKeyMember = false;
154       this.primaryKeyClass = primaryKeyClass;
155       this.primaryKeyField = primaryKeyField;
156       this.jdbcContextIndex = jdbcContextIndex;
157       this.tableIndex = tableIndex;
158       this.stateFactory = stateFactory;
159       this.checkDirtyAfterGet = checkDirtyAfterGet;
160       this.log = createLogger(manager, fieldName);
161    }
162
163    public byte getDefaultFlags()
164    {
165       return defaultFlags;
166    }
167
168    /** get rid of it later */
169    public void addDefaultFlag(byte flag)
170    {
171       defaultFlags |= flag;
172    }
173
174    public JDBCEntityPersistenceStore getManager()
175    {
176       return manager;
177    }
178
179    public String JavaDoc getFieldName()
180    {
181       return fieldName;
182    }
183
184    public JDBCType getJDBCType()
185    {
186       return jdbcType;
187    }
188
189    public Class JavaDoc getFieldType()
190    {
191       return fieldType;
192    }
193
194    public boolean isPrimaryKeyMember()
195    {
196       return primaryKeyMember;
197    }
198
199    public Field JavaDoc getPrimaryKeyField()
200    {
201       return primaryKeyField;
202    }
203
204    public boolean isReadOnly()
205    {
206       return readOnly;
207    }
208
209    public long getReadTimeOut()
210    {
211       return readTimeOut;
212    }
213
214    public Object JavaDoc getValue(EntityEnterpriseContext ctx)
215    {
216       Object JavaDoc value = getInstanceValue(ctx);
217       if(ctx.isValid())
218       {
219          lockingStrategy.accessed(this, ctx);
220          if(checkDirtyAfterGet)
221          {
222             setDirtyAfterGet(ctx);
223          }
224       }
225       return value;
226    }
227
228    public void setValue(EntityEnterpriseContext ctx, Object JavaDoc value)
229    {
230       if(isReadOnly())
231       {
232          throw new EJBException JavaDoc("Field is read-only: fieldName=" + fieldName);
233       }
234       if(primaryKeyMember && JDBCEntityBridge.isEjbCreateDone(ctx))
235       {
236          throw new IllegalStateException JavaDoc("A CMP field that is a member " +
237             "of the primary key can only be set in ejbCreate " +
238             "[EJB 2.0 Spec. 10.3.5].");
239       }
240
241       if(ctx.isValid())
242       {
243          if(!isLoaded(ctx))
244          {
245             // the field must be loaded for dirty cheking to work properly
246
manager.loadField(this, ctx);
247          }
248          lockingStrategy.changed(this, ctx);
249       }
250       setInstanceValue(ctx, value);
251    }
252
253    public Object JavaDoc getPrimaryKeyValue(Object JavaDoc primaryKey)
254       throws IllegalArgumentException JavaDoc
255    {
256       try
257       {
258          if(primaryKeyField != null)
259          {
260             if(primaryKey == null)
261             {
262                return null;
263             }
264
265             // Extract this field's value from the primary key.
266
return primaryKeyField.get(primaryKey);
267          }
268          else
269          {
270             // This field is the primary key, so no extraction is necessary.
271
return primaryKey;
272          }
273       }
274       catch(Exception JavaDoc e)
275       {
276          // Non recoverable internal exception
277
throw new EJBException JavaDoc("Internal error getting primary key " +
278             "field member " + getFieldName(), e);
279       }
280    }
281
282    public Object JavaDoc setPrimaryKeyValue(Object JavaDoc primaryKey, Object JavaDoc value)
283       throws IllegalArgumentException JavaDoc
284    {
285       try
286       {
287          if(primaryKeyField != null)
288          {
289             // if we are tring to set a null value
290
// into a null pk, we are already done.
291
if(value == null && primaryKey == null)
292             {
293                return null;
294             }
295
296             // if we don't have a pk object yet create one
297
if(primaryKey == null)
298             {
299                primaryKey = primaryKeyClass.newInstance();
300             }
301
302             // Set this field's value into the primary key object.
303
primaryKeyField.set(primaryKey, value);
304             return primaryKey;
305          }
306          else
307          {
308             // This field is the primary key, so no extraction is necessary.
309
return value;
310          }
311       }
312       catch(Exception JavaDoc e)
313       {
314          // Non recoverable internal exception
315
throw new EJBException JavaDoc("Internal error setting instance field " +
316             getFieldName(), e);
317       }
318    }
319
320    public abstract void resetPersistenceContext(EntityEnterpriseContext ctx);
321
322    /**
323     * Set CMPFieldValue to Java default value (i.e., 0 or null).
324     */

325    public void initInstance(EntityEnterpriseContext ctx)
326    {
327       if(!readOnly)
328       {
329          Object JavaDoc value;
330          if(fieldType == boolean.class)
331             value = Boolean.FALSE;
332          else if(fieldType == byte.class)
333             value = new Byte JavaDoc((byte)0);
334          else if(fieldType == int.class)
335             value = new Integer JavaDoc(0);
336          else if(fieldType == long.class)
337             value = new Long JavaDoc(0L);
338          else if(fieldType == short.class)
339             value = new Short JavaDoc((short)0);
340          else if(fieldType == char.class)
341             value = new Character JavaDoc('\u0000');
342          else if(fieldType == double.class)
343             value = new Double JavaDoc(0d);
344          else if(fieldType == float.class)
345             value = new Float JavaDoc(0f);
346          else
347             value = null;
348          setInstanceValue(ctx, value);
349       }
350    }
351
352    public int setInstanceParameters(PreparedStatement JavaDoc ps, int parameterIndex, EntityEnterpriseContext ctx)
353    {
354       Object JavaDoc instanceValue = getInstanceValue(ctx);
355       return setArgumentParameters(ps, parameterIndex, instanceValue);
356    }
357
358    public int setPrimaryKeyParameters(PreparedStatement JavaDoc ps, int parameterIndex, Object JavaDoc primaryKey)
359       throws IllegalArgumentException JavaDoc
360    {
361       Object JavaDoc primaryKeyValue = getPrimaryKeyValue(primaryKey);
362       return setArgumentParameters(ps, parameterIndex, primaryKeyValue);
363    }
364
365    public int setArgumentParameters(PreparedStatement JavaDoc ps, int parameterIndex, Object JavaDoc arg)
366    {
367       try
368       {
369          int[] jdbcTypes = jdbcType.getJDBCTypes();
370          for(int i = 0; i < jdbcTypes.length; i++)
371          {
372             Object JavaDoc columnValue = jdbcType.getColumnValue(i, arg);
373             jdbcType.getParameterSetter()[i].set(ps, parameterIndex++, jdbcTypes[i], columnValue, log);
374             //JDBCUtil.setParameter(log, ps, parameterIndex++, jdbcTypes[i], columnValue);
375
}
376          return parameterIndex;
377       }
378       catch(SQLException JavaDoc e)
379       {
380          // Non recoverable internal exception
381
throw new EJBException JavaDoc("Internal error setting parameters for field " + getFieldName(), e);
382       }
383    }
384
385    public int loadInstanceResults(ResultSet JavaDoc rs, int parameterIndex, EntityEnterpriseContext ctx)
386    {
387       try
388       {
389          // value of this field, will be filled in below
390
Object JavaDoc[] argumentRef = new Object JavaDoc[1];
391
392          // load the cmp field value from the result set
393
parameterIndex = loadArgumentResults(rs, parameterIndex, argumentRef);
394
395          // set the value into the context
396
setInstanceValue(ctx, argumentRef[0]);
397
398          lockingStrategy.loaded(this, ctx);
399
400          return parameterIndex;
401       }
402       catch(EJBException JavaDoc e)
403       {
404          // to avoid double wrap of EJBExceptions
405
throw e;
406       }
407       catch(Exception JavaDoc e)
408       {
409          // Non recoverable internal exception
410
throw new EJBException JavaDoc("Internal error getting results for field " + getFieldName(), e);
411       }
412    }
413
414    public int loadPrimaryKeyResults(ResultSet JavaDoc rs, int parameterIndex, Object JavaDoc[] pkRef)
415       throws IllegalArgumentException JavaDoc
416    {
417       // value of this field, will be filled in below
418
Object JavaDoc[] argumentRef = new Object JavaDoc[1];
419
420       parameterIndex = loadArgumentResults(rs, parameterIndex, argumentRef, true);
421
422       // set the value of this field into the pk
423
pkRef[0] = argumentRef[0] == null ? null : setPrimaryKeyValue(pkRef[0], argumentRef[0]);
424
425       // retrun the updated parameterIndex
426
return parameterIndex;
427    }
428
429    public int loadArgumentResults(ResultSet JavaDoc rs, int parameterIndex, Object JavaDoc[] argumentRef)
430       throws IllegalArgumentException JavaDoc
431    {
432       return loadArgumentResults(rs, parameterIndex, argumentRef, false);
433    }
434
435    public boolean isRelationTableField()
436    {
437       return tableIndex < 0;
438    }
439
440    public final int getFieldIndex()
441    {
442       return jdbcContextIndex;
443    }
444
445    public Class JavaDoc getPrimaryKeyClass()
446    {
447       return primaryKeyClass;
448    }
449
450
451    public int getTableIndex()
452    {
453       return tableIndex;
454    }
455
456    public void setLockingStrategy(LockingStrategy lockingStrategy)
457    {
458       this.lockingStrategy = lockingStrategy;
459    }
460
461    protected abstract void setDirtyAfterGet(EntityEnterpriseContext ctx);
462
463    public boolean isCMPField()
464    {
465       return true;
466    }
467
468    private int loadArgumentResults(ResultSet JavaDoc rs, int parameterIndex, Object JavaDoc[] argumentRef, boolean nullColumnNullifiesResult)
469       throws IllegalArgumentException JavaDoc
470    {
471       try
472       {
473          // value of this field, will be filled in below
474
// set the value of this field into the pk
475
argumentRef[0] = null;
476
477          // update the value from the result set
478
Class JavaDoc[] javaTypes = jdbcType.getJavaTypes();
479          JDBCResultSetReader[] rsReaders = jdbcType.getResultSetReaders();
480          for(int i = 0; i < javaTypes.length; i++)
481          {
482             Object JavaDoc columnValue = rsReaders[i].get(rs, parameterIndex++, javaTypes[i], log);
483             if(nullColumnNullifiesResult && columnValue == null)
484             {
485                argumentRef[0] = null;
486                parameterIndex += javaTypes.length - i - 1;
487                break;
488             }
489             argumentRef[0] = jdbcType.setColumnValue(i, argumentRef[0], columnValue);
490          }
491
492          // retrun the updated parameterIndex
493
return parameterIndex;
494       }
495       catch(SQLException JavaDoc e)
496       {
497          // Non recoverable internal exception
498
throw new EJBException JavaDoc("Internal error getting results " +
499             "for field member " + getFieldName(), e);
500       }
501    }
502
503    private Logger createLogger(JDBCStoreManager manager, String JavaDoc fieldName)
504    {
505       return Logger.getLogger(
506          this.getClass().getName() +
507          "." +
508          manager.getMetaData().getName() +
509          "#" +
510          fieldName);
511    }
512 }
513
Popular Tags