com.ibm.as400.access.PrintObjectInputStreamImplRemote Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400 Show documentation
Show all versions of jt400 Show documentation
The Open Source version of the IBM Toolbox for Java
The newest version!
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: PrintObjectInputStreamImplRemote.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-2000 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.io.IOException;
/**
* The PrintObjectInputStream class is used to read data out of a
* server spooled file or AFP resource such as an overlay or page
* segment.
**/
class PrintObjectInputStreamImplRemote
implements PrintObjectInputStreamImpl
{
private static final String copyright = "Copyright (C) 1997-2000 International Business Machines Corporation and others.";
private NPConversation conversation_;
private NPCodePoint cpObjHndl_; // Spooled File handle or Resource Handle code point
private NPCPID cpObjID_; // spooled file or resource ID codepoint
private NPCPAttribute cpCPFMsg_;
private int markLimit_ = 0; // limit of mark/reset
private boolean markSet_ = false; // has a mark been set?
private NPSystem npSystem_;
private int numBytes_ = 0; // total size in splf or resource in bytes
private int objectType_;
private int offset_ = 0; // offset from beginning of file in bytes
private int offsetFromMark_ = 0; // offset from mark
/**
* Constructs a PrintObjectInputStream object. It uses the
* specified SpooledFile object from which to read and the PrintParameterList.
* @exception AS400Exception If the server system returns an error message.
* @exception AS400SecurityException If a security or authority error occurs.
* @exception ErrorCompletingRequestException If an error occurs before the request is completed.
* @exception IOException If an error occurs while communicating with the server.
* @exception InterruptedException If this thread is interrupted.
* @exception RequestNotSupportedException If the requested function is not supported because the server
* operating system is not at the correct level.
**/
public synchronized void createPrintObjectInputStream(SpooledFileImpl sf,
PrintParameterList openOptions)
throws AS400Exception,
AS400SecurityException,
ErrorCompletingRequestException,
IOException,
InterruptedException,
RequestNotSupportedException
{
objectType_ = NPConstants.SPOOLED_FILE;
NPDataStream openReq = new NPDataStream(objectType_);
NPDataStream openRep = new NPDataStream(objectType_);
npSystem_ = NPSystem.getSystem(((SpooledFileImplRemote) sf).getSystem());
cpCPFMsg_ = new NPCPAttribute();
cpObjID_ = ((SpooledFileImplRemote) sf).getIDCodePoint();
cpObjHndl_ = new NPCPSplFHandle();
// setup the request data stream
openReq.setAction(NPDataStream.OPEN);
openReq.addCodePoint(cpObjID_);
// for opening spooled files we need to send up a selection code point
// with the attribute of PRECOMPUTE NUMBER OF BYTES set to YES
NPCPSelection selectionCP = new NPCPSelection();
// first set any options the user has passed in
if (openOptions != null)
{
selectionCP.addUpdateAttributes(openOptions.getAttrCodePoint());
}
// then set the precompute size to *YES.
selectionCP.setAttrValue(PrintObject.ATTR_PRECOMPUTE_NUMBYTES, "*YES");
// add the selection codepoint to the open request datastream
openReq.addCodePoint(selectionCP);
// setup the reply datastream
openRep.addCodePoint(cpObjHndl_);
openRep.addCodePoint(cpCPFMsg_);
// try to open the spooled file
conversation_ = npSystem_.getConversation();
boolean fOpenOK = false;
try
{
int rc = conversation_.makeRequest(openReq, openRep);
if (rc != NPDataStream.RET_OK)
{
Trace.log(Trace.ERROR, "Error opening SpooledFile; rc = " + rc);
throw new ErrorCompletingRequestException(ErrorCompletingRequestException.AS400_ERROR);
} else {
// try to get the number of bytes in the spooled file
// it will throw an exception if there is any error
retrieveNumberOfBytes();
fOpenOK = true; //we opened the spooled file
}
}
finally
{
// if we got here because an exception was thrown
if (!fOpenOK)
{
if (npSystem_ != null) {
npSystem_.returnConversation(conversation_);
}
conversation_ = null;
}
}
}
/**
* Constructs a PrintObjectInputStream object. It uses the
* specified SpooledFile object from which to read, the PrintParameterList
* and a hidden attribute ATTR_ACIF to indicate a ACIF merge file process
* should be used.
* @exception AS400Exception If the server system returns an error message.
* @exception AS400SecurityException If a security or authority error occurs.
* @exception ErrorCompletingRequestException If an error occurs before the request is completed.
* @exception IOException If an error occurs while communicating with the server.
* @exception InterruptedException If this thread is interrupted.
* @exception RequestNotSupportedException If the requested function is not supported because the server
* operating system is not at the correct level.
**/
public synchronized void createPrintObjectInputStream(SpooledFileImpl sf,
PrintParameterList openOptions, String acifP)
throws AS400Exception,
AS400SecurityException,
ErrorCompletingRequestException,
IOException,
InterruptedException,
RequestNotSupportedException
{
objectType_ = NPConstants.SPOOLED_FILE;
NPDataStream openReq = new NPDataStream(objectType_);
NPDataStream openRep = new NPDataStream(objectType_);
npSystem_ = NPSystem.getSystem(((SpooledFileImplRemote) sf).getSystem());
cpCPFMsg_ = new NPCPAttribute();
cpObjID_ = ((SpooledFileImplRemote) sf).getIDCodePoint();
cpObjHndl_ = new NPCPSplFHandle();
// setup the request data stream
openReq.setAction(NPDataStream.OPEN);
openReq.addCodePoint(cpObjID_);
// for opening spooled files we need to send up a selection code point
// with the attribute of PRECOMPUTE NUMBER OF BYTES set to YES
NPCPSelection selectionCP = new NPCPSelection();
selectionCP.setAttrValue(PrintObject.ATTR_ACIF, acifP);
// first set any options the user has passed in
if (openOptions != null)
{
selectionCP.addUpdateAttributes(openOptions.getAttrCodePoint());
}
// then set the precompute size to *YES.
selectionCP.setAttrValue(PrintObject.ATTR_PRECOMPUTE_NUMBYTES, "*YES");
// add the selection codepoint to the open request datastream
openReq.addCodePoint(selectionCP);
// setup the reply datastream
openRep.addCodePoint(cpObjHndl_);
openRep.addCodePoint(cpCPFMsg_);
// try to open the spooled file
conversation_ = npSystem_.getConversation();
boolean fOpenOK = false;
try
{
int rc = conversation_.makeRequest(openReq, openRep);
if (rc != NPDataStream.RET_OK)
{
Trace.log(Trace.ERROR, "Error opening SpooledFile; rc = " + rc);
throw new ErrorCompletingRequestException(ErrorCompletingRequestException.AS400_ERROR);
} else {
// try to get the number of bytes in the spooled file
// it will throw an exception if there is any error
retrieveNumberOfBytes();
fOpenOK = true; //we opened the spooled file
}
}
finally
{
// if we got here because an exception was thrown
if (!fOpenOK)
{
if (npSystem_ != null) {
npSystem_.returnConversation(conversation_);
}
conversation_ = null;
}
}
}
/**
* Contructs a PrintObjectInputStream object.
* It uses the specified AFP Resource object from which to read and
* the PrintParameterList.
* @exception AS400Exception If the server system returns an error message.
* @exception AS400SecurityException If a security or authority error occurs.
* @exception ErrorCompletingRequestException If an error occurs before the request is completed.
* @exception IOException If an error occurs while communicating with the server.
* @exception InterruptedException If this thread is interrupted.
* @exception RequestNotSupportedException If the requested function is not supported because the server
* operating system is not at the correct level.
**/
public synchronized void createPrintObjectInputStream(PrintObjectImpl resource,
PrintParameterList openOptions)
throws AS400Exception,
AS400SecurityException,
ErrorCompletingRequestException,
IOException,
InterruptedException,
RequestNotSupportedException
{
objectType_ = NPConstants.RESOURCE;
NPDataStream openReq = new NPDataStream(objectType_);
NPDataStream openRep = new NPDataStream(objectType_);
npSystem_ = NPSystem.getSystem(((AFPResourceImplRemote) resource).getSystem());
cpCPFMsg_ = new NPCPAttribute();
cpObjID_ = ((AFPResourceImplRemote)resource).getIDCodePoint();
cpObjHndl_ = new NPCPResHandle();
// setup the request data stream
openReq.setAction(NPDataStream.OPEN);
openReq.addCodePoint(cpObjID_);
if (openOptions != null)
{
openReq.addCodePoint(openOptions.getAttrCodePoint());
}
// setup the reply datastream
openRep.addCodePoint(cpObjHndl_);
openRep.addCodePoint(cpCPFMsg_);
// try to open the AFP resource
conversation_ = npSystem_.getConversation();
boolean fOpenOK = false;
try
{
int rc = conversation_.makeRequest(openReq, openRep);
if (rc != NPDataStream.RET_OK)
{
String curLevel = conversation_.getAttribute(PrintObject.ATTR_NPSLEVEL);
Trace.log(Trace.ERROR, "Error opening AFP Resource; rc = " + rc);
switch(rc)
{
// we get back RET_INV_REQ_ACT on pre-V3R7 systems if we try
// to open an AFP resource. The server must be at V3R7 with PTFs
// to work with AFP resources so throw a requestNotSupportedException
// here.
case NPDataStream.RET_INV_REQ_ACT:
throw new RequestNotSupportedException(curLevel,
RequestNotSupportedException.SYSTEM_LEVEL_NOT_CORRECT);
// any other error is either an unexpected error or an error
// completing request
default:
break;
}
} else {
// try to get the number of bytes in the resource
// it will throw an exception if there is any error
retrieveNumberOfBytes();
fOpenOK = true; //we opened the spooled file
}
}
finally
{
// if we threw an exception, then return the conversation here
if (!fOpenOK)
{
if (npSystem_ != null) {
npSystem_.returnConversation(conversation_);
}
conversation_ = null;
}
}
}
/**
* Returns the number of bytes that can be read without blocking.
* This class always returns the number of bytes remaining in the spooled
* file or AFP resource.
* @return The number of available bytes without blocking.
**/
public int available()
throws IOException
{
return numBytes_ - offset_;
}
/**
* Closes the input stream.
* It must be called to release any resources associated with the stream.
* @exception IOException If an error occurs while communicating with the server.
**/
public void close()
throws IOException
{
if (conversation_ == null)
{
Trace.log(Trace.ERROR, "Conversation is null.");
throw new IOException();
} else {
NPDataStream closeReq = new NPDataStream(objectType_);
NPDataStream closeRep = new NPDataStream(objectType_);
closeReq.setAction(NPDataStream.CLOSE);
closeReq.addCodePoint(cpObjHndl_);
closeRep.addCodePoint(cpCPFMsg_);
try
{
int rc = conversation_.makeRequest(closeReq, closeRep);
if (rc != NPDataStream.RET_OK)
{
Trace.log(Trace.ERROR, "Error opening SpooledFile; rc = " + rc);
npSystem_.returnConversation(conversation_);
conversation_ = null;
}
}
catch (Exception e)
{
Trace.log(Trace.ERROR, "Caught an Exception." + e.toString());
throw new IOException(e.toString());
}
finally
{
if (npSystem_ != null) {
npSystem_.returnConversation(conversation_);
npSystem_ = null;
}
conversation_ = null;
}
}
} // close()
/**
*Closes the stream when garbage is collected.
*@exception Throwable If an error occurs.
**/
protected void finalize()
throws Throwable
{
if (conversation_ != null)
{
// attempt to send the close() request and then
// return the conversation to the pool...
// We must ignore any replies here to avoid a deadlock
// if we are called on the AS400Server's background thread.
NPDataStream closeReq = new NPDataStream(objectType_);
closeReq.setAction(NPDataStream.CLOSE);
closeReq.addCodePoint(cpObjHndl_);
AS400Server server= conversation_.getServer();
if (server != null)
{
// closeReq.setHostCCSID(conversation_.getHostCCSID());
closeReq.setConverter(conversation_.getConverter());
server.sendAndDiscardReply(closeReq);
}
if (npSystem_ != null) {
npSystem_.returnConversation(conversation_);
npSystem_ = null;
}
conversation_ = null;
}
super.finalize(); // always call super.finalize()!
}
/** Marks the current position in the input stream.
* A subsequent call to reset() will reposition the stream at the
* last marked position, so that subsequent reads will reread the same bytes.
* The stream promises to allow readLimit bytes to be read before the
* mark position gets invalidated.
*
* @param readLimit The maximum limit of bytes allowed
* to be read before the mark position becomes invalid.
**/
public synchronized void mark(int readLimit)
{
offsetFromMark_ = 0;
markLimit_ = readLimit;
markSet_ = true;
}
/** Returns a boolean indicating whether this stream type
* supports mark/reset.
*
* @return Always true. Objects of this class will support
* the mark/reset methods.
**/
public boolean markSupported()
{
return true;
}
/** Reads the next byte of data from this input stream.
* @return The byte read, or -1 if the end of the stream is reached.
* @exception IOException If an error occurs while communicating with the server.
**/
/* public int read()
throws IOException
{
int iRC = -1;
if (conversation_ == null)
{
Trace.log(Trace.ERROR, "Conversation is null.");
throw new IOException();
} else {
byte[] byteBuffer = new byte[1];
int rc = read(byteBuffer);
if (rc == 1)
{
iRC = (int)byteBuffer[0];
}
}
return iRC;
} // read()
*/
/** Reads up to data.length bytes of data from this
* input stream into data.
*
* @param data The buffer into which the data is read.
*
* @return The total number of bytes read into the buffer,
* or -1 if there is no more data because the
* end of file has been reached.
* @exception IOException If an error occurs while communicating with the server.
**/
/* public int read(byte[] data)
throws IOException
{
return read(data, 0, data.length);
} // read(byte[]) */
/** Reads up to length bytes of data from this input stream
* into data, starting at the array offset dataOffset.
*
* @param data The buffer into which the data is read.
* @param dataOffset The start offset of the data.
* @param length The maximum number of bytes to read.
*
* @return The total number of bytes read into the buffer,
* or -1 if there is no more data because the
* end of file has been reached.
* @exception IOException If an error occurs while communicating with the server.
**/
public int read(byte data[], int dataOffset, int length)
throws IOException
{
int bytesRead = 0;
if (conversation_ == null)
{
Trace.log(Trace.ERROR, "Conversation is null.");
throw new IOException();
} else {
NPDataStream readReq = new NPDataStream(objectType_);
NPDataStream readRep = new NPDataStream(objectType_);
NPCPAttribute cpAttr = new NPCPAttribute();
NPCPData cpData = new NPCPData();
// set the number of bytes to read
cpAttr.setAttrValue(PrintObject.ATTR_NUMBYTES, length);
readReq.setAction(NPDataStream.READ);
readReq.addCodePoint(cpObjHndl_);
readReq.addCodePoint(cpAttr);
// Point the data codepoint to receive the data into our buffer.
// Our buffer better be big enough to hold the data or we''ll
// not get it at all
cpData.setDataBuffer(data, 0, dataOffset);
readRep.addCodePoint(cpData);
readRep.addCodePoint(cpCPFMsg_);
try
{
int iRC = conversation_.makeRequest(readReq, readRep);
switch (iRC)
{
case NPDataStream.RET_OK:
case NPDataStream.RET_READ_INCOMPLETE: // maybe read some bytes?
// see how many bytes we read
bytesRead = cpData.getDataLength();
offsetFromMark_ += bytesRead; // update how far we went from the mark
offset_ += bytesRead; // update how far we are from the start of file
break;
case NPDataStream.RET_READ_EOF:
// this return code is only returned if there are no
// bytes read at all
bytesRead = -1; // set rc to end of file
break;
default:
// log an error throw appropriate exception
Trace.log(Trace.ERROR, "Error received on read : " + Integer.toString(iRC));
throw new IOException(Integer.toString(iRC));
}
}
catch (Exception e)
{
Trace.log(Trace.ERROR, "PrintObjectInputStream::read() - caught an Exception." + e.toString());
throw new IOException(e.toString());
}
}
return bytesRead;
} // read(byte[], int, int)
/** Repositions the stream to the last marked position.
* If the stream has not been marked or if the mark has been invalidated,
* an IOException is thrown.
* @exception IOException If an error occurs while communicating with the server.
**/
public synchronized void reset()
throws IOException
{
if (conversation_ == null)
{
Trace.log(Trace.ERROR, "Conversation is null.");
throw new IOException();
}
if (!markSet_)
{
Trace.log(Trace.ERROR, "Mark not set.");
throw new IOException();
} else {
if ((markLimit_ == 0) || (offsetFromMark_ > markLimit_))
{
Trace.log(Trace.WARNING, "Stream has not been marked or mark has been invalidated.");
throw new IOException();
} else {
// seek backwards from the current spot offsetFromMark_ bytes
// and reset offsetFromMark_ to 0
if (offsetFromMark_ != 0)
{
seekFromCur(-offsetFromMark_);
}
}
}
} // reset()
private void retrieveNumberOfBytes()
throws AS400Exception,
AS400SecurityException,
ErrorCompletingRequestException,
IOException,
InterruptedException,
RequestNotSupportedException
{
NPDataStream sendDS = new NPDataStream(objectType_);
NPDataStream replyDS = new NPDataStream(objectType_);
NPCPAttribute cpAttrs = new NPCPAttribute();
NPCPAttributeIDList cpAttrsToRetrieve = new NPCPAttributeIDList();
cpAttrsToRetrieve.addAttrID(PrintObject.ATTR_NUMBYTES);
sendDS.addCodePoint(cpObjID_);
sendDS.addCodePoint(cpAttrsToRetrieve);
sendDS.setAction(NPDataStream.RETRIEVE_ATTRIBUTES);
replyDS.addCodePoint(cpAttrs);
int rc = conversation_.makeRequest(sendDS, replyDS);
if (rc == NPDataStream.RET_OK)
{
Integer numBytes = cpAttrs.getIntValue(PrintObject.ATTR_NUMBYTES);
if (numBytes != null)
{
numBytes_ = numBytes.intValue();
} else {
Trace.log(Trace.ERROR,
" Network Print Server does not support retrieving splf/resource length");
throw new RequestNotSupportedException(
conversation_.getAttribute(PrintObject.ATTR_NPSLEVEL),
RequestNotSupportedException.SYSTEM_LEVEL_NOT_CORRECT);
}
} else {
Trace.log(Trace.ERROR,
" Network Print Server error retrieving splf/resource length. RC =" +
rc);
throw new RequestNotSupportedException(
conversation_.getAttribute(PrintObject.ATTR_NPSLEVEL),
RequestNotSupportedException.SYSTEM_LEVEL_NOT_CORRECT);
}
} // retrieveNumBytes()
/** Skips over the next bytesToSkip bytes in the stream.
* This method may skip less bytes than specified if the end of
* file is reached. The actual number of bytes skipped is returned.
* @param bytesToSkip The number of bytes to be skipped.
* @return The actual number of bytes skipped.
* @exception IOException If an error occurs while communicating with the server.
**/
public long skip(long bytesToSkip) throws IOException
{
if ( (conversation_ == null))
{
Trace.log(Trace.ERROR, "Conversation is null.");
throw new IOException();
} else {
int maxSkip = numBytes_ - offset_; // maximum number of bytes you can skip
if (bytesToSkip > maxSkip)
{
bytesToSkip = maxSkip;
}
seekFromCur((int)bytesToSkip); // seek ahead from current pointer n bytes
}
return bytesToSkip;
} // skip(long n);
private void seekFromCur(int offset)
throws IOException
{
NPDataStream seekReq = new NPDataStream(objectType_);
NPDataStream seekRep = new NPDataStream(objectType_);
NPCPAttribute cpAttr = new NPCPAttribute();
cpAttr.setAttrValue(PrintObject.ATTR_SEEKORG, 2); // current read pointer
cpAttr.setAttrValue(PrintObject.ATTR_SEEKOFF, offset); // offset
seekReq.setAction(NPDataStream.SEEK);
seekReq.addCodePoint(cpObjHndl_);
seekReq.addCodePoint(cpAttr);
seekRep.addCodePoint(cpCPFMsg_);
try
{
int iRC = conversation_.makeRequest(seekReq, seekRep);
switch (iRC)
{
case NPDataStream.RET_OK:
offsetFromMark_ += offset; // update how far we went from the mark
offset_ += offset; // update how far we are from beginning of file
break;
case NPDataStream.RET_SEEK_OFF_BAD:
default:
// we should never get Seek offset bad because we
// always check in skip that we aren't going beyond the end of
// the file. The other place we seek is on a reset and that
// should work.
Trace.log(Trace.ERROR, "Seek from cur error " + Integer.toString(iRC));
throw new IOException(Integer.toString(iRC));
}
}
catch (Exception e)
{
Trace.log(Trace.ERROR, "Caught an Exception." + e.toString());
throw new IOException(e.toString());
}
} // seekFromCur()
/**
* returns the number of bytes from the beginning of the file.
*
* @return The number of bytes from the beginning of the file.
* @exception IOException If an error occurs while communicating with the server.
**/
long tell()
throws IOException
{
if ( (conversation_ == null))
{
Trace.log(Trace.ERROR, "Conversation is null.");
throw new IOException();
} else {
NPDataStream tellReq = new NPDataStream(objectType_);
NPDataStream tellRep = new NPDataStream(objectType_);
NPCPAttributeIDList cpAttrIDs = new NPCPAttributeIDList();
NPCPAttribute cpAttr = new NPCPAttribute();
cpAttrIDs.addAttrID(PrintObject.ATTR_SEEKOFF);
tellReq.setAction(NPDataStream.TELL);
tellReq.addCodePoint(cpObjHndl_);
// the cpAttr will catch either the offset attribute or the CPF message
tellRep.addCodePoint(cpAttr);
try
{
int iRC = conversation_.makeRequest(tellReq, tellRep);
switch (iRC)
{
case NPDataStream.RET_OK:
Integer curOffset = cpAttr.getIntValue(PrintObject.ATTR_SEEKOFF);
if (curOffset == null)
{
Trace.log(Trace.ERROR, " tell() returned null!");
throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR);
} else {
return curOffset.intValue();
}
default:
// Anything else would be an error...The conversation should handle
// the basic CPF message error for us, so this would be some unexpected
// result - throw a runtime error.
Trace.log(Trace.ERROR, " NPServer.Tell() returned " + iRC);
throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR);
}
}
catch (Exception e)
{
Trace.log(Trace.ERROR, "Caught an Exception." + e.toString());
throw new IOException(e.toString());
}
}
} // tell()
} // PrintObjectInputStream class
© 2015 - 2025 Weber Informatics LLC | Privacy Policy