Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for resources in repo.xml (replaces PR #727) #836

Merged
merged 3 commits into from
Nov 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 83 additions & 15 deletions src/org/exist/repo/Deployment.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.exist.SystemProperties;
import org.exist.collections.triggers.TriggerException;
import org.exist.dom.memtree.DocumentBuilderReceiver;
import org.exist.dom.memtree.InMemoryNodeSet;
import org.exist.dom.memtree.DocumentImpl;
Expand All @@ -54,10 +54,7 @@
import org.exist.storage.DBBroker;
import org.exist.storage.txn.TransactionManager;
import org.exist.storage.txn.Txn;
import org.exist.util.FileUtils;
import org.exist.util.MimeTable;
import org.exist.util.MimeType;
import org.exist.util.SyntaxException;
import org.exist.util.*;
import org.exist.util.serializer.AttrList;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.*;
Expand Down Expand Up @@ -98,6 +95,8 @@ public class Deployment {
private static final QName CLEANUP_ELEMENT = new QName("cleanup", REPO_NAMESPACE);
private static final QName DEPLOYED_ELEMENT = new QName("deployed", REPO_NAMESPACE);
private static final QName DEPENDENCY_ELEMENT = new QName("dependency", PKG_NAMESPACE);
private static final QName RESOURCES_ELEMENT = new QName("resources", REPO_NAMESPACE);
private static final String RESOURCES_PATH_ATTRIBUTE = "path";

private final DBBroker broker;

Expand Down Expand Up @@ -405,8 +404,10 @@ public Optional<String> deploy(final String pkgName, final Optional<ExistReposit
// check for invalid users now.
checkUserSettings();

final InMemoryNodeSet resources = findElements(repoXML,RESOURCES_ELEMENT);

// install
scanDirectory(packageDir, targetCollection, true);
scanDirectory(packageDir, targetCollection, resources, true, false);

// run the post-setup query if present
final ElementImpl postSetup = findElement(repoXML, POST_SETUP_ELEMENT);
Expand Down Expand Up @@ -635,7 +636,8 @@ private Sequence runQuery(final XmldbURI targetCollection, final Path tempDir, f
* @param directory
* @param target
*/
private void scanDirectory(final Path directory, final XmldbURI target, final boolean inRootDir) {
private void scanDirectory(final Path directory, final XmldbURI target, final InMemoryNodeSet resources,
final boolean inRootDir, final boolean isResourcesDir) {
final TransactionManager mgr = broker.getBrokerPool().getTransactionManager();
Collection collection = null;
try(final Txn txn = mgr.beginTransaction()) {
Expand All @@ -647,16 +649,44 @@ private void scanDirectory(final Path directory, final XmldbURI target, final bo
LOG.warn(e);
}

storeFiles(directory, collection, inRootDir);
final boolean isResources = isResourcesDir || isResourceDir(target, resources);

// the root dir is not allowed to be a resources directory
if (!inRootDir && isResourcesDir) {
try {
storeBinaryResources(directory, collection);
} catch (Exception e) {
e.printStackTrace();
}
} else {
storeFiles(directory, collection, inRootDir);
}

// scan sub directories
try(final Stream<Path> subDirs = Files.find(directory, 1, (path, attrs) -> (!path.equals(directory)) && attrs.isDirectory())) {
subDirs.forEach(path -> scanDirectory(path, target.append(FileUtils.fileName(path)), false));
subDirs.forEach(path -> scanDirectory(path, target.append(FileUtils.fileName(path)), resources, false,
isResources));
} catch(final IOException ioe) {
LOG.warn("Unable to scan sub-directories", ioe);
}
}

private boolean isResourceDir(XmldbURI target, InMemoryNodeSet resources) {
// iterate here or pass into scandirectory directly or even save as class property???
try {
for (final SequenceIterator i = resources.iterate(); i.hasNext(); ) {
final ElementImpl child = (ElementImpl) i.nextItem();
final String resourcePath = child.getAttribute(RESOURCES_PATH_ATTRIBUTE);
if (target.toString().endsWith(resourcePath)) {
return true;
}
}
} catch (XPathException e) {
LOG.warn("Caught exception while reading resource list in repo.xml: " + e.getMessage(), e);
}
return false;
}

/**
* Import all files in the given directory into the target collection
*
Expand Down Expand Up @@ -688,13 +718,21 @@ private void storeFiles(final Path directory, final Collection targetCollection,

try(final Txn txn = mgr.beginTransaction()) {
if (mime.isXMLType()) {
final InputSource is = new InputSource(file.toUri().toASCIIString());
final IndexInfo info = targetCollection.validateXMLResource(txn, broker, name, is);
info.getDocument().getMetadata().setMimeType(mime.getName());
final Permission permission = info.getDocument().getPermissions();
setPermissions(false, mime, permission);
try {
final InputSource is = new InputSource(file.toUri().toASCIIString());
final IndexInfo info = targetCollection.validateXMLResource(txn, broker, name, is);
info.getDocument().getMetadata().setMimeType(mime.getName());
final Permission permission = info.getDocument().getPermissions();
setPermissions(false, mime, permission);

targetCollection.store(txn, broker, info, is, false);
targetCollection.store(txn, broker, info, is, false);
} catch (Exception e) {
//check for .html ending
if(mime.getName().equals(MimeType.HTML_TYPE.getName())){
//store it
storeBinary(targetCollection, file, mime, name, txn);
}
}
} else {
final long size = Files.size(file);
try(final InputStream is = Files.newInputStream(file)) {
Expand All @@ -715,6 +753,36 @@ private void storeFiles(final Path directory, final Collection targetCollection,
}
}

private void storeBinary(Collection targetCollection, Path file, MimeType mime, XmldbURI name, Txn txn) throws
IOException, EXistException, PermissionDeniedException, LockException, TriggerException {
final long size = Files.size(file);
try (final InputStream is = Files.newInputStream(file)) {
final BinaryDocument doc =
targetCollection.addBinaryResource(txn, broker, name, is, mime.getName(), size);

final Permission permission = doc.getPermissions();
setPermissions(false, mime, permission);
doc.getMetadata().setMimeType(mime.getName());
broker.storeXMLResource(txn, doc);
}
}

private void storeBinaryResources(Path directory, Collection targetCollection) throws IOException, EXistException,
PermissionDeniedException, LockException, TriggerException {
final TransactionManager mgr = broker.getBrokerPool().getTransactionManager();
Files.newDirectoryStream(directory).forEach(file -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will leak file handles as you have not closed the stream!

if (!Files.isDirectory(file)) {
final XmldbURI name = XmldbURI.create(FileUtils.fileName(file));
try(final Txn txn = mgr.beginTransaction()) {
storeBinary(targetCollection, file, MimeType.BINARY_TYPE, name, txn);
mgr.commit(txn);
} catch (final Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Set owner, group and permissions. For XQuery resources, always set the executable flag.
* @param mime
Expand Down
Loading