src.com.ibm.as400.access.IFSFileEnumeration 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: IFSFileEnumeration.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-2002 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
//
// @D5 - 06/18/2007 - Changes to better handle when objects are filtered from
// the list returned by the IFS File Server.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.io.IOException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
class IFSFileEnumeration
implements Enumeration
{
// The block size is hardcoded based on the value chosen by OpNav.
// For now, it is not configurable.
private static final int MAXIMUM_GET_COUNT_ = 128;
private IFSFile[] contents_;
private IFSFile[] contentsPending_; // Staging area for contents_ @A1a
private IFSFile file_;
private IFSFileFilter filter_;
private int index_;
private String pattern_;
//private String restartName_;
//private byte[] restartID_; // @C3a
private boolean isRestartByNameSupported_; // @A1a
IFSFileEnumeration(IFSFile file, IFSFileFilter filter, String pattern)
throws AS400SecurityException, IOException
{
file_ = file;
filter_ = filter;
pattern_ = pattern;
// @A1a:
// Note from the File Server team on 02/05/01:
// "The vnode architecture allows a file system to use the cookie
// (Restart Number) or a Restart Name to find the entry
// that processing should start at.
// QDLS and QSYS allow Restart Name, but /root (EPFS) does not."
// "Restart by name" only works for QSYS.LIB and QDLS. @A1a
String path = file_.getPath().toUpperCase();
int indexOfQSYS = path.indexOf("/QSYS.LIB"); // @D1A - added support to look for /IASPNAME../QSYS.LIB
if (path.startsWith("/QSYS.LIB") || path.startsWith("/QDLS.LIB") ||
path.startsWith("/QDLS") || ((indexOfQSYS != -1) && (indexOfQSYS <= 11))) { // @C3a //@D1C - added support to look for /IASPNAME../QSYS.LIB
isRestartByNameSupported_ = true;
contentsPending_ = loadPendingBlock((String)null);// "Prime the pump" with the first block. @A1a @C3c
/*if (contentsPending_ != null) { // @C3a
restartName_ = contentsPending_[contentsPending_.length - 1].getName();
} */
}
else { // Use "restart by ID".
isRestartByNameSupported_ = false;
//@C3d if (Trace.traceOn_) Trace.log(Trace.WARNING,
//@C3d "Restart-by-name is not supported for directory " + path);
contentsPending_ = loadPendingBlock((byte[])null);// "Prime the pump" with the first block. @C3a
/*if (contentsPending_ != null) { // @C3a
restartID_ = contentsPending_[contentsPending_.length - 1].getRestartID();
} */
}
getNextBlock();
}
public boolean hasMoreElements()
{
return ((contents_ != null && index_ < contents_.length) ||
(contentsPending_ != null)); // @A1c
}
// @A1a @C3c
private IFSFile[] loadPendingBlock(String restartName)
throws AS400SecurityException, IOException
{
IFSFile[] block = null;
// Design note: Using contents_ and contentsPending_ allows us to "look ahead" and detect end-of-list in all situations, including when the number of matching files in the directory is an exact multiple of MAXIMUM_GET_COUNT.
// Continue reading/loading until we have something to return (that @D5A
// didn't all get filtered out) @D5A
do //@D5A
{ //@D5A
block = file_.listFiles0(filter_, pattern_, MAXIMUM_GET_COUNT_, restartName);
restartName = file_.getListFiles0LastRestartName(); //@D5A
} //@D5A
while ((block.length == 0) && (file_.getListFiles0LastNumObjsReturned() > 0)); //@D5A
if (block.length == 0) block = null; // Never return an empty list.
return block;
}
// @C3a
private IFSFile[] loadPendingBlock(byte[] restartID)
throws AS400SecurityException, IOException
{
IFSFile[] block = null;
// Design note: Using contents_ and contentsPending_ allows us to "look ahead" and detect end-of-list in all situations, including when the number of matching files in the directory is an exact multiple of MAXIMUM_GET_COUNT.
// Continue reading/loading until we have something to return (that @D5A
// didn't all get filtered out) @D5A
do //@D5A
{ //@D5A
block = file_.listFiles0(filter_, pattern_, MAXIMUM_GET_COUNT_, restartID);
restartID = file_.getListFiles0LastRestartID(); //@D5A
} //@D5A
while ((block.length == 0) && (file_.getListFiles0LastNumObjsReturned() > 0)); //@D5A
if (block.length == 0) block = null; // Never return an empty list.
return block;
}
// Transfers the "pending block" into the "current block".
// Assumes loadPendingBlock() has been called at least once, to initialize contentsPending_.
private void getNextBlock()
throws AS400SecurityException, IOException
{
// @A1a
if (contentsPending_ == null) {
if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC,
"getNextBlock() was called when contentsPending_==null.");
return;
}
// Transfer the "pending contents" into "current contents".
contents_ = contentsPending_;
contentsPending_ = null; // @C3M
index_ = 0;
// If contentsPending held fewer than max_get_count entries, we know that there are no more entries remaining to be read from the server.
// @R5A Above comments are not true, as if there is IFSFileFilter specified, the content_ length will be handled and the length may not get the Max value even if there is still block not read.
// Note: Prior to V5R2, the file list returned by the "List Contents of Directory" request included "." and "..", which get weeded out by IFSFileImplRemote, so we need to check for (max_get_count - 2). @C3A
if (file_.getListFiles0LastNumObjsReturned() == 0 || !isContainWildcard(pattern_)) { // No objects last time. @D5C If no wildcard in pattern, we only need one time reading as no more will return, otherwise it loops for using restartname //@R5C
// We're done. // @C3C
}
else // previous listFiles0 returned 1 to max_get_count number of objects
{
if (isRestartByNameSupported_)
{
// Load the next block from the system.
contentsPending_ = loadPendingBlock(file_.getListFiles0LastRestartName());// @C3c @D5C
}
else
{
// Load the next block from the system.
byte[] restartID = file_.getListFiles0LastRestartID();
// See if a zero-valued restartID was returned.
if (isAllZeros(restartID))
{
if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC,
"IFSFileEnumeration::getNextBlock(): A zero-valued restartID was returned.");
// Try setting the last filename returned, as the "restart name" for the next request.
// Note that this is the only circumstance where the File Server supports "restart by name" for file systems other than QSYS and QDLS.
if (contents_ != null && contents_.length != 0) {
String restartName = contents_[contents_.length-1].getName();
if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC,
"IFSFileEnumeration::getNextBlock(): Specifying restartName '"+restartName+"' for next request.");
contentsPending_ = loadPendingBlock(restartName);
return;
}
else {
if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC,
"IFSFileEnumeration::getNextBlock(): No restartName available from prior reply.");
}
}
contentsPending_ = loadPendingBlock(restartID);// @C3c @D5C
}
}
}
private static final boolean isAllZeros(byte[] arry)
{
if (arry == null || arry.length == 0) return false;
for (int i=0; i0)
return pattern.indexOf("*")!=-1|| pattern.indexOf("?")!=-1;
return false;
}
public Object nextElement()
{
if (index_ < contents_.length)
return contents_[index_++];
else if (contentsPending_ == null)
throw new NoSuchElementException();
else {
try {
getNextBlock();
}
catch(Exception e) {
throw new NoSuchElementException();
}
return contents_[index_++];
}
}
}