Skip to content

Commit 93b6021

Browse files
committed
FileLocator: better handling of locators routines - zip-file recognition - ZipStreamProvider
1 parent dd25fb8 commit 93b6021

File tree

1 file changed

+69
-38
lines changed

1 file changed

+69
-38
lines changed

snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocator.java

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
import electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException;
3636
import electrostatic4j.snaploader.util.SnapLoaderLogger;
37-
3837
import java.io.*;
3938
import java.util.logging.Level;
4039
import java.util.zip.ZipEntry;
@@ -46,7 +45,7 @@
4645
*
4746
* @author pavl_g
4847
*/
49-
public class FileLocator implements InputStreamProvider {
48+
public class FileLocator implements ZipStreamProvider {
5049

5150
/**
5251
* The input stream associated with the located filesystem.
@@ -59,27 +58,39 @@ public class FileLocator implements InputStreamProvider {
5958
*/
6059
protected FileLocalizingListener fileLocalizingListener;
6160

62-
protected String directory;
61+
protected ZipFile compression;
62+
63+
protected String compressionPath;
6364

6465
protected String filePath;
6566

6667
protected ZipCompressionType compressionType;
6768

69+
/**
70+
* Locates the library inside the stock jar filesystem.
71+
* This object leaks an input stream.
72+
*
73+
* @param filePath the path to the dynamic native library inside that jar filesystem
74+
*/
75+
public FileLocator(String filePath) {
76+
this.filePath = filePath;
77+
}
78+
6879
/**
6980
* Locates a filesystem inside an external zip compression, the zip filesystem is defined as a {@link ZipFile} object and
7081
* the locatable filesystem is defined as a {@link ZipEntry} object.
7182
* <p>
7283
* Warning: This object leaks a buffered stream, either use try-with-resources, or handle your
7384
* memory manually!
7485
*
75-
* @param directory the absolute path for the external jar filesystem
86+
* @param compressionPath the absolute path for the external jar filesystem
7687
* @param filePath the path to the filesystem to be extracted
7788
* @param compressionType the type of the zip compression, ZIP or JAR
7889
*
7990
* @throws IOException if the jar to be located is not found or an interrupted I/O exception has occured
8091
*/
81-
public FileLocator(String directory, String filePath, ZipCompressionType compressionType) throws IOException {
82-
this.directory = directory;
92+
public FileLocator(String compressionPath, String filePath, ZipCompressionType compressionType) throws IOException {
93+
this.compressionPath = compressionPath;
8394
this.filePath = filePath;
8495
this.compressionType = compressionType;
8596
}
@@ -94,53 +105,54 @@ protected FileLocator() {
94105
@Override
95106
public void initialize(int size) throws IOException {
96107
// 1) sanity-check for double initializing
97-
// 2) sanity-check for pre-initialization using other routines
98-
// (e.g., classpath resources stream).
99108
if (this.fileInputStream != null) {
100109
SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)",
101110
"File locator already initialized using external routines with hash key #" + getHashKey());
102111
return;
103112
}
104113
try {
105-
final ZipFile compression = compressionType.createNewCompressionObject(directory);
106-
final ZipEntry zipEntry = compression.getEntry(filePath);
107-
validateFileLocalization(zipEntry);
108-
if (size > 0) {
109-
this.fileInputStream = new BufferedInputStream(compression.getInputStream(zipEntry), size);
110-
SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)",
111-
"File locator initialized with hash key #" + getHashKey());
112-
return;
114+
115+
// 2) sanity-check for initialization routines
116+
// (e.g., classpath resources stream v.s. external compression).
117+
if (compressionPath == null || compressionType == null) {
118+
classPathRoutine();
119+
} else {
120+
externalCompressionRoutine(size);
121+
}
122+
123+
// fire the success listener if the file localization has passed!
124+
if (fileLocalizingListener != null) {
125+
fileLocalizingListener.onFileLocalizationSuccess(this);
113126
}
114-
this.fileInputStream = compression.getInputStream(zipEntry);
115-
SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)",
116-
"File locator initialized with hash key #" + getHashKey());
117127
} catch (Exception e) {
118128
close();
119-
throw new FilesystemResourceInitializationException(
129+
final FilesystemResourceInitializationException exception = new FilesystemResourceInitializationException(
120130
"Failed to initialize the file locator handler #" + getHashKey(), e);
131+
// fire the failure listener when file localization fails and pass
132+
// the causative exception
133+
if (fileLocalizingListener != null) {
134+
fileLocalizingListener.onFileLocalizationFailure(this, exception);
135+
}
136+
throw exception;
121137
}
122138
}
123139

124-
/**
125-
* Validates the file localization process inside the compression.
126-
*
127-
* @throws FileNotFoundException if the localization of the file inside
128-
* the specified compression has failed.
129-
*/
130-
protected void validateFileLocalization(final ZipEntry zipEntry) throws FileNotFoundException {
131-
if (zipEntry != null) {
132-
if (fileLocalizingListener != null) {
133-
fileLocalizingListener.onFileLocalizationSuccess(this);
134-
}
135-
} else {
136-
final FileNotFoundException fileNotFoundException =
137-
new FileNotFoundException("File locator has failed to locate the file inside the compression!");
140+
protected void classPathRoutine() {
141+
SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)",
142+
"File locator initialized using classpath routine with hash key #" + getHashKey());
143+
this.fileInputStream = getClass().getResourceAsStream(filePath);
144+
}
138145

139-
if (fileLocalizingListener != null) {
140-
fileLocalizingListener.onFileLocalizationFailure(this, fileNotFoundException);
141-
}
142-
throw fileNotFoundException;
146+
protected void externalCompressionRoutine(int size) throws IOException {
147+
this.compression = compressionType.createNewCompressionObject(compressionPath);
148+
final ZipEntry zipEntry = compression.getEntry(filePath);
149+
if (size > 0) {
150+
this.fileInputStream = new BufferedInputStream(compression.getInputStream(zipEntry), size);
151+
} else {
152+
this.fileInputStream = compression.getInputStream(zipEntry);
143153
}
154+
SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)",
155+
"File locator initialized using external compression routine with hash key #" + getHashKey());
144156
}
145157

146158
@Override
@@ -150,10 +162,24 @@ public InputStream getFileInputStream() {
150162

151163
@Override
152164
public void close() throws IOException {
165+
// this is executed in all routines
166+
// it updates the CleanableResource object
167+
// for the Compression Routines
153168
if (fileInputStream != null) {
154169
fileInputStream.close();
155170
fileInputStream = null;
156171
}
172+
173+
// this will be bypassed in the case of using other non-compression routines to
174+
// initialize the file streams (e.g., the classpath routines).
175+
if (compression != null) {
176+
// this closes all the streams associated with it (if they are not closed)
177+
// aka.
178+
// the file entries stream
179+
// and the native resources for this object
180+
compression.close();
181+
compression = null;
182+
}
157183
SnapLoaderLogger.log(Level.INFO, getClass().getName(),
158184
"close", "File locator #" + getHashKey() + " resources closed!");
159185
}
@@ -162,4 +188,9 @@ public void close() throws IOException {
162188
public void setFileLocalizingListener(FileLocalizingListener fileLocalizingListener) {
163189
this.fileLocalizingListener = fileLocalizingListener;
164190
}
191+
192+
@Override
193+
public ZipFile getCompression() {
194+
return compression;
195+
}
165196
}

0 commit comments

Comments
 (0)