![JAR search and dependency download from the Maven repository](/logo.png)
jcommon.extract.Resources Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of init Show documentation
Show all versions of init Show documentation
Java library for simple extracting and processing of embedded resources at runtime.
The newest version!
package jcommon.extract;
import jcommon.core.Namespaces;
import jcommon.core.StringUtil;
import jcommon.init.Loader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathException;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import static jcommon.extract.ResourceUtils.createUnprivilegedExecutorService;
import static jcommon.extract.ResourceUtils.stringAttributeValue;
/**
* Reads a simple XML file that describes files to be extracted.
*
* @author David Hoyt
*/
public class Resources {
//
public static final String
ATTRIBUTE_NAME = "name"
;
public static final Resources
Empty = new Resources(StringUtil.empty, new IResourcePackage[0])
;
public static final Future CompletedFuture = new Future() {
@Override
public final boolean cancel(boolean bln) {
return true;
}
@Override
public final boolean isCancelled() {
return false;
}
@Override
public final boolean isDone() {
return true;
}
@Override
public final Object get() throws InterruptedException, ExecutionException {
return null;
}
@Override
public final Object get(long l, TimeUnit tu) throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
};
//
//
protected Reference registryReference = null;
protected String name;
protected boolean loaded = false;
protected boolean processed = false;
protected final Object lock = new Object();
protected long totalResourceSize;
protected int totalResourceCount;
protected IResourcePackage[] packages;
protected String[] references;
//
//
public Resources(final IResourcePackage... Packages) {
initFromPackages(StringUtil.empty, null, Packages);
}
public Resources(final String Name, final IResourcePackage... Packages) {
initFromPackages(Name, null, Packages);
}
public Resources(final String[] References, final IResourcePackage... Packages) {
initFromPackages(StringUtil.empty, References, Packages);
}
public Resources(final String Name, final String[] References, final IResourcePackage... Packages) {
initFromPackages(Name, References, Packages);
}
public Resources(final IVariableProcessor VariableProcessor, final InputStream XMLData) throws XPathException, ParserConfigurationException, SAXException, IOException {
initFromXML(ResourceProcessorFactory.DEFAULT_INSTANCE, VariableProcessor, XMLData);
}
public Resources(final ResourceProcessorFactory ProcessorFactory, final IVariableProcessor VariableProcessor, final InputStream XMLData) throws XPathException, ParserConfigurationException, SAXException, IOException {
initFromXML(ProcessorFactory, VariableProcessor, XMLData);
}
protected void initFromPackages(final String Name, final String[] References, final IResourcePackage[] Packages) {
if (Packages == null)
throw new java.lang.NullPointerException("Processors cannot be null");
this.name = Name;
this.packages = Packages;
this.references = References;
initAfter();
}
protected void initFromXML(final ResourceProcessorFactory ProcessorFactory, final IVariableProcessor VariableProcessor, final InputStream XMLData) throws XPathException, ParserConfigurationException, SAXException, IOException {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final XPathFactory xpathFactory = XPathFactory.newInstance();
final XPath xpath = xpathFactory.newXPath();
//Creates a context that always has "jcommon" as a prefix -- useful for xpath evaluations
xpath.setNamespaceContext(Namespaces.createNamespaceContext());
this.packages = read(ProcessorFactory, VariableProcessor, xpath, builder.parse(XMLData));
initAfter();
}
protected void initAfter() {
calculateTotals();
loaded = true;
}
//
//
protected static void checkRegistryInitialization() {
if (!Loader.areRegistryReferencesInitialized()) {
try {
Loader.initializeRegistryReferences();
} catch(Throwable t) {
if (t instanceof ResourceException)
throw (ResourceException)t;
else
throw new ResourceException("Error initializing registry", t);
}
}
}
protected void calculateTotals() {
//Calculate total size and resource count
for(IResourcePackage pkg : packages) {
if (pkg == null)
continue;
totalResourceCount += pkg.getTotalResourceCount();
totalResourceSize += pkg.getTotalSize();
}
}
protected void notifyProgressBegin(jcommon.extract.IResourceProgressListener progress, long startTime) {
if (progress != null)
progress.begin(getTotalResourceCount(), getTotalPackageCount(), getTotalResourceSize(), startTime);
}
protected void notifyProgressReportResourceCompleted(IResourceProgressListener progress, IResourceProcessor resource, IResourcePackage pkg, long totalBytes, int totalResources, int totalPkgs, long startTime, String message) {
if (progress != null)
progress.reportResourceComplete(resource, pkg, getTotalResourceCount(), getTotalPackageCount(), getTotalResourceSize(), totalBytes, totalResources, totalPkgs, startTime, Math.abs(System.currentTimeMillis() - startTime), message);
}
protected void notifyProgressReportPackageCompleted(IResourceProgressListener progress, IResourcePackage pkg, long totalBytes, int totalResources, int totalPkgs, long startTime, String message) {
if (progress != null)
progress.reportPackageComplete(pkg, getTotalResourceCount(), getTotalPackageCount(), getTotalResourceSize(), totalBytes, totalResources, totalPkgs, startTime, Math.abs(System.currentTimeMillis() - startTime), message);
}
protected void notifyProgressError(IResourceProgressListener progress, Throwable exception, String message) {
if (progress != null)
progress.error(exception, message);
}
protected void notifyProgressEnd(IResourceProgressListener progress, boolean success, long totalBytes, int totalResources, int totalPkgs, long startTime, long endTime) {
if (progress != null)
progress.end(success, getTotalResourceCount(), getTotalPackageCount(), getTotalResourceSize(), totalBytes, totalResources, totalPkgs, startTime, endTime);
}
//
//
public String getName() {
return name;
}
public boolean isLoaded() {
return loaded;
}
public boolean isProcessed() {
return processed;
}
public String[] getReferences() {
return references;
}
public int getTotalPackageCount() {
return packages.length;
}
public int getTotalResourceCount() {
return totalResourceCount;
}
public long getTotalResourceSize() {
return totalResourceSize;
}
public IResourcePackage[] getPackages() {
return packages;
}
public Reference getRegistryReference() {
return registryReference;
}
//
//
//
public Future extract() {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return extract(references, packages, svc, IResourceFilter.None, IResourceProgressListener.None, IResourceCallback.None);
} finally {
svc.shutdown();
}
}
public Future extract(final IResourceCallback callback) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return extract(references, packages, svc, IResourceFilter.None, IResourceProgressListener.None, callback);
} finally {
svc.shutdown();
}
}
public Future extract(final IResourceProgressListener progress) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return extract(references, packages, svc, IResourceFilter.None, progress, IResourceCallback.None);
} finally {
svc.shutdown();
}
}
public Future extract(final IResourceFilter filter) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return extract(references, packages, svc, filter, IResourceProgressListener.None, IResourceCallback.None);
} finally {
svc.shutdown();
}
}
public Future extract(final IResourceFilter filter, final IResourceCallback callback) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return extract(references, packages, svc, filter, IResourceProgressListener.None, callback);
} finally {
svc.shutdown();
}
}
public Future extract(final IResourceProgressListener progress, final IResourceCallback callback) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return extract(references, packages, svc, IResourceFilter.None, progress, callback);
} finally {
svc.shutdown();
}
}
public Future extract(final IResourceFilter filter, final IResourceProgressListener progress, final IResourceCallback callback) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return extract(references, packages, svc, filter, progress, callback);
} finally {
svc.shutdown();
}
}
public Future extract(final ExecutorService executor, final IResourceFilter filter, final IResourceProgressListener progress, final IResourceCallback callback) {
return extract(references, packages, executor, filter, progress, callback);
}
//
/* public boolean preprocessEnvVars() {
return processEnvVars(packages, IResourceFilter.None);
}
public boolean preprocessEnvVars(final IResourceFilter filter) {
return processEnvVars(packages, filter);
} /**/
public Future extract(final String[] refs, final IResourcePackage[] pkgs, final ExecutorService executor, final IResourceFilter filter, final IResourceProgressListener progress, final IResourceCallback callback) {
checkRegistryInitialization();
synchronized(lock) {
if (processed) {
//If we've already processed this resource, then just mimic a
//typical extraction process but don't actually do anything.
if (progress == null)
return CompletedFuture;
//Extract nothing, but make sure that
return executor.submit(new Runnable() {
@Override
public void run() {
try {
//
if (false)
throw new InterruptedException();
//
//
if (callback != null)
callback.prepare(Resources.this);
//
if (progress != null) {
long startTime = System.currentTimeMillis();
notifyProgressBegin(progress, startTime);
notifyProgressEnd(progress, true, totalResourceSize, totalResourceCount, packages != null ? packages.length : 0, startTime, startTime);
}
//
if (callback != null)
callback.completed(Resources.this);
//
} catch(InterruptedException ie) {
//
if (callback != null)
callback.cancelled(Resources.this);
//
} catch(CancellationException ce) {
//
if (callback != null)
callback.cancelled(Resources.this);
//
} catch(RejectedExecutionException ree) {
//
if (callback != null)
callback.cancelled(Resources.this);
//
} catch(Throwable t) {
//
if (progress != null)
progress.error(t, t.getMessage());
if (callback != null)
callback.error(Resources.this);
//
}
}
});
}
return executor.submit(new Runnable() {
@Override
public void run() {
synchronized(lock) {
try {
//
if (false)
throw new InterruptedException();
//
//
if (callback != null)
callback.prepare(Resources.this);
//
if (!processed) {
//Do the real work
extractResources(refs, pkgs, filter, progress);
//Mark as processed
processed = true;
}
//
if (callback != null)
callback.completed(Resources.this);
//
} catch(InterruptedException ie) {
//
if (callback != null)
callback.cancelled(Resources.this);
//
} catch(CancellationException ce) {
//
if (callback != null)
callback.cancelled(Resources.this);
//
} catch(RejectedExecutionException ree) {
//
if (callback != null)
callback.cancelled(Resources.this);
//
} catch(Throwable t) {
//
if (callback != null)
callback.error(Resources.this);
//
}
}
}
});
}
}
//
//
//
public static final Future extractAll(final IResourcePackage... packages) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return newInstance((String[])null, packages).extract(svc, IResourceFilter.None, IResourceProgressListener.None, IResourceCallback.None);
} finally {
svc.shutdown();
}
}
public static final Future extractAll(final String[] refs, final IResourcePackage... packages) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return newInstance(refs, packages).extract(svc, IResourceFilter.None, IResourceProgressListener.None, IResourceCallback.None);
} finally {
svc.shutdown();
}
}
public static final Future extractAll(final IResourceCallback callback, final IResourcePackage... packages) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return newInstance((String[])null, packages).extract(svc, IResourceFilter.None, IResourceProgressListener.None, callback);
} finally {
svc.shutdown();
}
}
public static final Future extractAll(final IResourceProgressListener progress, final IResourceCallback callback, final IResourcePackage... packages) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return newInstance((String[])null, packages).extract(svc, IResourceFilter.None, progress, callback);
} finally {
svc.shutdown();
}
}
public static final Future extractAll(final IResourceFilter filter, final IResourceProgressListener progress, final IResourceCallback callback, final IResourcePackage... packages) {
final ExecutorService svc = createUnprivilegedExecutorService();
try {
return newInstance((String[])null, packages).extract(svc, filter, progress, callback);
} finally {
svc.shutdown();
}
}
public static final Future extractAll(final ExecutorService executor, final IResourceFilter filter, final IResourceProgressListener progress, final IResourceCallback callback, final IResourcePackage... packages) {
return newInstance((String[])null, packages).extract(executor, filter, progress, callback);
}
public static final Future extractAll(final ExecutorService executor, final IResourceFilter filter, final IResourceProgressListener progress, final IResourceCallback callback, final String[] refs, final IResourcePackage... packages) {
return newInstance(refs, packages).extract(executor, filter, progress, callback);
}
//
//
public static final Resources newInstance(final IResourcePackage... Packages) {
return new Resources(Packages);
}
public static final Resources newInstance(final String Name, final IResourcePackage... Packages) {
return new Resources(Name, Packages);
}
public static final Resources newInstance(final String[] References, final IResourcePackage... Packages) {
return new Resources(References, Packages);
}
public static final Resources newInstance(final String Name, final String[] References, final IResourcePackage... Packages) {
return new Resources(Name, References, Packages);
}
public static final Resources newInstance(final String ResourceName) {
return newInstance(VariableProcessorFactory.newInstance(), ResourceName);
}
public static final Resources newInstance(final File XMLFile) {
return newInstance(VariableProcessorFactory.newInstance(), XMLFile);
}
public static final Resources newInstance(final InputStream XMLData) {
return newInstance(VariableProcessorFactory.newInstance(), XMLData);
}
public static final Resources newInstance(final ResourceProcessorFactory ProcessorFactory, final String ResourceName) {
return newInstance(ProcessorFactory, VariableProcessorFactory.newInstance(), ResourceName);
}
public static final Resources newInstance(final ResourceProcessorFactory ProcessorFactory, final File XMLFile) {
return newInstance(ProcessorFactory, VariableProcessorFactory.newInstance(), XMLFile);
}
public static final Resources newInstance(final ResourceProcessorFactory ProcessorFactory, final InputStream XMLData) {
return newInstance(ProcessorFactory, VariableProcessorFactory.newInstance(), XMLData);
}
public static final Resources newInstance(final IVariableProcessor VariableProcessor, final String ResourceName) {
return newInstance(ResourceProcessorFactory.DEFAULT_INSTANCE, VariableProcessor, ResourceName);
}
public static final Resources newInstance(final IVariableProcessor VariableProcessor, final File XMLFile) {
return newInstance(ResourceProcessorFactory.DEFAULT_INSTANCE, VariableProcessor, XMLFile);
}
public static final Resources newInstance(final IVariableProcessor VariableProcessor, final InputStream XMLData) {
return newInstance(ResourceProcessorFactory.DEFAULT_INSTANCE, VariableProcessor, XMLData);
}
public static final Resources newInstance(final ResourceProcessorFactory ProcessorFactory, final IVariableProcessor VariableProcessor, final String ResourceName) {
return newInstance(ProcessorFactory, VariableProcessor, Resources.class.getResourceAsStream(ResourceName));
}
public static final Resources newInstance(final ResourceProcessorFactory ProcessorFactory, final IVariableProcessor VariableProcessor, final File XMLFile) {
FileInputStream fis = null;
try {
return newInstance(ProcessorFactory, VariableProcessor, (fis = new FileInputStream(XMLFile)));
} catch(ResourceException t) {
throw t;
} catch(Throwable t) {
throw new ResourceException("Unable to preprocess resource file", t);
} finally {
try {
if (fis != null)
fis.close();
} catch(IOException ie) {
}
}
}
public static final Resources newInstance(final ResourceProcessorFactory ProcessorFactory, final IVariableProcessor VariableProcessor, final InputStream XMLData) {
try {
return new Resources(VariableProcessor, XMLData);
} catch(ResourceException t) {
throw t;
} catch(Throwable t) {
throw new ResourceException("Unable to preprocess resource file", t);
}
}
//
//
//
protected IResourcePackage[] read(final ResourceProcessorFactory processorFactory, final IVariableProcessor variableProcessor, final XPath xpath, final Document document) throws XPathException {
Node node;
NodeList lst;
IResourcePackage pkg;
List pkgs = new ArrayList(1);
//Collapse whitespace nodes
document.normalize();
//Get the top-level document element,
final Element top = document.getDocumentElement();
//
if ((node = (Node)xpath.evaluate("//Resources", top, XPathConstants.NODE)) != null) {
this.name = stringAttributeValue(variableProcessor, StringUtil.empty, node, ATTRIBUTE_NAME);
if (StringUtil.isNullOrEmpty(name))
throw new ResourceException("Invalid resource name. It cannot be empty.");
this.registryReference = Registry.add(name, this);
}
//
//
//Locate tags
if ((lst = (NodeList)xpath.evaluate("//Resources/References/Add", top, XPathConstants.NODESET)) != null && lst.getLength() > 0) {
final List refs = new ArrayList(lst.getLength());
//Iterate over every tag
for(int i = 0; i < lst.getLength() && (node = lst.item(i)) != null; ++i) {
final String refName = stringAttributeValue(variableProcessor, StringUtil.empty, node, ATTRIBUTE_NAME);
if (!StringUtil.isNullOrEmpty(refName) && !this.name.equalsIgnoreCase(refName))
refs.add(refName);
}
this.references = refs.toArray(new String[refs.size()]);
}
//
//
//Locate tags
if ((lst = (NodeList)xpath.evaluate("//Resources/Extract", top, XPathConstants.NODESET)) == null || lst.getLength() <= 0)
return IResourcePackage.EMPTY;
//Iterate over every tag
for(int i = 0; i < lst.getLength() && (node = lst.item(i)) != null; ++i) {
//Ask the package to read it
if ((pkg = Package.newInstance(processorFactory, variableProcessor, node, xpath, document)) != null)
pkgs.add(pkg);
}
//
//Create an array and return it
return pkgs.toArray(new IResourcePackage[pkgs.size()]);
}
protected void extractResources(final String[] refs, final IResourcePackage[] pkgs, final IResourceFilter filter, final IResourceProgressListener progress) throws Throwable {
extractResources(0, refs, pkgs, filter, progress);
}
protected void extractResources(final int level, final String[] refs, final IResourcePackage[] pkgs, final IResourceFilter filter, final IResourceProgressListener progress) throws Throwable {
//Please note that this is executed in a separate thread.
//It can be cancelled or interrupted at any time.
int totalPkgs = 0;
int totalResources = 0;
long totalBytes = 0;
String resourceName;
long endTime;
boolean success = true;
Throwable exception = null;
String title = null;
long startTime = System.currentTimeMillis();
try {
//Notify begin
if (level == 0)
notifyProgressBegin(progress, startTime);
//Load references
if (refs != null && refs.length > 0) {
for(String ref : refs) {
if (ref.equalsIgnoreCase(name))
continue;
if (StringUtil.isNullOrEmpty(ref))
throw new MissingResourceReferenceException("An empty reference name is invalid.");
//Attempt to locate this reference
final Reference reference = Registry.findReference(ref, true);
if (reference == null)
continue;
//Get its associated resource object if it has one
final Resources res = reference.getResources();
if (res == null || res == this || res.isProcessed())
continue;
//Process on this same thread
res.extractResources(level + 1, res.references, res.packages, filter, progress);
}
}
for(IResourcePackage pkg : pkgs) {
if (pkg == null) {
notifyProgressReportPackageCompleted(progress, pkg, totalBytes, totalResources, ++totalPkgs, startTime, "Skipped package");
continue;
}
for(IResourceProcessor p : pkg) {
if (p == null) {
notifyProgressReportResourceCompleted(progress, p, pkg, totalBytes, ++totalResources, totalPkgs, startTime, "Skipped resource");
continue;
}
//Double check that we're allowed to process this resource
resourceName = pkg.resourcePath(p.getName());
if (filter != null && !filter.filter(pkg, p, resourceName)) {
notifyProgressReportResourceCompleted(progress, p, pkg, totalBytes, ++totalResources, totalPkgs, startTime, "Skipped resource");
continue;
}
//Here we go!
//If this was already processed, then skip the processing again
if (p.isProcessed() || p.process(resourceName, pkg, filter, progress)) {
totalBytes += p.getSize();
title = (p instanceof DefaultResourceProcessor ? ((DefaultResourceProcessor)p).getTitle() : p.getName());
if (StringUtil.isNullOrEmpty(title))
title = p.getName();
notifyProgressReportResourceCompleted(progress, p, pkg, totalBytes, ++totalResources, totalPkgs, startTime, title);
}
}
notifyProgressReportPackageCompleted(progress, pkg, totalBytes, totalResources, ++totalPkgs, startTime, "Completed package");
}
success = true;
} catch(Throwable t) {
success = false;
exception = t;
} finally {
endTime = System.currentTimeMillis();
}
if (exception != null)
notifyProgressError(progress, exception, !StringUtil.isNullOrEmpty(exception.getMessage()) ? exception.getMessage() : "Error loading resources");
if (level == 0)
notifyProgressEnd(progress, success, totalBytes, totalResources, totalPkgs, startTime, endTime);
}
//
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy