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