1 /* 2 * Copyright (c) 2003, 2014, 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 java.io.*; 30 import java.util.*; 31 32 /** 33 * A serialized mapping of a <code>Ref</code> object, which is the mapping in the 34 * Java programming language of an SQL <code>REF</code> value. 35 * <p> 36 * The <code>SerialRef</code> class provides a constructor for 37 * creating a <code>SerialRef</code> instance from a <code>Ref</code> 38 * object and provides methods for getting and setting the <code>Ref</code> object. 39 * 40 * <h3> Thread safety </h3> 41 * 42 * A SerialRef is not safe for use by multiple concurrent threads. If a 43 * SerialRef is to be used by more than one thread then access to the SerialRef 44 * should be controlled by appropriate synchronization. 45 * 46 * @since 1.5 47 */ 48 public class SerialRef implements Ref, Serializable, Cloneable { 49 50 /** 51 * String containing the base type name. 52 * @serial 53 */ 54 private String baseTypeName; 55 56 /** 57 * This will store the type <code>Ref</code> as an <code>Object</code>. 58 */ 59 private Object object; 60 61 /** 62 * Private copy of the Ref reference. 63 */ 64 private Ref reference; 65 66 /** 67 * Constructs a <code>SerialRef</code> object from the given <code>Ref</code> 68 * object. 69 * 70 * @param ref a Ref object; cannot be <code>null</code> 71 * @throws SQLException if a database access occurs; if <code>ref</code> 72 * is <code>null</code>; or if the <code>Ref</code> object returns a 73 * <code>null</code> value base type name. 74 * @throws SerialException if an error occurs serializing the <code>Ref</code> 75 * object 76 */ 77 public SerialRef(Ref ref) throws SerialException, SQLException { 78 if (ref == null) { 79 throw new SQLException("Cannot instantiate a SerialRef object " + 80 "with a null Ref object"); 81 } 82 reference = ref; 83 object = ref; 84 if (ref.getBaseTypeName() == null) { 85 throw new SQLException("Cannot instantiate a SerialRef object " + 86 "that returns a null base type name"); 87 } else { 88 baseTypeName = ref.getBaseTypeName(); 89 } 90 } 91 92 /** 93 * Returns a string describing the base type name of the <code>Ref</code>. 94 * 95 * @return a string of the base type name of the Ref 96 * @throws SerialException in no Ref object has been set 97 */ 98 public String getBaseTypeName() throws SerialException { 99 return baseTypeName; 100 } 101 102 /** 103 * Returns an <code>Object</code> representing the SQL structured type 104 * to which this <code>SerialRef</code> object refers. The attributes 105 * of the structured type are mapped according to the given type map. 106 * 107 * @param map a <code>java.util.Map</code> object containing zero or 108 * more entries, with each entry consisting of 1) a <code>String</code> 109 * giving the fully qualified name of a UDT and 2) the 110 * <code>Class</code> object for the <code>SQLData</code> implementation 111 * that defines how the UDT is to be mapped 112 * @return an object instance resolved from the Ref reference and mapped 113 * according to the supplied type map 114 * @throws SerialException if an error is encountered in the reference 115 * resolution 116 */ 117 public Object getObject(java.util.Map<String,Class<?>> map) 118 throws SerialException 119 { 120 map = new Hashtable<String, Class<?>>(map); 121 if (object != null) { 122 return map.get(object); 123 } else { 124 throw new SerialException("The object is not set"); 125 } 126 } 127 128 /** 129 * Returns an <code>Object</code> representing the SQL structured type 130 * to which this <code>SerialRef</code> object refers. 131 * 132 * @return an object instance resolved from the Ref reference 133 * @throws SerialException if an error is encountered in the reference 134 * resolution 135 */ 136 public Object getObject() throws SerialException { 137 138 if (reference != null) { 139 try { 140 return reference.getObject(); 141 } catch (SQLException e) { 142 throw new SerialException("SQLException: " + e.getMessage()); 143 } 144 } 145 146 if (object != null) { 147 return object; 148 } 149 150 151 throw new SerialException("The object is not set"); 152 153 } 154 155 /** 156 * Sets the SQL structured type that this <code>SerialRef</code> object 157 * references to the given <code>Object</code> object. 158 * 159 * @param obj an <code>Object</code> representing the SQL structured type 160 * to be referenced 161 * @throws SerialException if an error is encountered generating the 162 * the structured type referenced by this <code>SerialRef</code> object 163 */ 164 public void setObject(Object obj) throws SerialException { 165 try { 166 reference.setObject(obj); 167 } catch (SQLException e) { 168 throw new SerialException("SQLException: " + e.getMessage()); 169 } 170 object = obj; 171 } 172 173 /** 174 * Compares this SerialRef to the specified object. The result is {@code 175 * true} if and only if the argument is not {@code null} and is a {@code 176 * SerialRef} object that represents the same object as this 177 * object. 178 * 179 * @param obj The object to compare this {@code SerialRef} against 180 * 181 * @return {@code true} if the given object represents a {@code SerialRef} 182 * equivalent to this SerialRef, {@code false} otherwise 183 * 184 */ 185 public boolean equals(Object obj) { 186 if (this == obj) { 187 return true; 188 } 189 if(obj instanceof SerialRef) { 190 SerialRef ref = (SerialRef)obj; 191 return baseTypeName.equals(ref.baseTypeName) && 192 object.equals(ref.object); 193 } 194 return false; 195 } 196 197 /** 198 * Returns a hash code for this {@code SerialRef}. 199 * @return a hash code value for this object. 200 */ 201 public int hashCode() { 202 return (31 + object.hashCode()) * 31 + baseTypeName.hashCode(); 203 } 204 205 /** 206 * Returns a clone of this {@code SerialRef}. 207 * The underlying {@code Ref} object will be set to null. 208 * 209 * @return a clone of this SerialRef 210 */ 211 public Object clone() { 212 try { 213 SerialRef ref = (SerialRef) super.clone(); 214 ref.reference = null; 215 return ref; 216 } catch (CloneNotSupportedException ex) { 217 // this shouldn't happen, since we are Cloneable 218 throw new InternalError(); 219 } 220 221 } 222 223 /** 224 * readObject is called to restore the state of the SerialRef from 225 * a stream. 226 */ 227 private void readObject(ObjectInputStream s) 228 throws IOException, ClassNotFoundException { 229 ObjectInputStream.GetField fields = s.readFields(); 230 object = fields.get("object", null); 231 baseTypeName = (String) fields.get("baseTypeName", null); 232 reference = (Ref) fields.get("reference", null); 233 } 234 235 /** 236 * writeObject is called to save the state of the SerialRef 237 * to a stream. 238 */ 239 private void writeObject(ObjectOutputStream s) 240 throws IOException, ClassNotFoundException { 241 242 ObjectOutputStream.PutField fields = s.putFields(); 243 fields.put("baseTypeName", baseTypeName); 244 fields.put("object", object); 245 // Note: this check to see if it is an instance of Serializable 246 // is for backwards compatibility 247 fields.put("reference", reference instanceof Serializable ? reference : null); 248 s.writeFields(); 249 } 250 251 /** 252 * The identifier that assists in the serialization of this <code>SerialRef</code> 253 * object. 254 */ 255 static final long serialVersionUID = -4727123500609662274L; 256 257 258 }