src.com.ibm.as400.access.IFSFileDescriptorImplRemote 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
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: IFSFileDescriptorImplRemote.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.
//
///////////////////////////////////////////////////////////////////////////////
// @A3 - 10/18/2007 - Update finalize0() method to not send TWO close requests
// to the server. When garbage collection finds a descriptor
// that has not been closed, it calls the finalize method on
// one of the various IFSFilexxx classes which calls the
// finalize0() method of this class.
// This class was sending TWO close requests to the server
// for the same fileHandle_. Normally, the second close would
// silently fail. However, in some cases another thread might
// issue an open request for another file BETWEEN the two close
// requests sent by the garbage collection thread. This
// results in the newly opened file being incorrectly closed.
// Fix to finalize0() is to issue ONE close request to the
// File server.
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Vector;
/**
Provides a full remote implementation for the IFSFileDescriptor class.
**/
class IFSFileDescriptorImplRemote
implements IFSFileDescriptorImpl
{
private static final int UNINITIALIZED = -1; // @B8a
private static final int MAX_BYTES_PER_READ = 16000000; // limit of file server
// Note: We allow direct access to some of these fields, for performance. @B2C
ConverterImplRemote converter_;
private int fileHandle_ = UNINITIALIZED; // @B8c
int preferredServerCCSID_;
private int fileDataCCSID_ = UNINITIALIZED;
private int fileAsp_ = UNINITIALIZED;//@V4A
private int fileSystemType_ = UNINITIALIZED;//@V4A
int serverDatastreamLevel_; // @B3A
int requestedDatastreamLevel_; // @B6a
private long fileOffset_;
boolean isOpen_;
boolean isOpenAllowed_ = true;
private Object parent_; // The object that instantiated this IFSDescriptor.
String path_ = "";
byte[] pathnameBytes_;
AS400Server server_; // Note: AS400Server is not serializable.
private int shareOption_;
AS400ImplRemote system_;
private Object fileOffsetLock_ = new Object();
// Semaphore for synchronizing access to fileOffset_.
private int maxDataBlockSize_ = 1024; // @B2A
// Used by IFSFileOutputStreamImplRemote, IFSRandomAccessFileImplRemote.
private boolean determinedSystemVRM_ = false; // @B3A @B4C
private int systemVRM_; // @B3A @B4C
transient int errorRC_; // error return code from most recent request
int patternMatching_ = IFSFile.PATTERN_DEFAULT; // pattern-matching semantics
// Used for debugging only. This should always be false for production.
// When this is false, all debug code will theoretically compile out.
private static final boolean DEBUG = false; // @B3A
// Static initialization code.
static
{
// Add all byte stream reply data streams of interest to the
// AS400 server's reply data stream hash table.
AS400Server.addReplyStream(new IFSCloseRep(), AS400.FILE);
AS400Server.addReplyStream(new IFSExchangeAttrRep(), AS400.FILE);
AS400Server.addReplyStream(new IFSLockBytesRep(), AS400.FILE);
AS400Server.addReplyStream(new IFSReturnCodeRep(), AS400.FILE);
AS400Server.addReplyStream(new IFSWriteRep(), AS400.FILE);
AS400Server.addReplyStream(new IFSReadRep(), AS400.FILE);
}
// Cast an IFSFileDescriptorImpl object into an IFSFileDescriptorImplRemote.
// Used by various IFS*ImplRemote classes.
static IFSFileDescriptorImplRemote castImplToImplRemote(IFSFileDescriptorImpl fd)
{
try
{
return (IFSFileDescriptorImplRemote)fd;
}
catch (ClassCastException e)
{
Trace.log(Trace.ERROR, "Argument is not an instance of IFSFileDescriptorImplRemote", e);
throw new
InternalErrorException(InternalErrorException.UNEXPECTED_EXCEPTION);
}
}
// @B8m - Moved this method here from IFSFileImplRemote.
// Determine if the directory entry can be accessed in the specified
// manner.
// Returns the returnCode that was set (as a side effect) by createFileHandle().
int checkAccess(int access, int openOption) // @D1C @B8c
throws IOException, AS400SecurityException
{
int fileHandle = UNINITIALIZED;
try {
fileHandle = createFileHandle(access, openOption);
}
finally {
if (fileHandle != UNINITIALIZED) close(fileHandle); // we don't need this handle anymore
}
return errorRC_;
}
public void close()
{
try {
close0();
}
catch (IOException e) {
Trace.log(Trace.ERROR, "Error while closing file " + path_, e);
}
}
public void close0() throws IOException
{
isOpen_ = false;
close(fileHandle_);
fileHandle_ = UNINITIALIZED;
}
void close(int fileHandle) throws IOException
{
if (fileHandle == UNINITIALIZED) return; // @B8c
// Close the file. Send a close request to the server.
ClientAccessDataStream ds = null;
IFSCloseReq req = new IFSCloseReq(fileHandle);
try
{
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream connection lost during close", e);
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Validate the reply.
if (ds instanceof IFSCloseRep)
{
int rc = ((IFSCloseRep) ds).getReturnCode();
if (rc != 0)
{
Trace.log(Trace.ERROR, "IFSCloseRep return code", rc);
throw new ExtendedIOException(path_, rc);
}
}
else if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path_, rc);
}
}
else
{
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
}
/**
Establishes communications with the server.
@exception AS400SecurityException If a security or authority error occurs.
@exception IOException If an error occurs while communicating with the server.
**/
void connect() // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
throws IOException, AS400SecurityException
{
// Connect to the byte stream server if not already connected.
if (server_ == null)
{
// Ensure that the system has been set.
if (system_ == null)
{
throw new ExtendedIllegalStateException("system",
ExtendedIllegalStateException.PROPERTY_NOT_SET);
}
try {
server_ = system_.getConnection(AS400.FILE, false /*forceNewConnection*/, false /*skip signon server */ );
}
catch(AS400SecurityException e)
{
Trace.log(Trace.ERROR, "Access to byte stream server on '" +
system_.getSystemName() + "' denied.", e);
throw e;
}
// Exchange attributes with the server.
exchangeServerAttributes();
}
}
/**
Disconnects from the byte stream server.
@exception ConnectionDroppedException If the connection is dropped unexpectedly.
**/
void connectionDropped(ConnectionDroppedException e) // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
throws ConnectionDroppedException
{
if (server_ != null)
{
system_.disconnectServer(server_);
server_ = null;
try { close(); } catch (Exception exc) {} // Note: Not relevant for IFSFileImplRemote.
}
Trace.log(Trace.ERROR, "Byte stream connection lost.");
throw e;
}
/**
* Copies a file or directory to another file or directory.
**/
boolean copyTo(String destinationPath, boolean replace)
throws AS400SecurityException, IOException
{
ClientAccessDataStream ds = null;
IFSCopyReq req = new IFSCopyReq(path_, destinationPath, replace);
try
{
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream connection lost during copy", e);
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
String path = (rc == IFSReturnCodeRep.DUPLICATE_DIR_ENTRY_NAME ? destinationPath : path_);
throwSecurityExceptionIfAccessDenied(path,rc); // check for "access denied"
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path, rc);
}
return true;
}
else
{
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
}
// Opens the file for 'read' access, and returns a file handle.
// If failure, sets errorRC_ and returns UNINITIALIZED.
private final int createFileHandle()
throws IOException, AS400SecurityException
{
return createFileHandle(IFSOpenReq.READ_ACCESS, IFSOpenReq.OPEN_OPTION_FAIL_OPEN);
}
// Opens the file with specified access and option, and returns a file handle.
// If failure, sets errorRC_ and returns UNINITIALIZED.
int createFileHandle(int access, int openOption) // @D1C @B8c
throws IOException, AS400SecurityException
{
int returnCode = IFSReturnCodeRep.FILE_NOT_FOUND;
int fileHandle = UNINITIALIZED;
errorRC_ = 0;
// Try to open the file for the specified type of access.
try
{
// Process an open file request.
// For 3rd parm (file data CCSID), specify 0 since we don't care about CCSID.
IFSOpenReq req = new IFSOpenReq(getPathnameAsBytes(), preferredServerCCSID_,
0, access, IFSOpenReq.DENY_NONE,
IFSOpenReq.NO_CONVERSION,
openOption, serverDatastreamLevel_); // @D1C
ClientAccessDataStream ds = (ClientAccessDataStream) server_.sendAndReceive(req);
if (ds instanceof IFSOpenRep)
{
// The open was successful. Close the file if appropriate.
returnCode = IFSReturnCodeRep.SUCCESS;
fileHandle = ((IFSOpenRep) ds).getFileHandle(); // @B8a
}
else if (ds instanceof IFSReturnCodeRep)
{
returnCode = ((IFSReturnCodeRep) ds).getReturnCode();
throwSecurityExceptionIfAccessDenied(path_,returnCode); // check for "access denied"
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost", e);
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
if (returnCode != IFSReturnCodeRep.SUCCESS)
{
if (Trace.isTraceOn() && Trace.isTraceDiagnosticOn())
{
Trace.log(Trace.DIAGNOSTIC, "Unable to open file " + path_ + ": " +
"IFSReturnCodeRep return code", descriptionForReturnCode(returnCode));
}
errorRC_ = returnCode;
return UNINITIALIZED;
}
return fileHandle;
}
/**
Exchanges server attributes.
@exception IOException If an error occurs while communicating with the server.
**/
void exchangeServerAttributes() // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
throws IOException, AS400SecurityException
{
synchronized (server_)
{
DataStream ds = server_.getExchangeAttrReply();
IFSExchangeAttrRep rep = null;
try { rep = (IFSExchangeAttrRep)ds; }
catch (ClassCastException e)
{
if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path_, rc);
}
else {
String className = ( ds == null ? "null" : ds.getClass().getName());
Trace.log(Trace.ERROR, "Unexpected reply from Exchange Server Attributes: " + className);
throw new InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN);
}
}
// Note: For releases after V5R4, we ask for Datastream Level 16;
// for V5R3 thru V5R4, we ask for Datastream Level 8;
// for V4R5 thru V5R2, we ask for Datastream Level 2;
// for earlier systems, we ask for Datastream Level 0. // @B6c
if (getSystemVRM() >= 0x00060100)
requestedDatastreamLevel_ = 16;
else if (getSystemVRM() >= 0x00050300)
requestedDatastreamLevel_ = 8;
else if (getSystemVRM() >= 0x00040500) // @B3A @B4C
requestedDatastreamLevel_ = 2;
else
requestedDatastreamLevel_ = 0;
if (rep == null)
{
ds = null;
try
{
int[] preferredCcsids; // @A2A
// Datastream level 8 was introduced in release V5R3.
if (getSystemVRM() >= 0x00050300)
{ // System is post-V5R2.
preferredCcsids = new int[] {0x04b0,0x34b0,0xf200}; // UTF-16, new or old Unicode.
}
// Note: Pre-V4R5 systems hang when presented with multiple
// preferred CCSIDs in the exchange of attributes. @B3A @B4C
else if (getSystemVRM() >= 0x00040500) // @B3A @B4C
{ // System is V4R5 or later. We can present a list of preferred CCSIDs.
preferredCcsids = new int[] {0x34b0,0xf200}; // New or old Unicode.
}
else
{ // System is pre-V4R5. Exchange attr's the old way.
preferredCcsids = new int[] {0xf200}; // Old Unicode only.
}
// Use GMT date/time, don't use posix style return codes,
// use PC pattern matching semantics,
// maximum data transfer size of 0xffffffff.
ds = server_.sendExchangeAttrRequest( //@B3A
new IFSExchangeAttrReq(true, false,
IFSExchangeAttrReq.PC_PATTERN_MATCH,
0xffffffff,
requestedDatastreamLevel_,
preferredCcsids)); // @A2C
rep = (IFSExchangeAttrRep)ds;
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
system_.disconnectServer(server_);
server_ = null;
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
catch(IOException e)
{
Trace.log(Trace.ERROR, "I/O error during attribute exchange.");
system_.disconnectServer(server_);
server_ = null;
throw e;
}
catch(ClassCastException e)
{
if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path_, rc);
}
else {
String className = ( ds == null ? "null" : ds.getClass().getName());
Trace.log(Trace.ERROR, "Unexpected reply from Exchange Server Attributes: " + className);
throw new InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN);
}
}
}
// Process the exchange attributes reply.
if (rep != null)
{
maxDataBlockSize_ = ((IFSExchangeAttrRep) rep).getMaxDataBlockSize();
preferredServerCCSID_ = rep.getPreferredCCSID();
serverDatastreamLevel_ = rep.getDataStreamLevel();
setConverter(ConverterImplRemote.getConverter(preferredServerCCSID_,
system_));
if (DEBUG) {
System.out.println("DEBUG: IFSFileDescriptorImplRemote.exchangeServerAttributes(): " +
"preferredServerCCSID_ == " + preferredServerCCSID_);
int[] list = rep.getPreferredCCSIDs();
for (int i=0; i 1) {
if (Trace.traceOn_) Trace.log(Trace.WARNING, "Received multiple replies from listAttributes(fileHandle) (" +
replys.size() + ")");
}
else {
reply = (IFSListAttrsRep) replys.elementAt(0);
}
}
finally {
if(!usedGlobalHandle && fileHandle != UNINITIALIZED) //@KKBA
close(fileHandle);
}
return reply;
}
/**
Places a lock on the file at the specified bytes.
@param offset The first byte of the file to lock (zero is the first byte).
@param length The number of bytes to lock.
@return A key for undoing this lock.
@exception ConnectionDroppedException If the connection is dropped unexpectedly.
@exception ExtendedIOException If an error occurs while communicating with the server.
@exception InterruptedIOException If this thread is interrupted.
@exception ServerStartupException If the server cannot be started.
@exception UnknownHostException If the system cannot be located.
@see IFSKey
@see #unlock
**/
IFSKey lock(long length) // @B2A
throws IOException, AS400SecurityException
{
return lock(fileOffset_, length);
}
IFSKey lock(long offset, // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
long length)
throws IOException, AS400SecurityException
{
// Assume the arguments have been validated by the caller.
// Attempt to lock the file.
ClientAccessDataStream ds = null;
try
{
// Issue a mandatory, exclusive lock bytes request. Mandatory
// means that the file system enforces the lock by causing any
// operation which conflicts with the lock to fail. Exclusive
// means that only the owner of the lock can read or write the
// locked area.
IFSLockBytesReq req =
new IFSLockBytesReq(fileHandle_, true, false, offset,
length, serverDatastreamLevel_);
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Verify the reply.
if (ds instanceof IFSLockBytesRep)
{
int rc = ((IFSLockBytesRep) ds).getReturnCode();
if (rc != 0)
{
Trace.log(Trace.ERROR, "IFSLockBytesRep return code", rc);
throw new ExtendedIOException(path_, rc);
}
}
else if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path_, rc);
}
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
// Generate the key for this lock.
IFSKey key = new IFSKey(fileHandle_, offset, length, true);
return key;
}
// Common code used by IFSFileInputStreamImplRemote and IFSRandomAccessFileImplRemote.
/**
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 offset The start offset of the data in the buffer.
@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 ConnectionDroppedException If the connection is dropped unexpectedly.
@exception ExtendedIOException If an error occurs while communicating with the server.
@exception InterruptedIOException If this thread is interrupted.
@exception ServerStartupException If the server cannot be started.
@exception UnknownHostException If the system cannot be located.
**/
int read(byte[] data, // @B2A - code relocated from IFSFileInputStreamImplRemote,etc.
int dataOffset,
int length)
throws IOException, AS400SecurityException
{
// Assume the arguments have been validated by the public class.
// If length is zero then return zero.
if (length == 0)
{
return 0;
}
int totalBytesRead = 0;
int bytesRemainingToRead = length;
boolean endOfFile = false;
while (totalBytesRead < length && !endOfFile)
{
// If the number of bytes being requested is greater than 16 million, then submit multiple requests for smaller chunks. The File Server has a limit that is somewhat below 16 megabytes (allowing for headers, etc), so 16 _million_ bytes is a safe limit.
// Issue the read data request.
int bytesToReadThisTime = Math.min(bytesRemainingToRead, MAX_BYTES_PER_READ);
IFSReadReq req = new IFSReadReq(fileHandle_, fileOffset_,
bytesToReadThisTime, serverDatastreamLevel_);
ClientAccessDataStream ds = null;
try
{
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Receive replies until the end of chain.
boolean endOfChain = false;
int bytesReadByThisRequest = 0;
do
{
if (ds instanceof IFSReadRep)
{
// Copy the data from the reply to the data parameter.
byte[] buffer = ((IFSReadRep) ds).getData();
if (buffer.length > 0)
{
System.arraycopy(buffer, 0, data, dataOffset, buffer.length);
bytesReadByThisRequest += buffer.length;
dataOffset += buffer.length;
}
else // no data returned. This implies end-of-file (e.g. if file is empty).
{
bytesReadByThisRequest = -1;
endOfFile = true;
}
}
else if (ds instanceof IFSReturnCodeRep)
{
// Check for failure.
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc == IFSReturnCodeRep.SUCCESS)
{ // It worked, so nothing special to do here.
}
else if (rc == IFSReturnCodeRep.NO_MORE_DATA)
{
// End of file.
bytesReadByThisRequest = -1;
endOfFile = true;
}
else // none of the above
{
throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path_, rc);
}
}
else // neither IFSReadRep nor IFSReturnCodeRep
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
// Get the next reply if not end of chain.
endOfChain = ((IFSDataStream) ds).isEndOfChain();
if (!endOfChain)
{
try
{
ds = (ClientAccessDataStream)
server_.receive(req.getCorrelation());
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
}
}
while (!endOfChain);
// Advance the file pointer.
if (bytesReadByThisRequest > 0) {
incrementFileOffset(bytesReadByThisRequest);
totalBytesRead += bytesReadByThisRequest;
bytesRemainingToRead -= bytesReadByThisRequest;
}
}
// If we have read zero bytes and hit end-of-file, indicate that by returning -1.
// Otherwise return total number of bytes read.
return (endOfFile && totalBytesRead == 0 ? -1 : totalBytesRead);
}
void setConverter(ConverterImplRemote converter)
{
converter_ = converter;
}
/**
Sets the cached "file data CCSID" value.
**/
void setCCSID(int ccsid)
throws IOException
{
fileDataCCSID_ = ccsid;
}
public void setFileOffset(long fileOffset)
{
synchronized(fileOffsetLock_)
{
fileOffset_ = fileOffset;
}
}
// @B8a
boolean setLength(long length)
throws IOException, AS400SecurityException
{
// Assume that we are connected to the server.
// Prepare to issue a 'change attributes' request.
ClientAccessDataStream ds = null;
int fileHandle = UNINITIALIZED;
try
{
// Open the file for read/write, get a file handle, and call 'change attributes'.
fileHandle = createFileHandle(IFSOpenReq.WRITE_ACCESS, IFSOpenReq.OPEN_OPTION_FAIL_OPEN);
if (fileHandle == UNINITIALIZED)
{
if (Trace.traceOn_) Trace.log(Trace.ERROR, "Unable to create handle to file " + path_ + ". IFSReturnCodeRep return code", errorRC_);
return false;
}
IFSChangeAttrsReq req = new IFSChangeAttrsReq(fileHandle, length, serverDatastreamLevel_);
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost.");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted");
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
finally {
close(fileHandle); // we don't need this handle anymore
}
// Verify the reply.
boolean success = false;
if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc == IFSReturnCodeRep.SUCCESS)
success = true;
else
{
throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
Trace.log(Trace.ERROR, path_ + ": IFSReturnCodeRep return code", descriptionForReturnCode(rc));
}
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
// Back off the file pointer if needed.
if (fileOffset_ > length) {
fileOffset_ = length;
}
return success;
}
// Ignores fileHandle if state==false.
void setOpen(boolean state, int fileHandle)
{
if (state == true)
{
if (fileHandle == UNINITIALIZED)
{
Trace.log(Trace.ERROR, "Called setOpen with invalid file handle: " + fileHandle);
throw new
InternalErrorException(InternalErrorException.UNEXPECTED_EXCEPTION);
}
else
{
if (fileHandle != fileHandle_) close(); // close currently-open handle if different
fileHandle_ = fileHandle;
}
}
isOpen_ = state;
}
void setOpenAllowed(boolean state)
{
isOpenAllowed_ = state;
}
void setPreferredCCSID(int ccsid)
{
preferredServerCCSID_ = ccsid;
}
void setServer(AS400Server server)
{
server_ = server;
}
/**
Force the system buffers to synchronize with the underlying device.
**/ // $A1
public void sync() throws IOException
{
if (parent_ == null)
{
Trace.log(Trace.ERROR, "IFSFileDescriptor.sync() was called when parent is null.");
}
// Note: UserSpaceImplRemote creates an IFSFileDescriptorImplRemote directly.
else if (parent_ instanceof IFSRandomAccessFileImplRemote)
{
((IFSRandomAccessFileImplRemote)parent_).flush();
}
else if (parent_ instanceof IFSFileOutputStreamImplRemote)
{
((IFSFileOutputStreamImplRemote)parent_).flush();
}
else
{
Trace.log(Trace.WARNING, "IFSFileDescriptor.sync() was called " +
"when parent is neither an IFSRandomAccessFile nor an IFSFileOutputStream.");
}
}
private static final void throwSecurityExceptionIfAccessDenied(String path, int returnCode)
throws AS400SecurityException
{
if (returnCode == IFSReturnCodeRep.ACCESS_DENIED_TO_DIR_ENTRY ||
returnCode == IFSReturnCodeRep.ACCESS_DENIED_TO_REQUEST)
{
if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC, "Access denied to file " + path + ". " +
"IFSReturnCodeRep return code", returnCode);
throw new AS400SecurityException(path, AS400SecurityException.DIRECTORY_ENTRY_ACCESS_DENIED);
}
}
/**
Undoes a lock on this file.
@param key The key for the lock.
@exception IOException If an error occurs while communicating with the server.
@see IFSKey
@see #lock
**/
void unlock(IFSKey key) // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
throws IOException, AS400SecurityException
{
// Assume the argument has been validated by the caller.
// Verify that this key is compatible with this file.
if (key.fileHandle_ != fileHandle_)
{
Trace.log(Trace.ERROR, "Attempt to use IFSKey on different file stream.");
throw new ExtendedIllegalArgumentException("key",
ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
}
// Attempt to unlock the file.
ClientAccessDataStream ds = null;
// Issue an unlock bytes request.
IFSUnlockBytesReq req =
new IFSUnlockBytesReq(key.fileHandle_, key.offset_,
key.length_, key.isMandatory_, serverDatastreamLevel_);
try
{
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Verify the reply.
if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path_, rc);
}
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
}
// Common code used by IFSFileOutputStreamImplRemote and IFSRandomAccessFileImplRemote.
/**
Writes length bytes from the byte array data, starting at dataOffset, to this File.
@param data The data.
@param dataOffset The start offset in the data.
@param length The number of bytes to write.
@parm forceToStorage Whether data must be written before the server replies.
@exception ConnectionDroppedException If the connection is dropped unexpectedly.
@exception ExtendedIOException If an error occurs while communicating with the server.
@exception InterruptedIOException If this thread is interrupted.
@exception ServerStartupException If the server cannot be started.
@exception UnknownHostException If the system cannot be located.
**/
void writeBytes(byte[] data, // @B2A
int dataOffset,
int length)
throws IOException, AS400SecurityException
{
writeBytes(data, dataOffset, length, false);
}
void writeBytes(byte[] data, // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
int dataOffset,
int length,
boolean forceToStorage)
throws IOException, AS400SecurityException
{
// Assume the arguments have been validated by the caller.
// Send write requests until all data has been written.
while(length > 0)
{
// Determine how much data can be written on this request.
int writeLength = (length > maxDataBlockSize_ ?
maxDataBlockSize_ : length);
// Build the write request. Set the chain bit if there is
// more data to write.
IFSWriteReq req = new IFSWriteReq(fileHandle_, fileOffset_,
data, dataOffset, writeLength,
0xffff, forceToStorage, serverDatastreamLevel_);
if (length - writeLength > 0)
{
// Indicate that there is more to write.
req.setChainIndicator(1);
}
// Send the request.
ClientAccessDataStream ds = null;
try
{
// Send the request and receive the response.
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted", e);
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Check the reply.
if (ds instanceof IFSWriteRep)
{
IFSWriteRep rep = (IFSWriteRep) ds;
int rc = rep.getReturnCode();
if (rc != 0)
{
Trace.log(Trace.ERROR, "IFSWriteRep return code", rc);
throw new ExtendedIOException(path_, rc);
}
// Advance the file pointer the length of the data
// written.
int lengthWritten = writeLength - rep.getLengthNotWritten();
incrementFileOffset(lengthWritten);
dataOffset += lengthWritten;
length -= lengthWritten;
// Ensure that all data requested was written.
if (lengthWritten != writeLength)
{
Trace.log(Trace.ERROR, "Incomplete write. Only " +
Integer.toString(lengthWritten) + " bytes of a requested " +
Integer.toString(writeLength) + " were written.");
throw new ExtendedIOException(path_, ExtendedIOException.UNKNOWN_ERROR);
}
}
else if (ds instanceof IFSReturnCodeRep)
{
int rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
throw new ExtendedIOException(path_, rc);
}
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
}
}
public int getServerDatastreamLevel() {
return serverDatastreamLevel_;
}
//@V4A
public int createUserHandle() throws IOException, AS400SecurityException{
ClientAccessDataStream ds = null;
int UserHandle = UNINITIALIZED;
int rc;
byte[] ClientSeed = BinaryConverter.longToByteArray(System.currentTimeMillis());
byte[] ServerSeed = null;
try {
IFSUserHandleSeedReq req = new IFSUserHandleSeedReq(ClientSeed);
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted");
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Verify that we got a handle back.
if (ds instanceof IFSUserHandleSeedRep)
{
ServerSeed = ((IFSUserHandleSeedRep) ds).getSeed();
}
else if (ds instanceof IFSReturnCodeRep)
{
rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
}
throw new ExtendedIOException(rc);
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream",
ds.getReqRepID());
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
rc = 0;
ds = null;
byte[] userIDbytes = SignonConverter.stringToByteArray(system_.getUserId());
byte[] encryptedPassword = system_.getPassword(ClientSeed, ServerSeed);
IFSCreateUserHandlerReq req = new IFSCreateUserHandlerReq(userIDbytes, encryptedPassword);
try {
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
} catch (InterruptedException e) {
Trace.log(Trace.ERROR, "Interrupted");
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Verify the reply.
if (ds instanceof IFSCreateUserHandleRep)
{
rc = ((IFSCreateUserHandleRep)ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSCreateUserHandleRep return code", rc);
}
UserHandle = ((IFSCreateUserHandleRep) ds).getHandle();
}
else if (ds instanceof IFSReturnCodeRep)
{
rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
}
throw new ExtendedIOException(rc);
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream",
ds.getReqRepID());
throw new
InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN,
Integer.toHexString(ds.getReqRepID()),null);
}
return UserHandle;
}
public void freeUserHandle(int userHandle) throws IOException, AS400SecurityException{
IFSFreeUserHandlerReq req = new IFSFreeUserHandlerReq(userHandle);
server_.send(req);
}
public void freeHandle(int objectHandle) throws IOException, AS400SecurityException{
IFSFreeHandleReq req = new IFSFreeHandleReq(objectHandle);
server_.send(req);
}
public int getASP() throws IOException, AS400SecurityException {
if (fileAsp_ == UNINITIALIZED)
{
ClientAccessDataStream ds = null;
int rc = 0;
connect();
// Ensure that we are connected to the server.
byte[] pathname = getConverter().stringToByteArray(path_);
//create user handle
int userHandle = UNINITIALIZED, objectHandle = UNINITIALIZED;
try{
userHandle = system_.createUserHandle();
try
{
// Issue a Look up request to create an object handle.
IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle, IFSLookupReq.OA1, IFSLookupReq.ASP_FLAG, 0);
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost.");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted");
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
rc = 0;
if (ds instanceof IFSLookupRep)
{
objectHandle = ((IFSLookupRep) ds).getHandle();
fileAsp_ = ((IFSLookupRep) ds).getASP();
}
else if (ds instanceof IFSReturnCodeRep)
{
rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
}
throw new ExtendedIOException(path_, rc);
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream",
ds.getReqRepID());
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
}finally{
//if(userHandle != UNINITIALIZED)
// freeUserHandle(userHandle);
if(objectHandle != UNINITIALIZED)
freeHandle(objectHandle);
}
}
return fileAsp_;
}
public String getOwnerNameByUserHandle() throws IOException, AS400SecurityException {
String ownerName = null;
ClientAccessDataStream ds = null;
int rc = 0;
// Ensure that we are connected to the server.
connect();
byte[] pathname = getConverter().stringToByteArray(path_);
//create user handle
int userHandle = UNINITIALIZED, objectHandle = UNINITIALIZED;
try{
userHandle = system_.createUserHandle();
try
{
// Issue a Look up request to create an object handle.
IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle, IFSLookupReq.OA1, IFSObjAttrs1.OWNER_NAME_FLAG, 0);
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost.");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted");
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Verify that we got a handle back.
rc = 0;
if (ds instanceof IFSLookupRep)
{
ownerName = ((IFSLookupRep) ds).getOwnerName(system_.getCcsid());
objectHandle = ((IFSLookupRep) ds).getHandle();
}
else if (ds instanceof IFSReturnCodeRep)
{
rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
}
throw new ExtendedIOException(path_, rc);
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream",
ds.getReqRepID());
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
}finally{
// if(userHandle != UNINITIALIZED)
// freeUserHandle(userHandle);
if(objectHandle != UNINITIALIZED)
freeHandle(objectHandle);
}
return (ownerName == null ? "" : ownerName);
}
public String getFileSystemType() throws IOException, AS400SecurityException {
String typeString = "Unknown";
if (fileSystemType_ == UNINITIALIZED)
{
ClientAccessDataStream ds = null;
int rc = 0;
connect();
int objectHandle = UNINITIALIZED;
byte[] pathname = getConverter().stringToByteArray(path_);
//create user handle
int userHandle = UNINITIALIZED;
try{
userHandle = system_.createUserHandle();
try
{
// Issue a Look up request to create an object handle.
IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle);
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost.");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted");
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
rc = 0;
if (ds instanceof IFSLookupRep)
{
objectHandle = ((IFSLookupRep) ds).getHandle();
}
else if (ds instanceof IFSReturnCodeRep)
{
rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
}
throw new ExtendedIOException(path_, rc);
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream",
ds.getReqRepID());
throw new
InternalErrorException(Integer.toHexString(ds.getReqRepID()),
InternalErrorException.DATA_STREAM_UNKNOWN);
}
ds = null;
try
{
// Issue a get file system request.
IFSGetFileSystemReq req = new IFSGetFileSystemReq(objectHandle, userHandle);
ds = (ClientAccessDataStream) server_.sendAndReceive(req);
}
catch(ConnectionDroppedException e)
{
Trace.log(Trace.ERROR, "Byte stream server connection lost.");
connectionDropped(e);
}
catch(InterruptedException e)
{
Trace.log(Trace.ERROR, "Interrupted");
InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
try {
throwException.initCause(e);
} catch (Throwable t) {}
throw throwException;
}
// Verify the reply.
rc = 0;
if (ds instanceof IFSGetFileSystemRep)
{
fileSystemType_ = ((IFSGetFileSystemRep) ds).getFileSystemType();
}
else if (ds instanceof IFSReturnCodeRep)
{
rc = ((IFSReturnCodeRep) ds).getReturnCode();
if (rc != IFSReturnCodeRep.SUCCESS)
{
Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
}
throw new ExtendedIOException(path_, rc);
}
else
{
// Unknown data stream.
Trace.log(Trace.ERROR, "Unknown reply data stream",
ds.getReqRepID());
throw new
InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN,
Integer.toHexString(ds.getReqRepID()),null);
}
}finally{
//if(userHandle != UNINITIALIZED)
// freeUserHandle(userHandle);
if(objectHandle != UNINITIALIZED)
freeHandle(objectHandle);
}
}
switch(fileSystemType_) {
case 1 : typeString = "EPFS"; break;
case 2 : typeString = "QDLS"; break;
case 3 : typeString = "QSYS"; break;
case 4 : typeString = "NFS"; break;
case 5 : typeString = "LRFS"; break;
case 6 : typeString = "QOPT"; break;
case 7 : typeString = "QRFS"; break;
case 9 : typeString = "EPFSP"; break;
case 11 : typeString = "QNETC"; break;
case 12 : typeString = "QDTL"; break;
case 13 : typeString = "IEPFS"; break;
case 14 : typeString = "ASPQSYS"; break;
}
return typeString;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy