1 4 package org.h2.value; 5 6 import java.io.BufferedInputStream ; 7 import java.io.BufferedOutputStream ; 8 import java.io.DataInputStream ; 9 import java.io.DataOutputStream ; 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.io.OutputStreamWriter ; 13 import java.io.Reader ; 14 import java.io.Writer ; 15 import java.math.BigDecimal ; 16 import java.net.Socket ; 17 import java.sql.Date ; 18 import java.sql.ResultSet ; 19 import java.sql.ResultSetMetaData ; 20 import java.sql.SQLException ; 21 import java.sql.Time ; 22 import java.sql.Timestamp ; 23 24 import org.h2.engine.Constants; 25 import org.h2.engine.SessionInterface; 26 import org.h2.message.Message; 27 import org.h2.message.TraceSystem; 28 import org.h2.tools.SimpleResultSet; 29 import org.h2.util.ExactUTF8InputStreamReader; 30 import org.h2.util.IOUtils; 31 import org.h2.util.StringCache; 32 33 36 public class Transfer { 37 38 private static final int BUFFER_SIZE = 16 * 1024; 39 private static final int LOB_MAGIC = 0x1234; 40 41 protected Socket socket; 42 protected DataInputStream in; 43 protected DataOutputStream out; 44 private Exception stackTrace = new Exception (); 45 private SessionInterface session; 46 47 public Transfer(SessionInterface session) { 48 this.session = session; 49 } 50 51 protected void finalize() { 52 if (!Constants.RUN_FINALIZERS) { 53 return; 54 } 55 if(socket != null) { 56 throw Message.getInternalError("not closed", stackTrace); 57 } 58 } 59 60 public void setSocket(Socket s) { 61 socket = s; 62 } 63 64 public void init() throws IOException { 65 in = new DataInputStream (new BufferedInputStream (socket.getInputStream(), Transfer.BUFFER_SIZE)); 66 out = new DataOutputStream (new BufferedOutputStream (socket.getOutputStream(), Transfer.BUFFER_SIZE)); 67 } 68 69 public void flush() throws IOException { 70 out.flush(); 71 } 72 73 public Transfer writeBoolean(boolean x) throws IOException { 74 out.writeByte((byte)(x ? 1 : 0)); 75 return this; 76 } 77 78 public boolean readBoolean() throws IOException { 79 return in.readByte() == 1; 80 } 81 82 public Transfer writeByte(byte x) throws IOException { 83 out.writeByte(x); 84 return this; 85 } 86 87 public byte readByte() throws IOException { 88 return in.readByte(); 89 } 90 91 public Transfer writeInt(int i) throws IOException { 92 out.writeInt(i); 93 return this; 94 } 95 96 public int readInt() throws IOException { 97 return in.readInt(); 98 } 99 100 public Transfer writeLong(long i) throws IOException { 101 out.writeLong(i); 102 return this; 103 } 104 105 public long readLong() throws IOException { 106 return in.readLong(); 107 } 108 109 public Transfer writeDouble(double i) throws IOException { 110 out.writeDouble(i); 111 return this; 112 } 113 114 public Transfer writeFloat(float i) throws IOException { 115 out.writeFloat(i); 116 return this; 117 } 118 119 public double readDouble() throws IOException { 120 return in.readDouble(); 121 } 122 123 public float readFloat() throws IOException { 124 return in.readFloat(); 125 } 126 127 public Transfer writeString(String s) throws IOException { 128 if (s == null) { 129 out.writeInt(-1); 130 } else { 131 int len = s.length(); 132 out.writeInt(len); 133 for(int i=0; i<len; i++) { 134 out.writeChar(s.charAt(i)); 135 } 136 } 137 return this; 138 } 139 140 public String readString() throws IOException { 141 int len = in.readInt(); 142 if (len == -1) { 143 return null; 144 } 145 StringBuffer buff = new StringBuffer (len); 147 for(int i=0; i<len; i++) { 148 buff.append(in.readChar()); 149 } 150 String s = buff.toString(); 151 s = StringCache.get(s); 152 return s; 153 } 154 155 public Transfer writeBytes(byte[] data) throws IOException { 156 if(data == null) { 157 writeInt(-1); 158 } else { 159 writeInt(data.length); 160 out.write(data); 161 } 162 return this; 163 } 164 165 public byte[] readBytes() throws IOException { 166 int len = readInt(); 167 if(len == -1) { 168 return null; 169 } 170 byte[] b = new byte[len]; 171 in.readFully(b); 172 return b; 173 } 174 175 public void close() { 176 if(socket != null) { 177 try { 178 out.flush(); 179 if(socket != null) { 180 socket.close(); 181 } 182 } catch(IOException e) { 183 TraceSystem.traceThrowable(e); 184 } finally { 185 socket = null; 186 } 187 } 188 } 189 190 public void writeValue(Value v) throws IOException , SQLException { 191 int type = v.getType(); 192 writeInt(type); 193 switch(type) { 194 case Value.NULL: 195 break; 196 case Value.BYTES: 197 case Value.JAVA_OBJECT: 198 writeBytes(v.getBytesNoCopy()); 199 break; 200 case Value.UUID: { 201 ValueUuid uuid = (ValueUuid) v; 202 writeLong(uuid.getHigh()); 203 writeLong(uuid.getLow()); 204 break; 205 } 206 case Value.BOOLEAN: 207 writeBoolean(v.getBoolean().booleanValue()); 208 break; 209 case Value.BYTE: 210 writeByte(v.getByte()); 211 break; 212 case Value.TIME: 213 writeLong(v.getTimeNoCopy().getTime()); 214 break; 215 case Value.DATE: 216 writeLong(v.getDateNoCopy().getTime()); 217 break; 218 case Value.TIMESTAMP: { 219 Timestamp ts = v.getTimestampNoCopy(); 220 writeLong(ts.getTime()); 221 writeInt(ts.getNanos()); 222 break; 223 } 224 case Value.DECIMAL: 225 writeString(v.getString()); 226 break; 227 case Value.DOUBLE: 228 writeDouble(v.getDouble()); 229 break; 230 case Value.FLOAT: 231 writeFloat(v.getFloat()); 232 break; 233 case Value.INT: 234 writeInt(v.getInt()); 235 break; 236 case Value.LONG: 237 writeLong(v.getLong()); 238 break; 239 case Value.SHORT: 240 writeInt(v.getShort()); 241 break; 242 case Value.STRING: 243 case Value.STRING_IGNORECASE: 244 writeString(v.getString()); 245 break; 246 case Value.BLOB: { 247 long length = v.getPrecision(); 248 if(Constants.CHECK && length < 0) { 249 throw Message.getInternalError("length: " + length); 250 } 251 writeLong(length); 252 InputStream in = v.getInputStream(); 253 long written = IOUtils.copyAndCloseInput(in, out); 254 if(Constants.CHECK && written != length) { 255 throw Message.getInternalError("length:" + length + " written:" + written); 256 } 257 writeInt(LOB_MAGIC); 258 break; 259 } 260 case Value.CLOB: { 261 long length = v.getPrecision(); 262 if(Constants.CHECK && length < 0) { 263 throw Message.getInternalError("length: " + length); 264 } 265 writeLong(length); 266 Reader reader = v.getReader(); 267 Writer writer = new OutputStreamWriter (out, Constants.UTF8); 268 long written = IOUtils.copyAndCloseInput(reader, writer); 269 if(Constants.CHECK && written != length) { 270 throw Message.getInternalError("length:" + length + " written:" + written); 271 } 272 writer.flush(); 273 writeInt(LOB_MAGIC); 274 break; 275 } 276 case Value.ARRAY: { 277 Value[] list = ((ValueArray)v).getList(); 278 writeInt(list.length); 279 for(int i=0; i<list.length; i++) { 280 writeValue(list[i]); 281 } 282 break; 283 } 284 case Value.RESULT_SET: { 285 ResultSet rs = ((ValueResultSet)v).getResultSet(); 286 rs.beforeFirst(); 287 ResultSetMetaData meta = rs.getMetaData(); 288 int columnCount = meta.getColumnCount(); 289 writeInt(columnCount); 290 for(int i=0; i<columnCount; i++) { 291 writeString(meta.getColumnName(i + 1)); 292 writeInt(meta.getColumnType(i + 1)); 293 writeInt(meta.getPrecision(i + 1)); 294 writeInt(meta.getScale(i + 1)); 295 } 296 while(rs.next()) { 297 writeBoolean(true); 298 for(int i=0; i<columnCount; i++) { 299 int t = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1)); 300 Value val = DataType.readValue(session, rs, i+1, t); 301 writeValue(val); 302 } 303 } 304 writeBoolean(false); 305 rs.beforeFirst(); 306 break; 307 } 308 default: 309 throw Message.getInternalError("type="+type); 310 } 311 } 312 313 public Value readValue() throws IOException , SQLException { 314 int type = readInt(); 315 switch(type) { 316 case Value.NULL: 317 return ValueNull.INSTANCE; 318 case Value.BYTES: 319 return ValueBytes.getNoCopy(readBytes()); 320 case Value.UUID: 321 return ValueUuid.get(readLong(), readLong()); 322 case Value.JAVA_OBJECT: 323 return ValueJavaObject.getNoCopy(readBytes()); 324 case Value.BOOLEAN: 325 return ValueBoolean.get(readBoolean()); 326 case Value.BYTE: 327 return ValueByte.get(readByte()); 328 case Value.DATE: 329 return ValueDate.getNoCopy(new Date (readLong())); 330 case Value.TIME: 331 return ValueTime.getNoCopy(new Time (readLong())); 332 case Value.TIMESTAMP: { 333 Timestamp ts = new Timestamp (readLong()); 334 ts.setNanos(readInt()); 335 return ValueTimestamp.getNoCopy(ts); 336 } 337 case Value.DECIMAL: 338 return ValueDecimal.get(new BigDecimal (readString())); 339 case Value.DOUBLE: 340 return ValueDouble.get(readDouble()); 341 case Value.FLOAT: 342 return ValueFloat.get(readFloat()); 343 case Value.INT: 344 return ValueInt.get(readInt()); 345 case Value.LONG: 346 return ValueLong.get(readLong()); 347 case Value.SHORT: 348 return ValueShort.get((short)readInt()); 349 case Value.STRING: 350 return ValueString.get(readString()); 351 case Value.STRING_IGNORECASE: 352 return ValueStringIgnoreCase.get(readString()); 353 case Value.BLOB: { 354 long length = readLong(); 355 ValueLob v = ValueLob.createBlob(in, length, session.getDataHandler()); 356 if(readInt() != LOB_MAGIC) { 357 throw Message.getSQLException(Message.CONNECTION_BROKEN); 358 } 359 return v; 360 } 361 case Value.CLOB: { 362 long length = readLong(); 363 ValueLob v = ValueLob.createClob(new ExactUTF8InputStreamReader(in), length, session.getDataHandler()); 364 if(readInt() != LOB_MAGIC) { 365 throw Message.getSQLException(Message.CONNECTION_BROKEN); 366 } 367 return v; 368 } 369 case Value.ARRAY: { 370 int len = readInt(); 371 Value[] list = new Value[len]; 372 for(int i=0; i<len; i++) { 373 list[i] = readValue(); 374 } 375 return ValueArray.get(list); 376 } 377 case Value.RESULT_SET: { 378 SimpleResultSet rs = new SimpleResultSet(); 379 int columns = readInt(); 380 for(int i=0; i<columns; i++) { 381 rs.addColumn(readString(), readInt(), readInt(), readInt()); 382 } 383 while(true) { 384 if(!readBoolean()) { 385 break; 386 } 387 Object [] o = new Object [columns]; 388 for(int i=0; i<columns; i++) { 389 o[i] = readValue().getObject(); 390 } 391 rs.addRow(o); 392 } 393 return ValueResultSet.get(rs); 394 } 395 default: 396 throw Message.getInternalError("type="+type); 397 } 398 } 399 400 public Socket getSocket() { 401 return socket; 402 } 403 404 public void setSession(SessionInterface session) { 405 this.session = session; 406 } 407 408 } 409 | Popular Tags |