src.com.ibm.as400.access.DataStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400-jdk8 Show documentation
Show all versions of jt400-jdk8 Show documentation
The Open Source version of the IBM Toolbox for Java
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: DataStream.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2001 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
/** Base class for data streams. Provides methods to access common data stream parts.
*
*/
public abstract class DataStream
{
private static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
protected static ConverterImplRemote converter_; // Character set conversion object.
protected int connectionID_;
static ConverterImplRemote getDefaultConverter()
{
return converter_;
}
static void setDefaultConverter(ConverterImplRemote converter)
{
converter_ = converter;
}
// Read the number of bytes asked for and loop until either that many bytes have been read or until we hit the end of file.
// @param in Inputstream to read from.
// @param buf Where to read the data into.
// @param offset Offset within buf array to start reading into.
// @param length How many bytes to read.
// @param connectionID The connection ID.
// @exception IOException from Inputstream.read() operation.
// @returns Number of bytes read.
static final int readFromStream(InputStream in, byte[] buf, int offset, int length, int connectionID) throws IOException //@P0C
{
boolean endOfFile = false;
int bytesRead = 0;
while ((bytesRead < length) && !endOfFile)
{
int temp = in.read(buf, offset + bytesRead, length - bytesRead);
if (temp == -1)
{
endOfFile = true;
}
else
{
bytesRead += temp;
}
}
if (Trace.traceOn_) Trace.log(Trace.DATASTREAM, "Data stream data received (connID="+connectionID+") ...", buf, offset, bytesRead); //@P0C
return bytesRead;
}
// readFromStreamDebug is used to debugging problems with readFromStream
// left here so that it can be easily reused @A7A
static boolean traceOpened = false;
static final int readFromStreamDebug(InputStream in, byte[] buf, int offset, int length, int connectionID) throws IOException //@P0C
{
long lastReadTime = System.currentTimeMillis();
boolean endOfFile = false;
int bytesRead = 0;
while ((bytesRead < length) && !endOfFile)
{
int availableCount = in.available();
if ( availableCount > 0) {
int temp = in.read(buf, offset + bytesRead, length - bytesRead);
if (temp == -1) {
endOfFile = true;
} else {
bytesRead += temp;
}
lastReadTime = System.currentTimeMillis();
} else {
if (System.currentTimeMillis() > lastReadTime+120000) {
if (! traceOpened) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmm");
Trace.setFileName("/tmp/toolboxTrace."+sdf.format(new Date())+".txt");
traceOpened=true;
}
boolean traceTurnedOn = false;
if (!Trace.traceOn_) {
traceTurnedOn = true;
Trace.setTraceAllOn(true);
Trace.setTraceOn(true);
}
// Trace.log(Trace.DATASTREAM, "Debug0601: Waited more than 120 seconds to read "+length+" bytes. Current buffer with header is ");
// Trace.log(Trace.DATASTREAM, "Debug0601: Data stream data received (connID="+connectionID+") ...", buf, 0, offset + bytesRead); //@P0C
if (traceTurnedOn) {
Trace.setTraceAllOn(false);
Trace.setTraceOn(false);
}
}
try {
Thread.sleep(50);
} catch (Exception e) {
}
}
}
if (Trace.traceOn_) Trace.log(Trace.DATASTREAM, "Data stream data received (connID="+connectionID+") ...", buf, offset, bytesRead); //@P0C
return bytesRead;
}
// Read the number of bytes asked for and loop until either that many bytes have been read or until we hit the end of file.
// @param in Inputstream to read from.
// @param buf Where to read the data into.
// @param offset Offset within buf array to start reading into.
// @param length How many bytes to read.
// @exception IOException from Inputstream.read() operation.
// @returns Number of bytes read.
final int readFromStream(InputStream in, byte[] buf, int offset, int length) throws IOException
{
return readFromStream(in, buf, offset, length, connectionID_);
}
final int readFromStreamDebug(InputStream in, byte[] buf, int offset, int length) throws IOException
{
return readFromStreamDebug(in, buf, offset, length, connectionID_);
}
protected AS400ImplRemote system_;
protected byte[] data_; // Contains complete data stream data.
// Length of the header portion of the data stream. This should be set by sub-classes of this class during construction via calls to super.
protected int headerLength_;
// Constructs a data stream object with data of length headerLength initialized to hex 0's.
// @param headerLength Length of the header for the data stream.
DataStream(int headerLength)
{
// Initialize instance data.
headerLength_ = headerLength;
data_ = new byte[headerLength_];
// Set the total length field of the data stream.
setLength(headerLength_);
}
// Constructs a data stream object with data. It is expected that data is properly formatted for the data stream (header information and remaining data stream information).
// @param headerLength Length of the header for the data stream.
// @param data A byte array to be used for this data stream. The size of the byte array is the number of bytes to be used for this data stream.
DataStream(int headerLength, byte[] data)
{
headerLength_ = headerLength;
data_ = data;
}
// Override Object.equals so that this object is "equal" to another if they are of the same base type and their hash codes are the same.
// @param obj The object with which to compare this object.
// @return true is the objects are equal, false otherwise.
public boolean equals(Object obj)
{
if (obj instanceof DataStream)
{
return (hashCode() == ((DataStream)obj).hashCode());
}
return false;
}
// Retrieve the request/reply correlation for this data stream.
// @return The request correlation number.
abstract int getCorrelation();
// Retrieve the length of the data stream.
// @return The length of the data stream.
abstract int getLength();
// Get a new instance of this class. The code for this method should be provided by the subclasses. In the event that a sub-class does not override this method, null will be returned.
// @return Object representing a clone of this object.
public Object getNewDataStream()
{
return null;
}
// Retrieve the system associated with this object.
// @return Object representing the system.
AS400ImplRemote getSystem()
{
return system_;
}
// Retrieve data from the data stream as a 8-bit number from the specified offset.
// @param offset Offset in the data stream from which to retrieve.
protected final byte get8bit(final int offset) //@P0C
{
//@P0D return BinaryConverter.byteArrayToUnsignedShort(data_, offset);
return (data_[offset]);
}
// Retrieve data from the data stream as a 16-bit number from the specified offset.
// @param offset Offset in the data stream from which to retrieve.
protected final int get16bit(final int offset) //@P0C
{
//@P0D return BinaryConverter.byteArrayToUnsignedShort(data_, offset);
return ((data_[offset] & 0xFF) << 8) + (data_[offset+1] & 0xFF); //@P0A
}
// Retrieve data from the data stream as an int from the specified offset.
// @param offset Offset in the data stream from which to retrieve.
protected final int get32bit(final int offset) //@P0C
{
//@P0D return BinaryConverter.byteArrayToInt(data_, offset);
return ((data_[offset] & 0xFF) << 24) + ((data_[offset+1] & 0xFF) << 16) + ((data_[offset+2] & 0xFF) << 8) + (data_[offset+3] & 0xFF); //@P0A
}
// Retrieve data from the data stream as a long from the specified offset.
// @param offset Offset in the data stream from which to retrieve.
protected final long get64bit(final int offset) //@P0C
{
return BinaryConverter.byteArrayToLong(data_, offset);
}
// Retrieve the hash code for this data stream.
// @return Hash code for this data stream.
public int hashCode()
{
// This method should be overriden in the sub-class.
return super.hashCode();
}
// Read from input stream into this data stream placing the data read into this data stream after the header portion of the data stream.
// @param in InputStream from which to read the data.
// @exception IOException Unable to read from the input stream.
protected int readAfterHeader(InputStream in) throws IOException
{
// int bytesRead = readFromStreamDebug(in, data_, headerLength_, data_.length - headerLength_);
int bytesRead = readFromStream(in, data_, headerLength_, data_.length - headerLength_);
if (bytesRead < data_.length - headerLength_)
{
if (Trace.traceOn_) Trace.log(Trace.ERROR, "Failed to read all of the data stream."); //@P0C
throw new ConnectionDroppedException(ConnectionDroppedException.CONNECTION_DROPPED);
}
return bytesRead;
}
// Set the connection ID associated with this data stream.
// @param connectionID the connection ID.
void setConnectionID(int connectionID)
{
connectionID_ = connectionID;
}
// Set the request correlation for this data stream.
// @param correlation The request correlation number.
abstract void setCorrelation(int correlation);
// Set the length of the data stream. This is the total length of the data stream.
// @param len The length of the data stream.
abstract void setLength(int len);
// Set the system to be associated with this data stream.
// @param system the object representing the system.
void setSystem(AS400ImplRemote system)
{
system_ = system;
}
// Set the 2 bytes at the specified offset to the specified value.
// @param i Value to be set.
// @param offset Offset in the data stream at which to place the value.
protected final void set16bit(int i, int offset) //@P0C
{
//@P0D BinaryConverter.unsignedShortToByteArray(i, data_, offset);
data_[offset] = (byte)(i >>> 8); //@P0A
data_[offset+1] = (byte) i; //@P0A
}
// Set the 4 bytes at the specified offset to the specified value.
// @param i Value to be set.
// @param offset Offset in the data stream at which to place the value.
protected final void set32bit(int i, int offset) //@P0C
{
//@P0D BinaryConverter.intToByteArray(i, data_, offset);
data_[offset] = (byte)(i >>> 24); //@P0A
data_[offset+1] = (byte)(i >>> 16); //@P0A
data_[offset+2] = (byte)(i >>> 8); //@P0A
data_[offset+3] = (byte) i; //@P0A
}
//@RBA
// Set the 4 bytes at the specified offset to the specified value.
// @param i Value to be set.
// @param offset Offset in the data stream at which to place the value.
protected final void set32bit(long i, int offset) //@P0C
{
int bits = (int)i;
data_[offset] = (byte)(bits >>> 24);
data_[offset+1] = (byte)(bits >>> 16);
data_[offset+2] = (byte)(bits >>> 8);
data_[offset+3] = (byte) bits;
}
// Set the 8 bytes at the specified offset to the specified value.
// @param longVal Value to be set.
// @param offset Offset in the data stream at which to place the value.
protected final void set64bit(long longVal, int offset) //@LFS
{
BinaryConverter.longToByteArray(longVal, data_, offset);
}
// Write the data in this data stream out to the specified OutputStream.
// @param out OutputStream to which to write the data.
// @exception IOException Unable to write to the output stream.
void write(OutputStream out) throws IOException
{
// Synchronization is added around the socket write so that requests from multiple threads that use the same socket won't be garbled.
synchronized(out)
{
out.write(data_);
out.flush();
}
if (Trace.traceOn_) Trace.log(Trace.DATASTREAM, "Data stream sent (connID="+connectionID_+") ...", data_); //@P0C
}
}