mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch 'origin/GP-2184-dragonmacher-remove-jmockit-6'
This commit is contained in:
@@ -22,7 +22,8 @@ import ghidra.util.BigEndianDataConverter;
|
|||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.datastruct.IntSet;
|
import ghidra.util.datastruct.IntSet;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.*;
|
import ghidra.util.task.CancelledListener;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>LocalBufferFile</code> implements a BufferFile as block-oriented
|
* <code>LocalBufferFile</code> implements a BufferFile as block-oriented
|
||||||
@@ -30,7 +31,6 @@ import ghidra.util.task.*;
|
|||||||
* not support the save operation.
|
* not support the save operation.
|
||||||
*/
|
*/
|
||||||
public class LocalBufferFile implements BufferFile {
|
public class LocalBufferFile implements BufferFile {
|
||||||
// static final Logger log = Logger.getLogger(LocalBufferFile.class);
|
|
||||||
|
|
||||||
static final long MAGIC_NUMBER = 0x2f30312c34292c2aL;
|
static final long MAGIC_NUMBER = 0x2f30312c34292c2aL;
|
||||||
|
|
||||||
@@ -118,24 +118,29 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
private int[] freeIndexes = new int[0];
|
private int[] freeIndexes = new int[0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>file</code> is the underlying storage file for this buffer file.
|
* The underlying storage file for this buffer file.
|
||||||
*/
|
*/
|
||||||
private File file;
|
private File file;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>raf</code> is the random-access object for the underlying file.
|
* The random-access object for the underlying file.
|
||||||
*/
|
*/
|
||||||
private RandomAccessFile raf;
|
private RandomAccessFile raf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>activeBlockStream</code> provides a handle to the active
|
* Provides a handle to the active OutputBlockStream used to update file via this class's
|
||||||
* OutputBlockStream used to update file via raf. This should be
|
* random access file. This should be checked during {@link #close()} to guard against
|
||||||
* checked during {@link #close()} to guard against partially
|
* partially written file. A LocalOutputBlockStream should only be used for files open for
|
||||||
* written file. A LocalOutputBlockStream should only be used
|
* writing (i.e., !readOnly).
|
||||||
* for files open for writing (i.e., !readOnly).
|
|
||||||
*/
|
*/
|
||||||
private volatile LocalOutputBlockStream activeOutputBlockStream;
|
private volatile LocalOutputBlockStream activeOutputBlockStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple factory that allows this class to support dependency injection.
|
||||||
|
*/
|
||||||
|
private static InputBlockStreamFactory inputBlockStreamFactory =
|
||||||
|
new DefaultInputBlockStreamFactory();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When <code>temporary</code> is true and this file is writable (!readOnly)
|
* When <code>temporary</code> is true and this file is writable (!readOnly)
|
||||||
* it will be deleted when disposed or closed.
|
* it will be deleted when disposed or closed.
|
||||||
@@ -152,8 +157,8 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
/**
|
/**
|
||||||
* If <code>readOnly</code> is true, this file may not be modified
|
* If <code>readOnly</code> is true, this file may not be modified
|
||||||
* via the buffer put method.
|
* via the buffer put method.
|
||||||
* A read-only file may be considered "updateable" if the canSave
|
* A read-only file may be considered "updatable" if the canSave
|
||||||
* method returns true. The term "updateable" means that a Save file
|
* method returns true. The term "updatable" means that a Save file
|
||||||
* can be obtained via the getSaveFile method.
|
* can be obtained via the getSaveFile method.
|
||||||
*/
|
*/
|
||||||
private boolean readOnly;
|
private boolean readOnly;
|
||||||
@@ -185,6 +190,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
* @param bufferSize user buffer size
|
* @param bufferSize user buffer size
|
||||||
* @param tmpPrefix temporary file prefix
|
* @param tmpPrefix temporary file prefix
|
||||||
* @param tmpExtension temporary file extension
|
* @param tmpExtension temporary file extension
|
||||||
|
* @throws IOException if there is an exception creating underlying files
|
||||||
*/
|
*/
|
||||||
LocalBufferFile(int bufferSize, String tmpPrefix, String tmpExtension) throws IOException {
|
LocalBufferFile(int bufferSize, String tmpPrefix, String tmpExtension) throws IOException {
|
||||||
this.bufferSize = bufferSize;
|
this.bufferSize = bufferSize;
|
||||||
@@ -223,8 +229,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
* Open an existing block file.
|
* Open an existing block file.
|
||||||
* @param file block file
|
* @param file block file
|
||||||
* @param readOnly if true the file will be opened read-only
|
* @param readOnly if true the file will be opened read-only
|
||||||
* @throws IOException if an IO error occurs or the incorrect magicNumber
|
* @throws IOException if an error occurs or the incorrect magicNumber was read from the file.
|
||||||
* was read from the file.
|
|
||||||
*/
|
*/
|
||||||
public LocalBufferFile(File file, boolean readOnly) throws IOException {
|
public LocalBufferFile(File file, boolean readOnly) throws IOException {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
@@ -236,13 +241,14 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Modify an existing buffer file.
|
* Modify an existing buffer file.
|
||||||
* WARNING! Use with extreme caution since this modifies
|
* <p>
|
||||||
* the original file and could destroy data if used
|
* WARNING! Use with extreme caution since this modifies the original file and could destroy
|
||||||
* improperly.
|
* data if used improperly.
|
||||||
* @param file
|
*
|
||||||
* @param bufferIndex
|
* @param file block file
|
||||||
* @param buf
|
* @param bufferIndex the index at which to place the buffer
|
||||||
* @throws IOException
|
* @param buf the buffer add to the file
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public static void poke(File file, int bufferIndex, DataBuffer buf) throws IOException {
|
public static void poke(File file, int bufferIndex, DataBuffer buf) throws IOException {
|
||||||
LocalBufferFile bf = new LocalBufferFile(file, false);
|
LocalBufferFile bf = new LocalBufferFile(file, false);
|
||||||
@@ -256,10 +262,10 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a buffer from an existing buffer file.
|
* Read a buffer from an existing buffer file.
|
||||||
* @param file
|
* @param file block file
|
||||||
* @param bufferIndex
|
* @param bufferIndex the index from which to read the buffer
|
||||||
* @return
|
* @return the buffer
|
||||||
* @throws IOException
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public static DataBuffer peek(File file, int bufferIndex) throws IOException {
|
public static DataBuffer peek(File file, int bufferIndex) throws IOException {
|
||||||
LocalBufferFile bf = new LocalBufferFile(file, false);
|
LocalBufferFile bf = new LocalBufferFile(file, false);
|
||||||
@@ -275,6 +281,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the physical file associated with this BufferFile.
|
* Returns the physical file associated with this BufferFile.
|
||||||
|
* @return the file
|
||||||
*/
|
*/
|
||||||
public File getFile() {
|
public File getFile() {
|
||||||
return file;
|
return file;
|
||||||
@@ -296,7 +303,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParameter(String name, int value) {
|
public void setParameter(String name, int value) {
|
||||||
userParms.put(name, new Integer(value));
|
userParms.put(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -335,24 +342,24 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the file ID for this file. This should only be done
|
* Assigns the file ID for this file. This should only be done when reconstructing a file.
|
||||||
* when reconstructing a file.
|
* @param id file ID
|
||||||
* @param fileId file ID
|
|
||||||
*/
|
*/
|
||||||
void setFileId(long id) {
|
void setFileId(long id) {
|
||||||
fileId = id;
|
fileId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return number of buffers countained within this file
|
* The number of buffers contained within this file.
|
||||||
|
* @return the number of buffers contained within this file
|
||||||
*/
|
*/
|
||||||
int getBufferCount() {
|
int getBufferCount() {
|
||||||
return bufferCount;
|
return bufferCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the buffer count for this file. This should only be done
|
* Assigns the buffer count for this file. This should only be done when reconstructing a
|
||||||
* when reconstructing a file.
|
* file.
|
||||||
* @param count number of valid buffers contained within this file
|
* @param count number of valid buffers contained within this file
|
||||||
*/
|
*/
|
||||||
void setBufferCount(int count) {
|
void setBufferCount(int count) {
|
||||||
@@ -360,9 +367,9 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the temporary status of this buffer file.
|
* Set the temporary status of this buffer file. Temporary buffer files are deleted when
|
||||||
* Temporary buffer files are deleted when closed.
|
* closed.
|
||||||
* @param isTemporary
|
* @param isTemporary true if temporary
|
||||||
*/
|
*/
|
||||||
void setTemporary(boolean isTemporary) {
|
void setTemporary(boolean isTemporary) {
|
||||||
temporary = isTemporary;
|
temporary = isTemporary;
|
||||||
@@ -370,9 +377,9 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rename underlying file
|
* Rename underlying file
|
||||||
* @param newFile
|
* @param newFile the new file for this class
|
||||||
* @return true if rename successful
|
* @return true if rename successful
|
||||||
* @throws IOException
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
boolean renameFile(File newFile) throws IOException {
|
boolean renameFile(File newFile) throws IOException {
|
||||||
if (raf != null) {
|
if (raf != null) {
|
||||||
@@ -389,17 +396,17 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set random access file (raf) position to the file block containing the specified buffer
|
* Set the random access file position to the file block containing the specified buffer
|
||||||
* identified by its bufferIndex. It is important to understand the distinction between
|
* identified by its bufferIndex. It is important to understand the distinction between
|
||||||
* blocks and buffers, where buffers are stored within file blocks which are slightly larger.
|
* blocks and buffers, where buffers are stored within file blocks which are slightly larger.
|
||||||
* In addition, the first file block stores the file header and is not used to store a buffer.
|
* In addition, the first file block stores the file header and is not used to store a buffer.
|
||||||
* @param bufferIndex buffer index
|
* @param bufferIndex buffer index
|
||||||
* @return file block index (=bufferIndex+1)
|
* @return file block index (=bufferIndex+1)
|
||||||
* @throws IOException
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
private int seekBufferBlock(int bufferIndex) throws IOException {
|
private int seekBufferBlock(int bufferIndex) throws IOException {
|
||||||
// Perform long multiplication to support file sizes greater than 2-GBytes
|
// Perform long multiplication to support file sizes greater than 2-GBytes
|
||||||
// Add 1 to buffer index to obtain block index (first useable buffer, buffer#0, is
|
// Add 1 to buffer index to obtain block index (first usable buffer, buffer#0, is
|
||||||
// contained within block#1 since block#0 contains file header)
|
// contained within block#1 since block#0 contains file header)
|
||||||
int blockIndex = bufferIndex + 1;
|
int blockIndex = bufferIndex + 1;
|
||||||
long offset = (long) blockIndex * (long) blockSize;
|
long offset = (long) blockIndex * (long) blockSize;
|
||||||
@@ -408,11 +415,13 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set random access file (raf) position to the specified file block and offset
|
* Set the random access file position to the specified file block and offset within that
|
||||||
* within that block. NOTE: block#0 contains the file header.
|
* block.
|
||||||
|
*
|
||||||
|
* <p>NOTE: block#0 contains the file header.
|
||||||
* @param blockIndex block index
|
* @param blockIndex block index
|
||||||
* @param offsetWithinBlock offset within file block
|
* @param offsetWithinBlock offset within file block
|
||||||
* @throws IOException
|
* @throws IOException if there is an exception reading the file
|
||||||
*/
|
*/
|
||||||
private void seekBlock(int blockIndex, int offsetWithinBlock) throws IOException {
|
private void seekBlock(int blockIndex, int offsetWithinBlock) throws IOException {
|
||||||
// Perform long multiplication to support file sizes greater than 2-GBytes
|
// Perform long multiplication to support file sizes greater than 2-GBytes
|
||||||
@@ -422,7 +431,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Read file header and initialize the user parameter and free buffer index lists.
|
* Read file header and initialize the user parameter and free buffer index lists.
|
||||||
* @throws IOException if an I/O error occurs while reading file
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
private void readHeader() throws IOException {
|
private void readHeader() throws IOException {
|
||||||
|
|
||||||
@@ -466,9 +475,8 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the user parameter and free buffer index lists and write the
|
* Store the user parameter and free buffer index lists and write the file header.
|
||||||
* file header.
|
* @throws IOException if an I/O error occurs
|
||||||
* @throws IOException if an I/O error occurs while writing file
|
|
||||||
*/
|
*/
|
||||||
private void writeHeader() throws IOException {
|
private void writeHeader() throws IOException {
|
||||||
|
|
||||||
@@ -518,7 +526,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
while (nextIndex >= 0) {
|
while (nextIndex >= 0) {
|
||||||
|
|
||||||
// Push index on stack
|
// Push index on stack
|
||||||
freeIndexList.add(new Integer(nextIndex));
|
freeIndexList.add(nextIndex);
|
||||||
|
|
||||||
// Read block to get next index
|
// Read block to get next index
|
||||||
seekBufferBlock(nextIndex);
|
seekBufferBlock(nextIndex);
|
||||||
@@ -541,9 +549,9 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
/**
|
/**
|
||||||
* Update a storage block as free and link to the next free block.
|
* Update a storage block as free and link to the next free block.
|
||||||
* @param index block index of free block
|
* @param index block index of free block
|
||||||
* @param nextFreeIndex block index of next free block, a -1 should be
|
* @param nextFreeIndex block index of next free block, a -1 should be specified to mark the
|
||||||
* specified to mark the end of the linked list.
|
* end of the linked list.
|
||||||
* @throws IOException thrown if an IO error occurs
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
void putFreeBlock(int index, int nextFreeIndex) throws IOException {
|
void putFreeBlock(int index, int nextFreeIndex) throws IOException {
|
||||||
|
|
||||||
@@ -716,7 +724,8 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Truncate the buffer file length to the specified index count.
|
* Truncate the buffer file length to the specified index count.
|
||||||
* @param indexCount
|
* @param indexCount the index count
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
void truncate(int indexCount) throws IOException {
|
void truncate(int indexCount) throws IOException {
|
||||||
|
|
||||||
@@ -802,6 +811,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* True if this is a temporary buffer file
|
||||||
* @return true if this is a temporary buffer file
|
* @return true if this is a temporary buffer file
|
||||||
*/
|
*/
|
||||||
boolean isTemporary() {
|
boolean isTemporary() {
|
||||||
@@ -809,6 +819,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* True if buffer file is closed
|
||||||
* @return true if buffer file is closed
|
* @return true if buffer file is closed
|
||||||
*/
|
*/
|
||||||
boolean isClosed() {
|
boolean isClosed() {
|
||||||
@@ -875,9 +886,8 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone this buffer file to the specified file. The file must not
|
* Clone this buffer file to the specified file. The file must not already exist. If the
|
||||||
* already exist. If the operation is cancelled or an error occurs
|
* operation is cancelled or an error occurs the file is not created.
|
||||||
* the file is not created.
|
|
||||||
* @param destinationFile destination file
|
* @param destinationFile destination file
|
||||||
* @param monitor progress monitor
|
* @param monitor progress monitor
|
||||||
* @throws IOException if IO error occurs.
|
* @throws IOException if IO error occurs.
|
||||||
@@ -905,6 +915,210 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
return file.toString();
|
return file.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a direct stream to read all blocks of this buffer file
|
||||||
|
* @return input block stream
|
||||||
|
* @throws IOException if there is an exception creating the stream
|
||||||
|
*/
|
||||||
|
public InputBlockStream getInputBlockStream() throws IOException {
|
||||||
|
return inputBlockStreamFactory.createInputBlockStream(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a direct stream to write blocks to this buffer file
|
||||||
|
* @param blockCount number of blocks to be transferred
|
||||||
|
* @return output block stream
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
public OutputBlockStream getOutputBlockStream(int blockCount) throws IOException {
|
||||||
|
return new LocalOutputBlockStream(blockCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for generating the appropriate type of {@link InputBlockStream}
|
||||||
|
* for the specified read-only bufferFile. Input stream may not supply header block in which case
|
||||||
|
* free list and file parameters may need to be set separately.
|
||||||
|
* @param bufferFile buffer file opened read-only
|
||||||
|
* @return input block stream object
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
private static InputBlockStream getInputBlockStream(BufferFile bufferFile) throws IOException {
|
||||||
|
// This method is used so we can utilize a package method and avoid putting
|
||||||
|
// it on the BufferFile interface
|
||||||
|
if (bufferFile instanceof BufferFileAdapter) {
|
||||||
|
return ((BufferFileAdapter) bufferFile).getInputBlockStream();
|
||||||
|
}
|
||||||
|
if (bufferFile instanceof LocalBufferFile) {
|
||||||
|
return ((LocalBufferFile) bufferFile).getInputBlockStream();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unsupported buffer file implementation: " + bufferFile.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for generating the appropriate type of {@link InputBlockStream}
|
||||||
|
* for the specified read-only bufferFile with an optional changeMap used
|
||||||
|
* to select which buffer should be transferred. Input stream may not supply header block
|
||||||
|
* in which case free list and file parameters may need to be set separately.
|
||||||
|
* @param bufferFile buffer file opened read-only
|
||||||
|
* @return input block stream object
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
private static InputBlockStream getInputBlockStream(BufferFile bufferFile, ChangeMap changeMap)
|
||||||
|
throws IOException {
|
||||||
|
if (changeMap == null) {
|
||||||
|
return getInputBlockStream(bufferFile);
|
||||||
|
}
|
||||||
|
// This method is used so we can utilize a package method and avoid putting
|
||||||
|
// it on the BufferFile interface
|
||||||
|
if (bufferFile instanceof ManagedBufferFileAdapter) {
|
||||||
|
return ((ManagedBufferFileAdapter) bufferFile).getInputBlockStream(changeMap.getData());
|
||||||
|
}
|
||||||
|
if (bufferFile instanceof LocalManagedBufferFile) {
|
||||||
|
return ((LocalManagedBufferFile) bufferFile).getInputBlockStream(changeMap.getData());
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unsupported buffer file implementation: " + bufferFile.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for generating the appropriate type of {@link OutputBlockStream}
|
||||||
|
* for the specified write-able bufferFile.
|
||||||
|
* @param bufferFile write-able buffer file
|
||||||
|
* @param blockCount number of blocks to be written. This should be available from
|
||||||
|
* the corresponding {@link InputBlockStream}.
|
||||||
|
* @return output block stream object
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
static OutputBlockStream getOutputBlockStream(BufferFile bufferFile, int blockCount)
|
||||||
|
throws IOException {
|
||||||
|
// This method is used so we can utilize a package method and avoid putting
|
||||||
|
// it on the BufferFile interface
|
||||||
|
if (bufferFile instanceof BufferFileAdapter) {
|
||||||
|
return ((BufferFileAdapter) bufferFile).getOutputBlockStream(blockCount);
|
||||||
|
}
|
||||||
|
if (bufferFile instanceof LocalBufferFile) {
|
||||||
|
return ((LocalBufferFile) bufferFile).getOutputBlockStream(blockCount);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unsupported buffer file implementation: " + bufferFile.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the complete content of a specified srcFile into a destFile excluding file ID. Both
|
||||||
|
* files remain open.
|
||||||
|
* @param srcFile open buffer file
|
||||||
|
* @param destFile empty buffer file which is open for writing.
|
||||||
|
* @param changeMap optional change map which indicates those buffers which must be copied.
|
||||||
|
* Any buffer index outside the range of the change map will also be copied.
|
||||||
|
* @param monitor progress monitor
|
||||||
|
* @throws IOException if IO error occurs.
|
||||||
|
* @throws CancelledException if the monitor cancels the operation.
|
||||||
|
*/
|
||||||
|
public static void copyFile(BufferFile srcFile, BufferFile destFile, ChangeMap changeMap,
|
||||||
|
TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
|
if (destFile.isReadOnly()) {
|
||||||
|
throw new IOException("File is read-only");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcFile.getBufferSize() != destFile.getBufferSize()) {
|
||||||
|
throw new IOException("Buffer sizes differ");
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor = TaskMonitor.dummyIfNull(monitor);
|
||||||
|
|
||||||
|
int srcBlockCnt;
|
||||||
|
boolean headerTransferRequired;
|
||||||
|
|
||||||
|
try (InputBlockStream in = getInputBlockStream(srcFile, changeMap)) {
|
||||||
|
headerTransferRequired = !in.includesHeaderBlock();
|
||||||
|
srcBlockCnt = in.getBlockCount();
|
||||||
|
monitor.initialize(srcBlockCnt + 2);
|
||||||
|
try (OutputBlockStream out = getOutputBlockStream(destFile, in.getBlockCount())) {
|
||||||
|
completeBlockStreamTransfer(in, out, monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
// circumvent other exceptions if cancelled
|
||||||
|
monitor.checkCanceled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headerTransferRequired) {
|
||||||
|
destFile.clearParameters();
|
||||||
|
String[] parmNames = srcFile.getParameterNames();
|
||||||
|
for (String name : parmNames) {
|
||||||
|
destFile.setParameter(name, srcFile.getParameter(name));
|
||||||
|
}
|
||||||
|
monitor.setProgress(srcBlockCnt + 1);
|
||||||
|
|
||||||
|
// Copy free index list
|
||||||
|
destFile.setFreeIndexes(srcFile.getFreeIndexes());
|
||||||
|
}
|
||||||
|
monitor.setProgress(srcBlockCnt + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a complete block stream transfer from in to out
|
||||||
|
* @param in input block stream
|
||||||
|
* @param out output block stream
|
||||||
|
* @param monitor progress and cancel monitor
|
||||||
|
* @throws CancelledException the the operation is cancelled
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
static void completeBlockStreamTransfer(InputBlockStream in, OutputBlockStream out,
|
||||||
|
TaskMonitor monitor) throws CancelledException, IOException {
|
||||||
|
int count = 0;
|
||||||
|
try (BlockStreamCancelMonitor cancelMonitor =
|
||||||
|
new BlockStreamCancelMonitor(monitor, in, out)) {
|
||||||
|
int srcBlockCnt = in.getBlockCount();
|
||||||
|
BufferFileBlock block;
|
||||||
|
while ((block = in.readBlock()) != null) {
|
||||||
|
monitor.checkCanceled();
|
||||||
|
out.writeBlock(block);
|
||||||
|
monitor.setProgress(count++);
|
||||||
|
}
|
||||||
|
if (count != srcBlockCnt) {
|
||||||
|
throw new IOException("unexpected block transfer count");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to remove all pre-save files.
|
||||||
|
* Those still open by an existing process should
|
||||||
|
* not be removed by the operating system.
|
||||||
|
* @param dir data directory containing pre-save files
|
||||||
|
* @param beforeNow if not 0, file mod time must be less than the specified time
|
||||||
|
*/
|
||||||
|
public static void cleanupOldPreSaveFiles(File dir, long beforeNow) {
|
||||||
|
File[] oldFiles = dir.listFiles(new BufferFileFilter(null, PRESAVE_FILE_EXT));
|
||||||
|
if (oldFiles == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (File oldFile : oldFiles) {
|
||||||
|
if ((beforeNow == 0 || oldFile.lastModified() < beforeNow) && oldFile.delete()) {
|
||||||
|
Msg.info(LocalBufferFile.class, "Removed old presave file: " + oldFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the recommended buffer size given a target buffer size.
|
||||||
|
* @param requestedBufferSize target buffer size
|
||||||
|
* @return recommended buffer size
|
||||||
|
*/
|
||||||
|
static int getRecommendedBufferSize(int requestedBufferSize) {
|
||||||
|
int size = (requestedBufferSize + BUFFER_PREFIX_SIZE) & -MINIMUM_BLOCK_SIZE;
|
||||||
|
if (size <= 0) {
|
||||||
|
size = MINIMUM_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
return size - BUFFER_PREFIX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================================================================================
|
||||||
|
// Inner Classes
|
||||||
|
//=================================================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>LocalBufferInputBlockStream</code> provides an input BlockStream for
|
* <code>LocalBufferInputBlockStream</code> provides an input BlockStream for
|
||||||
* transferring the entire file content associated with a read-only buffer
|
* transferring the entire file content associated with a read-only buffer
|
||||||
@@ -917,7 +1131,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct input block stream for this buffer file.
|
* Construct input block stream for this buffer file.
|
||||||
* @throws IOException
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
LocalBufferInputBlockStream() throws IOException {
|
LocalBufferInputBlockStream() throws IOException {
|
||||||
if (!isReadOnly()) {
|
if (!isReadOnly()) {
|
||||||
@@ -991,7 +1205,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct input block stream for entire file
|
* Construct input block stream for entire file
|
||||||
* @throws IOException
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
LocalFileInputBlockStream() throws IOException {
|
LocalFileInputBlockStream() throws IOException {
|
||||||
if (!readOnly) {
|
if (!readOnly) {
|
||||||
@@ -1071,7 +1285,7 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
* will never be included in the transfer.
|
* will never be included in the transfer.
|
||||||
* @param changeMapData ChangeMap data which is used in determining which
|
* @param changeMapData ChangeMap data which is used in determining which
|
||||||
* buffers should be streamed
|
* buffers should be streamed
|
||||||
* @throws IOException
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
LocalRandomInputBlockStream(byte[] changeMapData) throws IOException {
|
LocalRandomInputBlockStream(byte[] changeMapData) throws IOException {
|
||||||
if (!readOnly) {
|
if (!readOnly) {
|
||||||
@@ -1230,187 +1444,13 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
public int getBlockSize() {
|
public int getBlockSize() {
|
||||||
return blockSize;
|
return blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a direct stream to read all blocks of this buffer file
|
|
||||||
* @return input block stream
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public InputBlockStream getInputBlockStream() throws IOException {
|
|
||||||
if (!readOnly) {
|
|
||||||
throw new IOException("Read stream only permitted on read-only buffer file");
|
|
||||||
}
|
|
||||||
return new LocalFileInputBlockStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a direct stream to write blocks to this buffer file
|
|
||||||
* @param blockCount number of blocks to be transferred
|
|
||||||
* @return output block stream
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public OutputBlockStream getOutputBlockStream(int blockCount) throws IOException {
|
|
||||||
return new LocalOutputBlockStream(blockCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method for generating the appropriate type of {@link InputBlockStream}
|
|
||||||
* for the specified read-only bufferFile. Input stream may not supply header block in which case
|
|
||||||
* free list and file parameters may need to be set separately.
|
|
||||||
* @param bufferFile buffer file opened read-only
|
|
||||||
* @return input block stream object
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private static InputBlockStream getInputBlockStream(BufferFile bufferFile) throws IOException {
|
|
||||||
// This method is used so we can utilize a package method and avoid putting
|
|
||||||
// it on the BufferFile interface
|
|
||||||
if (bufferFile instanceof BufferFileAdapter) {
|
|
||||||
return ((BufferFileAdapter) bufferFile).getInputBlockStream();
|
|
||||||
}
|
|
||||||
if (bufferFile instanceof LocalBufferFile) {
|
|
||||||
return ((LocalBufferFile) bufferFile).getInputBlockStream();
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Unsupported buffer file implementation: " + bufferFile.getClass().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method for generating the appropriate type of {@link InputBlockStream}
|
|
||||||
* for the specified read-only bufferFile with an optional changeMap used
|
|
||||||
* to select which buffer should be transferred. Input stream may not supply header block
|
|
||||||
* in which case free list and file parameters may need to be set separately.
|
|
||||||
* @param bufferFile buffer file opened read-only
|
|
||||||
* @return input block stream object
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private static InputBlockStream getInputBlockStream(BufferFile bufferFile, ChangeMap changeMap)
|
|
||||||
throws IOException {
|
|
||||||
if (changeMap == null) {
|
|
||||||
return getInputBlockStream(bufferFile);
|
|
||||||
}
|
|
||||||
// This method is used so we can utilize a package method and avoid putting
|
|
||||||
// it on the BufferFile interface
|
|
||||||
if (bufferFile instanceof ManagedBufferFileAdapter) {
|
|
||||||
return ((ManagedBufferFileAdapter) bufferFile).getInputBlockStream(changeMap.getData());
|
|
||||||
}
|
|
||||||
if (bufferFile instanceof LocalManagedBufferFile) {
|
|
||||||
return ((LocalManagedBufferFile) bufferFile).getInputBlockStream(changeMap.getData());
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Unsupported buffer file implementation: " + bufferFile.getClass().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method for generating the appropriate type of {@link OutputBlockStream}
|
|
||||||
* for the specified write-able bufferFile.
|
|
||||||
* @param bufferFile write-able buffer file
|
|
||||||
* @param blockCount number of blocks to be written. This should be available from
|
|
||||||
* the corresponding {@link InputBlockStream}.
|
|
||||||
* @return output block stream object
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
static OutputBlockStream getOutputBlockStream(BufferFile bufferFile, int blockCount)
|
|
||||||
throws IOException {
|
|
||||||
// This method is used so we can utilize a package method and avoid putting
|
|
||||||
// it on the BufferFile interface
|
|
||||||
if (bufferFile instanceof BufferFileAdapter) {
|
|
||||||
return ((BufferFileAdapter) bufferFile).getOutputBlockStream(blockCount);
|
|
||||||
}
|
|
||||||
if (bufferFile instanceof LocalBufferFile) {
|
|
||||||
return ((LocalBufferFile) bufferFile).getOutputBlockStream(blockCount);
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Unsupported buffer file implementation: " + bufferFile.getClass().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy the complete content of a specfied srcFile into a destFile
|
|
||||||
* excluding file ID. Both files remain open.
|
|
||||||
* @param srcFile open buffer file
|
|
||||||
* @param destFile empty buffer file which is open for writing.
|
|
||||||
* @param changeMap optional change map which indicates those buffers which must be copied.
|
|
||||||
* Any buffer index outside the range of the change map will also be copied.
|
|
||||||
* @param monitor progress monitor
|
|
||||||
* @throws IOException if IO error occurs.
|
|
||||||
* @throws CancelledException if the monitor cancels the operation.
|
|
||||||
*/
|
|
||||||
public static void copyFile(BufferFile srcFile, BufferFile destFile, ChangeMap changeMap,
|
|
||||||
TaskMonitor monitor) throws IOException, CancelledException {
|
|
||||||
if (destFile.isReadOnly()) {
|
|
||||||
throw new IOException("File is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srcFile.getBufferSize() != destFile.getBufferSize()) {
|
|
||||||
throw new IOException("Buffer sizes differ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monitor == null) {
|
|
||||||
monitor = TaskMonitorAdapter.DUMMY_MONITOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int srcBlockCnt;
|
|
||||||
boolean headerTransferRequired;
|
|
||||||
|
|
||||||
try (InputBlockStream in = getInputBlockStream(srcFile, changeMap)) {
|
|
||||||
headerTransferRequired = !in.includesHeaderBlock();
|
|
||||||
srcBlockCnt = in.getBlockCount();
|
|
||||||
monitor.initialize(srcBlockCnt + 2);
|
|
||||||
try (OutputBlockStream out = getOutputBlockStream(destFile, in.getBlockCount())) {
|
|
||||||
completeBlockStreamTransfer(in, out, monitor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
// circumvent other exceptions if cancelled
|
|
||||||
monitor.checkCanceled();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headerTransferRequired) {
|
|
||||||
destFile.clearParameters();
|
|
||||||
String[] parmNames = srcFile.getParameterNames();
|
|
||||||
for (String name : parmNames) {
|
|
||||||
destFile.setParameter(name, srcFile.getParameter(name));
|
|
||||||
}
|
|
||||||
monitor.setProgress(srcBlockCnt + 1);
|
|
||||||
|
|
||||||
// Copy free index list
|
|
||||||
destFile.setFreeIndexes(srcFile.getFreeIndexes());
|
|
||||||
}
|
|
||||||
monitor.setProgress(srcBlockCnt + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a complete block stream transfer from in to out
|
|
||||||
* @param in input block stream
|
|
||||||
* @param out output block stream
|
|
||||||
* @param monitor progress and cancel monitor
|
|
||||||
* @throws CancelledException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
static void completeBlockStreamTransfer(InputBlockStream in, OutputBlockStream out,
|
|
||||||
TaskMonitor monitor) throws CancelledException, IOException {
|
|
||||||
int count = 0;
|
|
||||||
try (BlockStreamCancelMonitor cancelMonitor =
|
|
||||||
new BlockStreamCancelMonitor(monitor, in, out)) {
|
|
||||||
int srcBlockCnt = in.getBlockCount();
|
|
||||||
BufferFileBlock block;
|
|
||||||
while ((block = in.readBlock()) != null) {
|
|
||||||
monitor.checkCanceled();
|
|
||||||
out.writeBlock(block);
|
|
||||||
monitor.setProgress(count++);
|
|
||||||
}
|
|
||||||
if (count != srcBlockCnt) {
|
|
||||||
throw new IOException("unexpected block transfer count");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>BlockStreamCancelMonitor</code> is used to close associated BlockStreams
|
* <code>BlockStreamCancelMonitor</code> is used to close associated BlockStreams
|
||||||
* when a TaskMonitor is cancelled
|
* when a TaskMonitor is cancelled
|
||||||
*/
|
*/
|
||||||
static class BlockStreamCancelMonitor implements Closeable, CancelledListener {
|
private static class BlockStreamCancelMonitor implements Closeable, CancelledListener {
|
||||||
|
|
||||||
private TaskMonitor monitor;
|
private TaskMonitor monitor;
|
||||||
private BlockStream[] blockStreams;
|
private BlockStream[] blockStreams;
|
||||||
@@ -1467,36 +1507,23 @@ public class LocalBufferFile implements BufferFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to remove all pre-save files.
|
* A simple interface that allows for dependency injection
|
||||||
* Those still open by an existing process should
|
|
||||||
* not be removed by the operating system.
|
|
||||||
* @param dir data directory containing presave files
|
|
||||||
* @param beforeNow if not 0, file mod time must be less than the specified time
|
|
||||||
*/
|
*/
|
||||||
public static void cleanupOldPreSaveFiles(File dir, long beforeNow) {
|
public static interface InputBlockStreamFactory {
|
||||||
File[] oldFiles = dir.listFiles(new BufferFileFilter(null, PRESAVE_FILE_EXT));
|
public InputBlockStream createInputBlockStream(LocalBufferFile bf) throws IOException;
|
||||||
if (oldFiles == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (File oldFile : oldFiles) {
|
|
||||||
if ((beforeNow == 0 || oldFile.lastModified() < beforeNow) &&
|
|
||||||
oldFile.delete()) {
|
|
||||||
Msg.info(LocalBufferFile.class, "Removed old presave file: " + oldFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the recommended buffer size given a target buffer size.
|
* A factory to supply the default implementation for create an {@link InputBlockStream}
|
||||||
* @param requestedBufferSize target buffer size
|
|
||||||
* @return recommended buffer size
|
|
||||||
*/
|
*/
|
||||||
static int getRecommendedBufferSize(int requestedBufferSize) {
|
private static class DefaultInputBlockStreamFactory implements InputBlockStreamFactory {
|
||||||
int size = (requestedBufferSize + BUFFER_PREFIX_SIZE) & -MINIMUM_BLOCK_SIZE;
|
@Override
|
||||||
if (size <= 0) {
|
public InputBlockStream createInputBlockStream(LocalBufferFile bf) throws IOException {
|
||||||
size = MINIMUM_BLOCK_SIZE;
|
if (!bf.readOnly) {
|
||||||
|
throw new IOException("Read stream only permitted on read-only buffer file");
|
||||||
|
}
|
||||||
|
return bf.new LocalFileInputBlockStream();
|
||||||
}
|
}
|
||||||
return size - BUFFER_PREFIX_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void checkSameContent(BufferFile expectedBf, BufferFile inspectedBf) throws IOException {
|
// private void checkSameContent(BufferFile expectedBf, BufferFile inspectedBf) throws IOException {
|
||||||
|
|||||||
@@ -27,14 +27,17 @@ import javax.swing.table.TableColumn;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import docking.test.AbstractDockingTest;
|
||||||
import docking.widgets.table.*;
|
import docking.widgets.table.*;
|
||||||
import docking.widgets.table.constraint.ColumnConstraint;
|
import docking.widgets.table.constraint.ColumnConstraint;
|
||||||
import docking.widgets.table.constraint.MappedColumnConstraint;
|
import docking.widgets.table.constraint.MappedColumnConstraint;
|
||||||
import docking.widgets.table.constraint.dialog.*;
|
import docking.widgets.table.constraint.dialog.*;
|
||||||
import docking.widgets.table.constraint.provider.*;
|
import docking.widgets.table.constraint.provider.*;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import mockit.Mock;
|
import ghidra.util.Msg;
|
||||||
import mockit.MockUp;
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test performs operations on swing components in the test thread. I believe this is ok
|
* This test performs operations on swing components in the test thread. I believe this is ok
|
||||||
@@ -42,29 +45,17 @@ import mockit.MockUp;
|
|||||||
* involved. If this test has displays intermittent failures, then more work will be needed to
|
* involved. If this test has displays intermittent failures, then more work will be needed to
|
||||||
* fix the threading when accessing swing components.
|
* fix the threading when accessing swing components.
|
||||||
*/
|
*/
|
||||||
public class ColumnTableFilterTest {
|
public class ColumnTableFilterTest extends AbstractDockingTest {
|
||||||
private SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy");
|
private SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy");
|
||||||
private RowObjectFilterModel<Integer> tableModel;
|
private RowObjectFilterModel<Integer> tableModel;
|
||||||
private GTable gTable;
|
private GTable gTable;
|
||||||
private ColumnFilterDialogModel<Integer> filterModel;
|
private ColumnFilterDialogModel<Integer> filterModel;
|
||||||
private List<ColumnConstraint<?>> allConstraints;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() throws Exception {
|
||||||
allConstraints = loadConstraints();
|
|
||||||
// using a mock up to load discoverable column filters without performing a class search.
|
ClassSearcher.search(TaskMonitor.DUMMY);
|
||||||
new MockUp<DiscoverableTableUtils>() {
|
|
||||||
@Mock
|
|
||||||
public List<ColumnConstraint<?>> getColumnConstraints(Class<?> columnType) {
|
|
||||||
List<ColumnConstraint<?>> matches = new ArrayList<>();
|
|
||||||
for (ColumnConstraint<?> columnConstraint : allConstraints) {
|
|
||||||
if (columnConstraint.getColumnType().equals(columnType)) {
|
|
||||||
matches.add(columnConstraint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matches;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
tableModel = createTableModel();
|
tableModel = createTableModel();
|
||||||
gTable = new GTable(tableModel);
|
gTable = new GTable(tableModel);
|
||||||
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ import java.io.IOException;
|
|||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import db.buffers.*;
|
import db.buffers.*;
|
||||||
|
import db.buffers.LocalBufferFile.InputBlockStreamFactory;
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGenericTest;
|
||||||
import ghidra.framework.store.local.LocalFileSystem;
|
import ghidra.framework.store.local.LocalFileSystem;
|
||||||
import ghidra.framework.store.local.LocalFolderItem;
|
import ghidra.framework.store.local.LocalFolderItem;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import mockit.*;
|
|
||||||
import utilities.util.FileUtilities;
|
import utilities.util.FileUtilities;
|
||||||
|
|
||||||
public class VersionFailureRecoveryTest extends AbstractGenericTest {
|
public class VersionFailureRecoveryTest extends AbstractGenericTest {
|
||||||
@@ -65,7 +65,7 @@ public class VersionFailureRecoveryTest extends AbstractGenericTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testAddToVersionControlFailure() {
|
public void testAddToVersionControlFailure() {
|
||||||
|
|
||||||
new FakeBadBufferFile(); // setup for mocking
|
setInstanceField("inputBlockStreamFactory", LocalBufferFile.class, factory);
|
||||||
|
|
||||||
LocalBufferFile fakeBadBufferFile = null;
|
LocalBufferFile fakeBadBufferFile = null;
|
||||||
try {
|
try {
|
||||||
@@ -99,17 +99,54 @@ public class VersionFailureRecoveryTest extends AbstractGenericTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FakeBadBufferFile extends MockUp<LocalBufferFile> {
|
private InputBlockStreamFactory factory = new InputBlockStreamFactory() {
|
||||||
|
|
||||||
@Mock
|
@Override
|
||||||
|
public InputBlockStream createInputBlockStream(LocalBufferFile bf) throws IOException {
|
||||||
|
return new InputBlockStream() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean includesHeaderBlock() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockSize() {
|
||||||
|
return bf.getBufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferFileBlock readBlock() throws IOException {
|
||||||
|
throw new IOException("forced block read failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockCount() {
|
||||||
|
return bf.getIndexCount();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
private class FakeBadBufferFile extends LocalBufferFile {
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getIndexCount() {
|
public int getIndexCount() {
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mock
|
@Override
|
||||||
public InputBlockStream getInputBlockStream(Invocation invocation) {
|
public InputBlockStream getInputBlockStream() {
|
||||||
|
|
||||||
LocalBufferFile bufferFile = invocation.getInvokedInstance();
|
LocalBufferFile bufferFile = null;
|
||||||
|
|
||||||
return new InputBlockStream() {
|
return new InputBlockStream() {
|
||||||
|
|
||||||
@@ -140,5 +177,5 @@ public class VersionFailureRecoveryTest extends AbstractGenericTest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user