src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialStruct.java
changeset 47216 71c04702a3d5
parent 25859 3317bb8137f4
child 51181 01b8120f867a
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package javax.sql.rowset.serial;
       
    27 
       
    28 import java.sql.*;
       
    29 import javax.sql.*;
       
    30 import java.io.*;
       
    31 import java.math.*;
       
    32 import java.util.Arrays;
       
    33 import java.util.Map;
       
    34 import java.util.Vector;
       
    35 
       
    36 import javax.sql.rowset.*;
       
    37 
       
    38 /**
       
    39  * A serialized mapping in the Java programming language of an SQL
       
    40  * structured type. Each attribute that is not already serialized
       
    41  * is mapped to a serialized form, and if an attribute is itself
       
    42  * a structured type, each of its attributes that is not already
       
    43  * serialized is mapped to a serialized form.
       
    44  * <P>
       
    45  * In addition, the structured type is custom mapped to a class in the
       
    46  * Java programming language if there is such a mapping, as are
       
    47  * its attributes, if appropriate.
       
    48  * <P>
       
    49  * The <code>SerialStruct</code> class provides a constructor for creating
       
    50  * an instance from a <code>Struct</code> object, a method for retrieving
       
    51  * the SQL type name of the SQL structured type in the database, and methods
       
    52  * for retrieving its attribute values.
       
    53  *
       
    54  * <h3> Thread safety </h3>
       
    55  *
       
    56  * A SerialStruct is not safe for use by multiple concurrent threads.  If a
       
    57  * SerialStruct is to be used by more than one thread then access to the
       
    58  * SerialStruct should be controlled by appropriate synchronization.
       
    59  *
       
    60  * @since 1.5
       
    61  */
       
    62 public class SerialStruct implements Struct, Serializable, Cloneable {
       
    63 
       
    64 
       
    65     /**
       
    66      * The SQL type name for the structured type that this
       
    67      * <code>SerialStruct</code> object represents.  This is the name
       
    68      * used in the SQL definition of the SQL structured type.
       
    69      *
       
    70      * @serial
       
    71      */
       
    72     private String SQLTypeName;
       
    73 
       
    74     /**
       
    75      * An array of <code>Object</code> instances in  which each
       
    76      * element is an attribute of the SQL structured type that this
       
    77      * <code>SerialStruct</code> object represents.  The attributes are
       
    78      * ordered according to their order in the definition of the
       
    79      * SQL structured type.
       
    80      *
       
    81      * @serial
       
    82      */
       
    83     private Object attribs[];
       
    84 
       
    85     /**
       
    86      * Constructs a <code>SerialStruct</code> object from the given
       
    87      * <code>Struct</code> object, using the given <code>java.util.Map</code>
       
    88      * object for custom mapping the SQL structured type or any of its
       
    89      * attributes that are SQL structured types.
       
    90      *
       
    91      * @param in an instance of {@code Struct}
       
    92      * @param map a <code>java.util.Map</code> object in which
       
    93      *        each entry consists of 1) a <code>String</code> object
       
    94      *        giving the fully qualified name of a UDT and 2) the
       
    95      *        <code>Class</code> object for the <code>SQLData</code> implementation
       
    96      *        that defines how the UDT is to be mapped
       
    97      * @throws SerialException if an error occurs
       
    98      * @see java.sql.Struct
       
    99      */
       
   100      public SerialStruct(Struct in, Map<String,Class<?>> map)
       
   101          throws SerialException
       
   102      {
       
   103 
       
   104         try {
       
   105 
       
   106         // get the type name
       
   107         SQLTypeName = in.getSQLTypeName();
       
   108         System.out.println("SQLTypeName: " + SQLTypeName);
       
   109 
       
   110         // get the attributes of the struct
       
   111         attribs = in.getAttributes(map);
       
   112 
       
   113         /*
       
   114          * the array may contain further Structs
       
   115          * and/or classes that have been mapped,
       
   116          * other types that we have to serialize
       
   117          */
       
   118         mapToSerial(map);
       
   119 
       
   120         } catch (SQLException e) {
       
   121             throw new SerialException(e.getMessage());
       
   122         }
       
   123     }
       
   124 
       
   125      /**
       
   126       * Constructs a <code>SerialStruct</code> object from the
       
   127       * given <code>SQLData</code> object, using the given type
       
   128       * map to custom map it to a class in the Java programming
       
   129       * language.  The type map gives the SQL type and the class
       
   130       * to which it is mapped.  The <code>SQLData</code> object
       
   131       * defines the class to which the SQL type will be mapped.
       
   132       *
       
   133       * @param in an instance of the <code>SQLData</code> class
       
   134       *           that defines the mapping of the SQL structured
       
   135       *           type to one or more objects in the Java programming language
       
   136       * @param map a <code>java.util.Map</code> object in which
       
   137       *        each entry consists of 1) a <code>String</code> object
       
   138       *        giving the fully qualified name of a UDT and 2) the
       
   139       *        <code>Class</code> object for the <code>SQLData</code> implementation
       
   140       *        that defines how the UDT is to be mapped
       
   141       * @throws SerialException if an error occurs
       
   142       */
       
   143     public SerialStruct(SQLData in, Map<String,Class<?>> map)
       
   144         throws SerialException
       
   145     {
       
   146 
       
   147         try {
       
   148 
       
   149         //set the type name
       
   150         SQLTypeName = in.getSQLTypeName();
       
   151 
       
   152         Vector<Object> tmp = new Vector<>();
       
   153         in.writeSQL(new SQLOutputImpl(tmp, map));
       
   154         attribs = tmp.toArray();
       
   155 
       
   156         } catch (SQLException e) {
       
   157             throw new SerialException(e.getMessage());
       
   158         }
       
   159     }
       
   160 
       
   161 
       
   162     /**
       
   163      * Retrieves the SQL type name for this <code>SerialStruct</code>
       
   164      * object. This is the name used in the SQL definition of the
       
   165      * structured type
       
   166      *
       
   167      * @return a <code>String</code> object representing the SQL
       
   168      *         type name for the SQL structured type that this
       
   169      *         <code>SerialStruct</code> object represents
       
   170      * @throws SerialException if an error occurs
       
   171      */
       
   172     public String getSQLTypeName() throws SerialException {
       
   173         return SQLTypeName;
       
   174     }
       
   175 
       
   176     /**
       
   177      * Retrieves an array of <code>Object</code> values containing the
       
   178      * attributes of the SQL structured type that this
       
   179      * <code>SerialStruct</code> object represents.
       
   180      *
       
   181      * @return an array of <code>Object</code> values, with each
       
   182      *         element being an attribute of the SQL structured type
       
   183      *         that this <code>SerialStruct</code> object represents
       
   184      * @throws SerialException if an error occurs
       
   185      */
       
   186     public Object[]  getAttributes() throws SerialException {
       
   187         Object[] val = this.attribs;
       
   188         return (val == null) ? null : Arrays.copyOf(val, val.length);
       
   189     }
       
   190 
       
   191     /**
       
   192      * Retrieves the attributes for the SQL structured type that
       
   193      * this <code>SerialStruct</code> represents as an array of
       
   194      * <code>Object</code> values, using the given type map for
       
   195      * custom mapping if appropriate.
       
   196      *
       
   197      * @param map a <code>java.util.Map</code> object in which
       
   198      *        each entry consists of 1) a <code>String</code> object
       
   199      *        giving the fully qualified name of a UDT and 2) the
       
   200      *        <code>Class</code> object for the <code>SQLData</code> implementation
       
   201      *        that defines how the UDT is to be mapped
       
   202      * @return an array of <code>Object</code> values, with each
       
   203      *         element being an attribute of the SQL structured
       
   204      *         type that this <code>SerialStruct</code> object
       
   205      *         represents
       
   206      * @throws SerialException if an error occurs
       
   207      */
       
   208     public Object[] getAttributes(Map<String,Class<?>> map)
       
   209         throws SerialException
       
   210     {
       
   211         Object[] val = this.attribs;
       
   212         return (val == null) ? null : Arrays.copyOf(val, val.length);
       
   213     }
       
   214 
       
   215 
       
   216     /**
       
   217      * Maps attributes of an SQL structured type that are not
       
   218      * serialized to a serialized form, using the given type map
       
   219      * for custom mapping when appropriate.  The following types
       
   220      * in the Java programming language are mapped to their
       
   221      * serialized forms:  <code>Struct</code>, <code>SQLData</code>,
       
   222      * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>, and
       
   223      * <code>Array</code>.
       
   224      * <P>
       
   225      * This method is called internally and is not used by an
       
   226      * application programmer.
       
   227      *
       
   228      * @param map a <code>java.util.Map</code> object in which
       
   229      *        each entry consists of 1) a <code>String</code> object
       
   230      *        giving the fully qualified name of a UDT and 2) the
       
   231      *        <code>Class</code> object for the <code>SQLData</code> implementation
       
   232      *        that defines how the UDT is to be mapped
       
   233      * @throws SerialException if an error occurs
       
   234      */
       
   235     private void mapToSerial(Map<String,Class<?>> map) throws SerialException {
       
   236 
       
   237         try {
       
   238 
       
   239         for (int i = 0; i < attribs.length; i++) {
       
   240             if (attribs[i] instanceof Struct) {
       
   241                 attribs[i] = new SerialStruct((Struct)attribs[i], map);
       
   242             } else if (attribs[i] instanceof SQLData) {
       
   243                 attribs[i] = new SerialStruct((SQLData)attribs[i], map);
       
   244             } else if (attribs[i] instanceof Blob) {
       
   245                 attribs[i] = new SerialBlob((Blob)attribs[i]);
       
   246             } else if (attribs[i] instanceof Clob) {
       
   247                 attribs[i] = new SerialClob((Clob)attribs[i]);
       
   248             } else if (attribs[i] instanceof Ref) {
       
   249                 attribs[i] = new SerialRef((Ref)attribs[i]);
       
   250             } else if (attribs[i] instanceof java.sql.Array) {
       
   251                 attribs[i] = new SerialArray((java.sql.Array)attribs[i], map);
       
   252             }
       
   253         }
       
   254 
       
   255         } catch (SQLException e) {
       
   256             throw new SerialException(e.getMessage());
       
   257         }
       
   258         return;
       
   259     }
       
   260 
       
   261     /**
       
   262      * Compares this SerialStruct to the specified object.  The result is
       
   263      * {@code true} if and only if the argument is not {@code null} and is a
       
   264      * {@code SerialStruct} object whose attributes are identical to this
       
   265      * object's attributes
       
   266      *
       
   267      * @param  obj The object to compare this {@code SerialStruct} against
       
   268      *
       
   269      * @return {@code true} if the given object represents a {@code SerialStruct}
       
   270      *          equivalent to this SerialStruct, {@code false} otherwise
       
   271      *
       
   272      */
       
   273     public boolean equals(Object obj) {
       
   274         if (this == obj) {
       
   275             return true;
       
   276         }
       
   277         if (obj instanceof SerialStruct) {
       
   278             SerialStruct ss = (SerialStruct)obj;
       
   279             return SQLTypeName.equals(ss.SQLTypeName) &&
       
   280                     Arrays.equals(attribs, ss.attribs);
       
   281         }
       
   282         return false;
       
   283     }
       
   284 
       
   285     /**
       
   286      * Returns a hash code for this {@code SerialStruct}. The hash code for a
       
   287      * {@code SerialStruct} object is computed using the hash codes
       
   288      * of the attributes of the {@code SerialStruct} object and its
       
   289      * {@code SQLTypeName}
       
   290      *
       
   291      * @return  a hash code value for this object.
       
   292      */
       
   293     public int hashCode() {
       
   294         return ((31 + Arrays.hashCode(attribs)) * 31) * 31
       
   295                 + SQLTypeName.hashCode();
       
   296     }
       
   297 
       
   298     /**
       
   299      * Returns a clone of this {@code SerialStruct}. The copy will contain a
       
   300      * reference to a clone of the underlying attribs array, not a reference
       
   301      * to the original underlying attribs array of this {@code SerialStruct} object.
       
   302      *
       
   303      * @return  a clone of this SerialStruct
       
   304      */
       
   305     public Object clone() {
       
   306         try {
       
   307             SerialStruct ss = (SerialStruct) super.clone();
       
   308             ss.attribs = Arrays.copyOf(attribs, attribs.length);
       
   309             return ss;
       
   310         } catch (CloneNotSupportedException ex) {
       
   311             // this shouldn't happen, since we are Cloneable
       
   312             throw new InternalError();
       
   313         }
       
   314 
       
   315     }
       
   316 
       
   317     /**
       
   318      * readObject is called to restore the state of the {@code SerialStruct} from
       
   319      * a stream.
       
   320      */
       
   321     private void readObject(ObjectInputStream s)
       
   322             throws IOException, ClassNotFoundException {
       
   323 
       
   324        ObjectInputStream.GetField fields = s.readFields();
       
   325        Object[] tmp = (Object[])fields.get("attribs", null);
       
   326        attribs = tmp == null ? null : tmp.clone();
       
   327        SQLTypeName = (String)fields.get("SQLTypeName", null);
       
   328     }
       
   329 
       
   330     /**
       
   331      * writeObject is called to save the state of the {@code SerialStruct}
       
   332      * to a stream.
       
   333      */
       
   334     private void writeObject(ObjectOutputStream s)
       
   335             throws IOException, ClassNotFoundException {
       
   336 
       
   337         ObjectOutputStream.PutField fields = s.putFields();
       
   338         fields.put("attribs", attribs);
       
   339         fields.put("SQLTypeName", SQLTypeName);
       
   340         s.writeFields();
       
   341     }
       
   342 
       
   343     /**
       
   344      * The identifier that assists in the serialization of this
       
   345      * <code>SerialStruct</code> object.
       
   346      */
       
   347     static final long serialVersionUID = -8322445504027483372L;
       
   348 }