001 /*
002 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.sql.rowset.serial;
027
028 import java.sql.*;
029 import java.io.*;
030 import java.util.Map;
031 import java.net.URL;
032
033 /**
034 * A serialized version of an <code>Array</code>
035 * object, which is the mapping in the Java programming language of an SQL
036 * <code>ARRAY</code> value.
037 * <P>
038 * The <code>SerialArray</code> class provides a constructor for creating
039 * a <code>SerialArray</code> instance from an <code>Array</code> object,
040 * methods for getting the base type and the SQL name for the base type, and
041 * methods for copying all or part of a <code>SerialArray</code> object.
042 * <P>
043 * Note: In order for this class to function correctly, a connection to the
044 * data source
045 * must be available in order for the SQL <code>Array</code> object to be
046 * materialized (have all of its elements brought to the client server)
047 * if necessary. At this time, logical pointers to the data in the data source,
048 * such as locators, are not currently supported.
049 */
050 public class SerialArray implements Array, Serializable, Cloneable {
051
052 /**
053 * A serialized array in which each element is an <code>Object</code>
054 * in the Java programming language that represents an element
055 * in the SQL <code>ARRAY</code> value.
056 * @serial
057 */
058 private Object[] elements;
059
060 /**
061 * The SQL type of the elements in this <code>SerialArray</code> object. The
062 * type is expressed as one of the constants from the class
063 * <code>java.sql.Types</code>.
064 * @serial
065 */
066 private int baseType;
067
068 /**
069 * The type name used by the DBMS for the elements in the SQL <code>ARRAY</code>
070 * value that this <code>SerialArray</code> object represents.
071 * @serial
072 */
073 private String baseTypeName;
074
075 /**
076 * The number of elements in this <code>SerialArray</code> object, which
077 * is also the number of elements in the SQL <code>ARRAY</code> value
078 * that this <code>SerialArray</code> object represents.
079 * @serial
080 */
081 private int len;
082
083 /**
084 * Constructs a new <code>SerialArray</code> object from the given
085 * <code>Array</code> object, using the given type map for the custom
086 * mapping of each element when the elements are SQL UDTs.
087 * <P>
088 * This method does custom mapping if the array elements are a UDT
089 * and the given type map has an entry for that UDT.
090 * Custom mapping is recursive,
091 * meaning that if, for instance, an element of an SQL structured type
092 * is an SQL structured type that itself has an element that is an SQL
093 * structured type, each structured type that has a custom mapping will be
094 * mapped according to the given type map.
095 * <P>
096 * The new <code>SerialArray</code>
097 * object contains the same elements as the <code>Array</code> object
098 * from which it is built, except when the base type is the SQL type
099 * <code>STRUCT</code>, <code>ARRAY</code>, <code>BLOB</code>,
100 * <code>CLOB</code>, <code>DATALINK</code> or <code>JAVA_OBJECT</code>.
101 * In this case, each element in the new
102 * <code>SerialArray</code> object is the appropriate serialized form,
103 * that is, a <code>SerialStruct</code>, <code>SerialArray</code>,
104 * <code>SerialBlob</code>, <code>SerialClob</code>,
105 * <code>SerialDatalink</code>, or <code>SerialJavaObject</code> object.
106 * <P>
107 * Note: (1) The <code>Array</code> object from which a <code>SerialArray</code>
108 * object is created must have materialized the SQL <code>ARRAY</code> value's
109 * data on the client before it is passed to the constructor. Otherwise,
110 * the new <code>SerialArray</code> object will contain no data.
111 * <p>
112 * Note: (2) If the <code>Array</code> contains <code>java.sql.Types.JAVA_OBJECT</code>
113 * types, the <code>SerialJavaObject</code> constructor is called where checks
114 * are made to ensure this object is serializable.
115 * <p>
116 * Note: (3) The <code>Array</code> object supplied to this constructor cannot
117 * return <code>null</code> for any <code>Array.getArray()</code> methods.
118 * <code>SerialArray</code> cannot serialize null array values.
119 *
120 *
121 * @param array the <code>Array</code> object to be serialized
122 * @param map a <code>java.util.Map</code> object in which
123 * each entry consists of 1) a <code>String</code> object
124 * giving the fully qualified name of a UDT (an SQL structured type or
125 * distinct type) and 2) the
126 * <code>Class</code> object for the <code>SQLData</code> implementation
127 * that defines how the UDT is to be mapped. The <i>map</i>
128 * parameter does not have any effect for <code>Blob</code>,
129 * <code>Clob</code>, <code>DATALINK</code>, or
130 * <code>JAVA_OBJECT</code> types.
131 * @throws SerialException if an error occurs serializing the
132 * <code>Array</code> object
133 * @throws SQLException if a database access error occurs or if the
134 * <i>array</i> or the <i>map</i> values are <code>null</code>
135 */
136 public SerialArray(Array array, Map<String, Class<?>> map)
137 throws SerialException, SQLException {
138
139 if ((array == null) || (map == null)) {
140 throw new SQLException("Cannot instantiate a SerialArray "
141 + "object with null parameters");
142 }
143
144 if ((elements = (Object[]) array.getArray()) == null) {
145 throw new SQLException(
146 "Invalid Array object. Calls to Array.getArray() "
147 + "return null value which cannot be serialized");
148 }
149
150 elements = (Object[]) array.getArray(map);
151 baseType = array.getBaseType();
152 baseTypeName = array.getBaseTypeName();
153 len = elements.length;
154
155 switch (baseType) {
156 case java.sql.Types.STRUCT:
157 for (int i = 0; i < len; i++) {
158 elements[i] = new SerialStruct((Struct) elements[i],
159 map);
160 }
161 break;
162
163 case java.sql.Types.ARRAY:
164 for (int i = 0; i < len; i++) {
165 elements[i] = new SerialArray((Array) elements[i], map);
166 }
167 break;
168
169 case java.sql.Types.BLOB:
170 for (int i = 0; i < len; i++) {
171 elements[i] = new SerialBlob((Blob) elements[i]);
172 }
173 break;
174
175 case java.sql.Types.CLOB:
176 for (int i = 0; i < len; i++) {
177 elements[i] = new SerialClob((Clob) elements[i]);
178 }
179 break;
180
181 case java.sql.Types.DATALINK:
182 for (int i = 0; i < len; i++) {
183 elements[i] = new SerialDatalink((URL) elements[i]);
184 }
185 break;
186
187 case java.sql.Types.JAVA_OBJECT:
188 for (int i = 0; i < len; i++) {
189 elements[i] = new SerialJavaObject((Object) elements[i]);
190 }
191 default:
192 ;
193 }
194 }
195
196 /**
197 * This method frees the <code>Array</code> object and releases the resources that
198 * it holds. The object is invalid once the <code>free</code>
199 * method is called.
200 *<p>
201 * After <code>free</code> has been called, any attempt to invoke a
202 * method other than <code>free</code> will result in a <code>SQLException</code>
203 * being thrown. If <code>free</code> is called multiple times, the subsequent
204 * calls to <code>free</code> are treated as a no-op.
205 *<p>
206 *
207 * @throws SQLException if an error occurs releasing
208 * the Array's resources
209 * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
210 * this method
211 * @since 1.6
212 */
213 public void free() throws SQLException {
214 throw new SQLFeatureNotSupportedException(
215 "Feature not supported");
216 }
217
218 /**
219 * Constructs a new <code>SerialArray</code> object from the given
220 * <code>Array</code> object.
221 * <P>
222 * This constructor does not do custom mapping. If the base type of the array
223 * is an SQL structured type and custom mapping is desired, the constructor
224 * <code>SerialArray(Array array, Map map)</code> should be used.
225 * <P>
226 * The new <code>SerialArray</code>
227 * object contains the same elements as the <code>Array</code> object
228 * from which it is built, except when the base type is the SQL type
229 * <code>BLOB</code>,
230 * <code>CLOB</code>, <code>DATALINK</code> or <code>JAVA_OBJECT</code>.
231 * In this case, each element in the new
232 * <code>SerialArray</code> object is the appropriate serialized form,
233 * that is, a <code>SerialBlob</code>, <code>SerialClob</code>,
234 * <code>SerialDatalink</code>, or <code>SerialJavaObject</code> object.
235 * <P>
236 * Note: (1) The <code>Array</code> object from which a <code>SerialArray</code>
237 * object is created must have materialized the SQL <code>ARRAY</code> value's
238 * data on the client before it is passed to the constructor. Otherwise,
239 * the new <code>SerialArray</code> object will contain no data.
240 * <p>
241 * Note: (2) The <code>Array</code> object supplied to this constructor cannot
242 * return <code>null</code> for any <code>Array.getArray()</code> methods.
243 * <code>SerialArray</code> cannot serialize <code>null</code> array values.
244 *
245 * @param array the <code>Array</code> object to be serialized
246 * @throws SerialException if an error occurs serializing the
247 * <code>Array</code> object
248 * @throws SQLException if a database access error occurs or the
249 * <i>array</i> parameter is <code>null</code>.
250 */
251 public SerialArray(Array array) throws SerialException,
252 SQLException {
253 if (array == null) {
254 throw new SQLException("Cannot instantiate a SerialArray "
255 + "object with a null Array object");
256 }
257
258 if ((elements = (Object[]) array.getArray()) == null) {
259 throw new SQLException(
260 "Invalid Array object. Calls to Array.getArray() "
261 + "return null value which cannot be serialized");
262 }
263
264 //elements = (Object[])array.getArray();
265 baseType = array.getBaseType();
266 baseTypeName = array.getBaseTypeName();
267 len = elements.length;
268
269 switch (baseType) {
270
271 case java.sql.Types.BLOB:
272 for (int i = 0; i < len; i++) {
273 elements[i] = new SerialBlob((Blob) elements[i]);
274 }
275 break;
276
277 case java.sql.Types.CLOB:
278 for (int i = 0; i < len; i++) {
279 elements[i] = new SerialClob((Clob) elements[i]);
280 }
281 break;
282
283 case java.sql.Types.DATALINK:
284 for (int i = 0; i < len; i++) {
285 elements[i] = new SerialDatalink((URL) elements[i]);
286 }
287 break;
288
289 case java.sql.Types.JAVA_OBJECT:
290 for (int i = 0; i < len; i++) {
291 elements[i] = new SerialJavaObject((Object) elements[i]);
292 }
293
294 default:
295 ;
296 }
297
298 }
299
300 /**
301 * Returns a new array that is a copy of this <code>SerialArray</code>
302 * object.
303 *
304 * @return a copy of this <code>SerialArray</code> object as an
305 * <code>Object</code> in the Java programming language
306 * @throws SerialException if an error occurs retrieving a copy of
307 * this <code>SerialArray</code> object
308 */
309 public Object getArray() throws SerialException {
310 Object dst = new Object[len];
311 System.arraycopy((Object) elements, 0, dst, 0, len);
312 return dst;
313 }
314
315 //[if an error occurstype map used??]
316 /**
317 * Returns a new array that is a copy of this <code>SerialArray</code>
318 * object, using the given type map for the custom
319 * mapping of each element when the elements are SQL UDTs.
320 * <P>
321 * This method does custom mapping if the array elements are a UDT
322 * and the given type map has an entry for that UDT.
323 * Custom mapping is recursive,
324 * meaning that if, for instance, an element of an SQL structured type
325 * is an SQL structured type that itself has an element that is an SQL
326 * structured type, each structured type that has a custom mapping will be
327 * mapped according to the given type map.
328 *
329 * @param map a <code>java.util.Map</code> object in which
330 * each entry consists of 1) a <code>String</code> object
331 * giving the fully qualified name of a UDT and 2) the
332 * <code>Class</code> object for the <code>SQLData</code> implementation
333 * that defines how the UDT is to be mapped
334 * @return a copy of this <code>SerialArray</code> object as an
335 * <code>Object</code> in the Java programming language
336 * @throws SerialException if an error occurs
337 */
338 public Object getArray(Map<String, Class<?>> map)
339 throws SerialException {
340 Object dst[] = new Object[len];
341 System.arraycopy((Object) elements, 0, dst, 0, len);
342 return dst;
343 }
344
345 /**
346 * Returns a new array that is a copy of a slice
347 * of this <code>SerialArray</code> object, starting with the
348 * element at the given index and containing the given number
349 * of consecutive elements.
350 *
351 * @param index the index into this <code>SerialArray</code> object
352 * of the first element to be copied;
353 * the index of the first element is <code>0</code>
354 * @param count the number of consecutive elements to be copied, starting
355 * at the given index
356 * @return a copy of the designated elements in this <code>SerialArray</code>
357 * object as an <code>Object</code> in the Java programming language
358 * @throws SerialException if an error occurs
359 */
360 public Object getArray(long index, int count)
361 throws SerialException {
362 Object dst = new Object[count];
363 System.arraycopy((Object) elements, (int) index, dst, 0, count);
364 return dst;
365 }
366
367 /**
368 * Returns a new array that is a copy of a slice
369 * of this <code>SerialArray</code> object, starting with the
370 * element at the given index and containing the given number
371 * of consecutive elements.
372 * <P>
373 * This method does custom mapping if the array elements are a UDT
374 * and the given type map has an entry for that UDT.
375 * Custom mapping is recursive,
376 * meaning that if, for instance, an element of an SQL structured type
377 * is an SQL structured type that itself has an element that is an SQL
378 * structured type, each structured type that has a custom mapping will be
379 * mapped according to the given type map.
380 *
381 * @param index the index into this <code>SerialArray</code> object
382 * of the first element to be copied; the index of the
383 * first element in the array is <code>0</code>
384 * @param count the number of consecutive elements to be copied, starting
385 * at the given index
386 * @param map a <code>java.util.Map</code> object in which
387 * each entry consists of 1) a <code>String</code> object
388 * giving the fully qualified name of a UDT and 2) the
389 * <code>Class</code> object for the <code>SQLData</code> implementation
390 * that defines how the UDT is to be mapped
391 * @return a copy of the designated elements in this <code>SerialArray</code>
392 * object as an <code>Object</code> in the Java programming language
393 * @throws SerialException if an error occurs
394 */
395 public Object getArray(long index, int count,
396 Map<String, Class<?>> map) throws SerialException {
397 Object dst = new Object[count];
398 System.arraycopy((Object) elements, (int) index, dst, 0, count);
399 return dst;
400 }
401
402 /**
403 * Retrieves the SQL type of the elements in this <code>SerialArray</code>
404 * object. The <code>int</code> returned is one of the constants in the class
405 * <code>java.sql.Types</code>.
406 *
407 * @return one of the constants in <code>java.sql.Types</code>, indicating
408 * the SQL type of the elements in this <code>SerialArray</code> object
409 * @throws SerialException if an error occurs
410 */
411 public int getBaseType() throws SerialException {
412 return baseType;
413 }
414
415 /**
416 * Retrieves the DBMS-specific type name for the elements in this
417 * <code>SerialArray</code> object.
418 *
419 * @return the SQL type name used by the DBMS for the base type of this
420 * <code>SerialArray</code> object
421 * @throws SerialException if an error occurs
422 */
423 public String getBaseTypeName() throws SerialException {
424 return baseTypeName;
425 }
426
427 /**
428 * Retrieves a <code>ResultSet</code> object holding the elements of
429 * the subarray that starts at
430 * index <i>index</i> and contains up to <i>count</i> successive elements.
431 * This method uses the connection's type map to map the elements of
432 * the array if the map contains
433 * an entry for the base type. Otherwise, the standard mapping is used.
434 *
435 * @param index the index into this <code>SerialArray</code> object
436 * of the first element to be copied; the index of the
437 * first element in the array is <code>0</code>
438 * @param count the number of consecutive elements to be copied, starting
439 * at the given index
440 * @return a <code>ResultSet</code> object containing the designated
441 * elements in this <code>SerialArray</code> object, with a
442 * separate row for each element
443 * @throws SerialException, which in turn throws an
444 * <code>UnsupportedOperationException</code>, if this method is called
445 */
446 public ResultSet getResultSet(long index, int count)
447 throws SerialException {
448 throw new UnsupportedOperationException();
449 }
450
451 /**
452 *
453 * Retrieves a <code>ResultSet</code> object that contains all of
454 * the elements of the SQL <code>ARRAY</code>
455 * value represented by this <code>SerialArray</code> object. This method uses
456 * the specified map for type map customizations unless the base type of the
457 * array does not match a user-defined type (UDT) in <i>map</i>, in
458 * which case it uses the
459 * standard mapping. This version of the method <code>getResultSet</code>
460 * uses either the given type map or the standard mapping; it never uses the
461 * type map associated with the connection.
462 *
463 * @param map a <code>java.util.Map</code> object in which
464 * each entry consists of 1) a <code>String</code> object
465 * giving the fully qualified name of a UDT and 2) the
466 * <code>Class</code> object for the <code>SQLData</code> implementation
467 * that defines how the UDT is to be mapped
468 * @return a <code>ResultSet</code> object containing all of the
469 * elements in this <code>SerialArray</code> object, with a
470 * separate row for each element
471 * @throws SerialException, which in turn throws an
472 * <code>UnsupportedOperationException</code>, if this method is called
473 */
474 public ResultSet getResultSet(Map<String, Class<?>> map)
475 throws SerialException {
476 throw new UnsupportedOperationException();
477 }
478
479 /**
480 * Retrieves a <code>ResultSet</code> object that contains all of
481 * the elements in the <code>ARRAY</code> value that this
482 * <code>SerialArray</code> object represents.
483 * If appropriate, the elements of the array are mapped using the connection's
484 * type map; otherwise, the standard mapping is used.
485 *
486 * @return a <code>ResultSet</code> object containing all of the
487 * elements in this <code>SerialArray</code> object, with a
488 * separate row for each element
489 * @throws SerialException if called, which in turn throws an
490 * <code>UnsupportedOperationException</code>, if this method is called
491 */
492 public ResultSet getResultSet() throws SerialException {
493 throw new UnsupportedOperationException();
494 }
495
496 /**
497 * Retrieves a result set holding the elements of the subarray that starts at
498 * Retrieves a <code>ResultSet</code> object that contains a subarray of the
499 * elements in this <code>SerialArray</code> object, starting at
500 * index <i>index</i> and containing up to <i>count</i> successive
501 * elements. This method uses
502 * the specified map for type map customizations unless the base type of the
503 * array does not match a user-defined type (UDT) in <i>map</i>, in
504 * which case it uses the
505 * standard mapping. This version of the method <code>getResultSet</code> uses
506 * either the given type map or the standard mapping; it never uses the type
507 * map associated with the connection.
508 *
509 * @param index the index into this <code>SerialArray</code> object
510 * of the first element to be copied; the index of the
511 * first element in the array is <code>0</code>
512 * @param count the number of consecutive elements to be copied, starting
513 * at the given index
514 * @param map a <code>java.util.Map</code> object in which
515 * each entry consists of 1) a <code>String</code> object
516 * giving the fully qualified name of a UDT and 2) the
517 * <code>Class</code> object for the <code>SQLData</code> implementation
518 * that defines how the UDT is to be mapped
519 * @return a <code>ResultSet</code> object containing the designated
520 * elements in this <code>SerialArray</code> object, with a
521 * separate row for each element
522 * @throws SerialException if called, which in turn throws an
523 * <code>UnsupportedOperationException</code>
524 */
525 public ResultSet getResultSet(long index, int count,
526 Map<String, Class<?>> map) throws SerialException {
527 throw new UnsupportedOperationException();
528 }
529
530 /**
531 * The identifier that assists in the serialization of this <code>SerialArray</code>
532 * object.
533 */
534 static final long serialVersionUID = -8466174297270688520L;
535 }
|