org.apache.tika.core,\
org.apache.commons.dbcp,\
org.apache.commons.pool,\
- com.google.guava
+ com.google.guava,\
+ org.apache.jackrabbit.jcr2spi,\
+ org.apache.jackrabbit.spi2dav,\
+ org.apache.httpcomponents.httpclient,\
+ org.apache.httpcomponents.httpcore
--- /dev/null
+package org.argeo.jackrabbit.fs;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
+import org.argeo.jcr.ArgeoJcrException;
+import org.argeo.jcr.fs.JcrFileSystem;
+import org.argeo.jcr.fs.JcrFsException;
+
+public class DavexFsProvider extends AbstractJackrabbitFsProvider {
+ final static String JACKRABBIT_REPOSITORY_URI = "org.apache.jackrabbit.repository.uri";
+ final static String JACKRABBIT_REMOTE_DEFAULT_WORKSPACE = "org.apache.jackrabbit.spi2davex.WorkspaceNameDefault";
+
+ private Map<String, JcrFileSystem> fileSystems = new HashMap<>();
+
+ @Override
+ public String getScheme() {
+ return "davex";
+ }
+
+ @Override
+ public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException {
+ if (uri.getHost() == null)
+ throw new ArgeoJcrException("An host should be provided");
+ try {
+ URI repoUri = new URI("http", uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, null);
+ String repoKey = repoUri.toString();
+ if (fileSystems.containsKey(repoKey))
+ throw new FileSystemAlreadyExistsException("CMS file system already exists for " + repoKey);
+ RepositoryFactory repositoryFactory = new Jcr2davRepositoryFactory();
+ return tryGetRepo(repositoryFactory, repoUri, "main");
+ } catch (Exception e) {
+ throw new ArgeoJcrException("Cannot open file system " + uri, e);
+ }
+ }
+
+ private JcrFileSystem tryGetRepo(RepositoryFactory repositoryFactory, URI repoUri, String workspace) {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(JACKRABBIT_REPOSITORY_URI, repoUri.toString());
+ params.put(JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, "main");
+ Repository repository = null;
+ Session session = null;
+ try {
+ repository = repositoryFactory.getRepository(params);
+ if (repository != null)
+ session = repository.login(workspace);
+ } catch (Exception e) {
+ // silent
+ }
+
+ if (session == null) {
+ if (repoUri.getPath() == null || repoUri.getPath().equals("/"))
+ return null;
+ String repoUriStr = repoUri.toString();
+ if (repoUriStr.endsWith("/"))
+ repoUriStr = repoUriStr.substring(0, repoUriStr.length() - 1);
+ String nextRepoUriStr = repoUriStr.substring(0, repoUriStr.lastIndexOf('/'));
+ String nextWorkspace = repoUriStr.substring(repoUriStr.lastIndexOf('/') + 1);
+ URI nextUri;
+ try {
+ nextUri = new URI(nextRepoUriStr);
+ } catch (URISyntaxException e) {
+ throw new ArgeoJcrException("Badly formatted URI", e);
+ }
+ return tryGetRepo(repositoryFactory, nextUri, nextWorkspace);
+ } else {
+ JcrFileSystem fileSystem = new JcrFileSystem(this, session);
+ fileSystems.put(repoUri.toString() + "/" + workspace, fileSystem);
+ return fileSystem;
+ }
+ }
+
+ @Override
+ public FileSystem getFileSystem(URI uri) {
+ return currentUserFileSystem(uri);
+ }
+
+ @Override
+ public Path getPath(URI uri) {
+ JcrFileSystem fileSystem = currentUserFileSystem(uri);
+ if (fileSystem == null)
+ try {
+ fileSystem = (JcrFileSystem) newFileSystem(uri, new HashMap<String, Object>());
+ } catch (IOException e) {
+ throw new JcrFsException("Could not autocreate file system", e);
+ }
+ URI repoUri = null;
+ try {
+ repoUri = new URI("http", uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, null);
+ } catch (URISyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ String uriStr = repoUri.toString();
+ String localPath = null;
+ for (String key : fileSystems.keySet()) {
+ if (uriStr.startsWith(key)) {
+ localPath = uriStr.toString().substring(key.length());
+ }
+ }
+ return fileSystem.getPath(localPath);
+ }
+
+ private JcrFileSystem currentUserFileSystem(URI uri) {
+ for (String key : fileSystems.keySet()) {
+ if (uri.toString().startsWith(key))
+ return fileSystems.get(key);
+ }
+ return null;
+ }
+
+ public static void main(String args[]) {
+ try {
+ DavexFsProvider fsProvider = new DavexFsProvider();
+ Path path = fsProvider.getPath(new URI("davex://root:demo@localhost:7070/jcr/node/main/home/"));
+ System.out.println(path);
+ DirectoryStream<Path> ds = Files.newDirectoryStream(path);
+ for (Path p : ds) {
+ System.out.println("- " + p);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
public class ArgeoJcrException extends RuntimeException {
private static final long serialVersionUID = -1941940005390084331L;
- public ArgeoJcrException(String message, Throwable cause) {
- super(message, cause);
+ public ArgeoJcrException(String message, Throwable e) {
+ super(message, e);
}
public ArgeoJcrException(String message) {
--- /dev/null
+package org.argeo.jcr;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.Binary;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+/**
+ * A {@link Binary} wrapper implementing {@link AutoCloseable} for ease of use
+ * in try/catch blocks.
+ */
+public class Bin implements Binary, AutoCloseable {
+ private final Binary wrappedBinary;
+
+ public Bin(Property property) throws RepositoryException {
+ this(property.getBinary());
+ }
+
+ public Bin(Binary wrappedBinary) {
+ if (wrappedBinary == null)
+ throw new IllegalArgumentException("Wrapped binary cannot be null");
+ this.wrappedBinary = wrappedBinary;
+ }
+
+ // private static Binary getBinary(Property property) throws IOException {
+ // try {
+ // return property.getBinary();
+ // } catch (RepositoryException e) {
+ // throw new IOException("Cannot get binary from property " + property, e);
+ // }
+ // }
+
+ @Override
+ public void close() {
+ dispose();
+ }
+
+ @Override
+ public InputStream getStream() throws RepositoryException {
+ return wrappedBinary.getStream();
+ }
+
+ @Override
+ public int read(byte[] b, long position) throws IOException, RepositoryException {
+ return wrappedBinary.read(b, position);
+ }
+
+ @Override
+ public long getSize() throws RepositoryException {
+ return wrappedBinary.getSize();
+ }
+
+ @Override
+ public void dispose() {
+ wrappedBinary.dispose();
+ }
+
+}
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.security.MessageDigest;
import java.security.Principal;
import java.text.DateFormat;
import java.text.ParseException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.argeo.util.DigestUtils;
/** Utility methods to simplify common JCR operations. */
public class JcrUtils {
public static Node mkdirs(Session session, String path, String type, String intermediaryNodeType,
Boolean versioning) {
try {
- if (path.equals('/'))
+ if (path.equals("/"))
return session.getRootNode();
if (session.itemExists(path)) {
return name;
}
-// /**
-// * Removes forbidden characters from a path, replacing them with '_'
-// *
-// * @deprecated use {@link #replaceInvalidChars(String)} instead
-// */
-// public static String removeForbiddenCharacters(String str) {
-// return str.replace('[', '_').replace(']', '_').replace('/', '_').replace('*', '_');
-//
-// }
+ // /**
+ // * Removes forbidden characters from a path, replacing them with '_'
+ // *
+ // * @deprecated use {@link #replaceInvalidChars(String)} instead
+ // */
+ // public static String removeForbiddenCharacters(String str) {
+ // return str.replace('[', '_').replace(']', '_').replace('/', '_').replace('*',
+ // '_');
+ //
+ // }
/** Cleanly disposes a {@link Binary} even if it is null. */
public static void closeQuietly(Binary binary) {
/** Retrieve a {@link Binary} as a byte array */
public static byte[] getBinaryAsBytes(Property property) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- InputStream in = null;
- Binary binary = null;
- try {
- binary = property.getBinary();
- in = binary.getStream();
+ // ByteArrayOutputStream out = new ByteArrayOutputStream();
+ // InputStream in = null;
+ // Binary binary = null;
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Bin binary = new Bin(property);
+ InputStream in = binary.getStream()) {
+ // binary = property.getBinary();
+ // in = binary.getStream();
IOUtils.copy(in, out);
return out.toByteArray();
} catch (Exception e) {
throw new ArgeoJcrException("Cannot read binary " + property + " as bytes", e);
} finally {
- IOUtils.closeQuietly(out);
- IOUtils.closeQuietly(in);
- closeQuietly(binary);
+ // IOUtils.closeQuietly(out);
+ // IOUtils.closeQuietly(in);
+ // closeQuietly(binary);
}
}
/** Writes a {@link Binary} from a byte array */
public static void setBinaryAsBytes(Node node, String property, byte[] bytes) {
- InputStream in = null;
+ // InputStream in = null;
Binary binary = null;
- try {
- in = new ByteArrayInputStream(bytes);
+ try (InputStream in = new ByteArrayInputStream(bytes)) {
+ // in = new ByteArrayInputStream(bytes);
binary = node.getSession().getValueFactory().createBinary(in);
node.setProperty(property, binary);
} catch (Exception e) {
throw new ArgeoJcrException("Cannot read binary " + property + " as bytes", e);
} finally {
- IOUtils.closeQuietly(in);
+ // IOUtils.closeQuietly(in);
closeQuietly(binary);
}
}
public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive, JcrMonitor monitor, boolean onlyAdd) {
long count = 0l;
- Binary binary = null;
- InputStream in = null;
+ // Binary binary = null;
+ // InputStream in = null;
try {
NodeIterator fromChildren = fromNode.getNodes();
children: while (fromChildren.hasNext()) {
if (monitor != null)
monitor.subTask("Copy " + fileName);
- binary = fromChild.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary();
- in = binary.getStream();
- copyStreamAsFile(toNode, fileName, in);
- IOUtils.closeQuietly(in);
- closeQuietly(binary);
+ try (Bin binary = new Bin(fromChild.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA));
+ InputStream in = binary.getStream();) {
+ copyStreamAsFile(toNode, fileName, in);
+ }
+ // IOUtils.closeQuietly(in);
+ // closeQuietly(binary);
// save session
toNode.getSession().save();
}
}
return count;
- } catch (RepositoryException e) {
+ } catch (RepositoryException | IOException e) {
throw new ArgeoJcrException("Cannot copy files between " + fromNode + " and " + toNode);
} finally {
// in case there was an exception
- IOUtils.closeQuietly(in);
- closeQuietly(binary);
+ // IOUtils.closeQuietly(in);
+ // closeQuietly(binary);
}
}
* @return the created file node
*/
public static Node copyFile(Node folderNode, File file) {
- InputStream in = null;
- try {
- in = new FileInputStream(file);
+ // InputStream in = null;
+ try (InputStream in = new FileInputStream(file)) {
+ // in = new FileInputStream(file);
return copyStreamAsFile(folderNode, file.getName(), in);
} catch (IOException e) {
throw new ArgeoJcrException("Cannot copy file " + file + " under " + folderNode, e);
- } finally {
- IOUtils.closeQuietly(in);
+ // } finally {
+ // IOUtils.closeQuietly(in);
}
}
/** Copy bytes as an nt:file */
public static Node copyBytesAsFile(Node folderNode, String fileName, byte[] bytes) {
- InputStream in = null;
- try {
- in = new ByteArrayInputStream(bytes);
+ // InputStream in = null;
+ try (InputStream in = new ByteArrayInputStream(bytes)) {
+ // in = new ByteArrayInputStream(bytes);
return copyStreamAsFile(folderNode, fileName, in);
} catch (Exception e) {
throw new ArgeoJcrException("Cannot copy file " + fileName + " under " + folderNode, e);
- } finally {
- IOUtils.closeQuietly(in);
+ // } finally {
+ // IOUtils.closeQuietly(in);
}
}
}
}
- /** Computes the checksum of an nt:file */
+ /**
+ * Computes the checksum of an nt:file.
+ *
+ * @deprecated use separate digest utilities
+ */
+ @Deprecated
public static String checksumFile(Node fileNode, String algorithm) {
Binary data = null;
- InputStream in = null;
- try {
- data = fileNode.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary();
- in = data.getStream();
- return DigestUtils.digest(algorithm, in);
- } catch (RepositoryException e) {
+ try (InputStream in = fileNode.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary()
+ .getStream()) {
+ return digest(algorithm, in);
+ } catch (RepositoryException | IOException e) {
throw new ArgeoJcrException("Cannot checksum file " + fileNode, e);
} finally {
- IOUtils.closeQuietly(in);
closeQuietly(data);
}
}
+ @Deprecated
+ private static String digest(String algorithm, InputStream in) {
+ final Integer byteBufferCapacity = 100 * 1024;// 100 KB
+ try {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ byte[] buffer = new byte[byteBufferCapacity];
+ int read = 0;
+ while ((read = in.read(buffer)) > 0) {
+ digest.update(buffer, 0, read);
+ }
+
+ byte[] checksum = digest.digest();
+ String res = encodeHexString(checksum);
+ return res;
+ } catch (Exception e) {
+ throw new ArgeoJcrException("Cannot digest with algorithm " + algorithm, e);
+ }
+ }
+
+ /**
+ * From
+ * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to
+ * -a-hex-string-in-java
+ */
+ @Deprecated
+ private static String encodeHexString(byte[] bytes) {
+ final char[] hexArray = "0123456789abcdef".toCharArray();
+ char[] hexChars = new char[bytes.length * 2];
+ for (int j = 0; j < bytes.length; j++) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
}
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
-import org.apache.commons.io.IOUtils;
import org.argeo.jcr.JcrUtils;
public class BinaryChannel implements SeekableByteChannel {
throw new JcrFsException("Cannot close " + file, e);
} finally {
JcrUtils.closeQuietly(newBinary);
- IOUtils.closeQuietly(fc);
+ // IOUtils.closeQuietly(fc);
+ if (fc != null) {
+ fc.close();
+ }
}
} else {
clearReadState();
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.jcr.ArgeoJcrException;
void init() {
try {
- jcrAdminSession = JcrUtils.loginOrCreateWorkspace(jcrRepository,
- proxyWorkspace);
+ jcrAdminSession = JcrUtils.loginOrCreateWorkspace(jcrRepository, proxyWorkspace);
beforeInitSessionSave(jcrAdminSession);
if (jcrAdminSession.hasPendingChanges())
jcrAdminSession.save();
}
/**
- * Called before the (admin) session is saved at the end of the
- * initialization. Does nothing by default, to be overridden.
+ * Called before the (admin) session is saved at the end of the initialization.
+ * Does nothing by default, to be overridden.
*/
- protected void beforeInitSessionSave(Session session)
- throws RepositoryException {
+ protected void beforeInitSessionSave(Session session) throws RepositoryException {
}
void destroy() {
}
/**
- * Called before the (admin) session is logged out when resources are
- * released. Does nothing by default, to be overridden.
+ * Called before the (admin) session is logged out when resources are released.
+ * Does nothing by default, to be overridden.
*/
protected void beforeDestroySessionLogout() throws RepositoryException {
}
Session clientSession = null;
try {
clientSession = jcrRepository.login(proxyWorkspace);
- if (!clientSession.itemExists(path)
- || shouldUpdate(clientSession, path)) {
+ if (!clientSession.itemExists(path) || shouldUpdate(clientSession, path)) {
nodeAdmin = retrieveAndSave(path);
if (nodeAdmin != null)
nodeClient = clientSession.getNode(path);
}
/** Session is not saved */
- protected synchronized Node proxyUrl(Session session, String remoteUrl,
- String path) throws RepositoryException {
+ protected synchronized Node proxyUrl(Session session, String remoteUrl, String path) throws RepositoryException {
Node node = null;
if (session.itemExists(path)) {
// throw new ArgeoJcrException("Node " + path + " already exists");
}
- InputStream in = null;
- try {
- URL u = new URL(remoteUrl);
- in = u.openStream();
+ try (InputStream in = new URL(remoteUrl).openStream()) {
+ // URL u = new URL(remoteUrl);
+ // in = u.openStream();
node = importFile(session, path, in);
} catch (IOException e) {
if (log.isDebugEnabled()) {
- log.debug("Cannot read " + remoteUrl + ", skipping... "
- + e.getMessage());
+ log.debug("Cannot read " + remoteUrl + ", skipping... " + e.getMessage());
// log.trace("Cannot read because of ", e);
}
JcrUtils.discardQuietly(session);
- } finally {
- IOUtils.closeQuietly(in);
+ // } finally {
+ // IOUtils.closeQuietly(in);
}
return node;
}
- protected synchronized Node importFile(Session session, String path,
- InputStream in) throws RepositoryException {
+ protected synchronized Node importFile(Session session, String path, InputStream in) throws RepositoryException {
Binary binary = null;
try {
Node content = null;
Node node = null;
if (!session.itemExists(path)) {
- node = JcrUtils.mkdirs(session, path, NodeType.NT_FILE,
- NodeType.NT_FOLDER, false);
+ node = JcrUtils.mkdirs(session, path, NodeType.NT_FILE, NodeType.NT_FOLDER, false);
content = node.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
} else {
node = session.getNode(path);
import java.io.IOException;
import java.io.InputStream;
-import javax.jcr.Binary;
import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.servlet.ServletException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.jcr.ArgeoJcrException;
+import org.argeo.jcr.Bin;
import org.argeo.jcr.JcrUtils;
/** Wraps a proxy via HTTP */
/** Retrieve the content of the node. */
protected void processResponse(Node node, HttpServletResponse response) {
- Binary binary = null;
- InputStream in = null;
- try {
+// Binary binary = null;
+// InputStream in = null;
+ try(Bin binary = new Bin( node.getNode(Property.JCR_CONTENT)
+ .getProperty(Property.JCR_DATA));InputStream in = binary.getStream()) {
String fileName = node.getName();
String ext = FilenameUtils.getExtension(fileName);
response.setContentType(contentType);
- try {
- binary = node.getNode(Property.JCR_CONTENT)
- .getProperty(Property.JCR_DATA).getBinary();
- } catch (PathNotFoundException e) {
- log.error("Node " + node + " as no data under content");
- throw e;
- }
- in = binary.getStream();
+// try {
+// binary = node.getNode(Property.JCR_CONTENT)
+// .getProperty(Property.JCR_DATA).getBinary();
+// } catch (PathNotFoundException e) {
+// log.error("Node " + node + " as no data under content");
+// throw e;
+// }
+// in = binary.getStream();
IOUtils.copy(in, response.getOutputStream());
} catch (Exception e) {
throw new ArgeoJcrException("Cannot download " + node, e);
- } finally {
- IOUtils.closeQuietly(in);
- JcrUtils.closeQuietly(binary);
+// } finally {
+// IOUtils.closeQuietly(in);
+// JcrUtils.closeQuietly(binary);
}
}