<param name="schema" value="default" />
<param name="schemaObjectPrefix" value="fs_" />
</FileSystem>
+ <DataStore class="org.apache.jackrabbit.core.data.FileDataStore"/>
+ <!--
<DataStore class="org.apache.jackrabbit.core.data.db.DbDataStore">
<param name="dataSourceName" value="dataSource" />
<param name="schemaObjectPrefix" value="ds_" />
</DataStore>
+ -->
<!-- Workspace templates -->
<Workspaces rootPath="${rep.home}/workspaces"
<version>0.3.4-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>com.springsource.org.apache.commons.io</artifactId>
+ </dependency>
+
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
--- /dev/null
+package org.argeo.jcr.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.Session;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.proxy.ResourceProxy;
+
+/** Wraps a proxy via HTTP */
+public class ResourceProxyServlet extends HttpServlet implements ArgeoNames {
+ private static final long serialVersionUID = -8886549549223155801L;
+
+ private final static Log log = LogFactory
+ .getLog(ResourceProxyServlet.class);
+
+ private ResourceProxy proxy;
+
+ private Session jcrSession;
+ private String contentTypeCharset = "UTF-8";
+
+ @Override
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ String path = request.getPathInfo();
+
+ String nodePath = proxy.getNodePath(path);
+ if (log.isTraceEnabled())
+ log.trace("path=" + path + ", nodePath=" + nodePath);
+
+ Node node = proxy.proxy(jcrSession, path);
+ if (node == null)
+ response.sendError(404);
+ else
+ processResponse(nodePath, node, response);
+ }
+
+ /** Retrieve the content of the node. */
+ protected void processResponse(String path, Node node,
+ HttpServletResponse response) {
+ Binary binary = null;
+ InputStream in = null;
+ try {
+ String fileName = node.getName();
+ String ext = FilenameUtils.getExtension(fileName);
+
+ // TODO use a more generic / standard approach
+ // see http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml
+ String contentType;
+ if ("xml".equals(ext))
+ contentType = "text/xml;charset=" + contentTypeCharset;
+ else if ("jar".equals(ext))
+ contentType = "application/java-archive";
+ else if ("zip".equals(ext))
+ contentType = "application/zip";
+ else if ("gz".equals(ext))
+ contentType = "application/x-gzip";
+ else if ("tar".equals(ext))
+ contentType = "application/x-tar";
+ else
+ contentType = "application/octet-stream";
+ contentType = contentType + ";name=\"" + fileName + "\"";
+ response.setHeader("Content-Disposition", "attachment; filename=\""
+ + fileName + "\"");
+ response.setHeader("Expires", "0");
+ response.setHeader("Cache-Control", "no-cache, must-revalidate");
+ response.setHeader("Pragma", "no-cache");
+
+ response.setContentType(contentType);
+
+ binary = node.getNode(Property.JCR_CONTENT)
+ .getProperty(Property.JCR_DATA).getBinary();
+ in = binary.getStream();
+ IOUtils.copy(in, response.getOutputStream());
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot download " + node, e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ JcrUtils.closeQuietly(binary);
+ }
+ }
+
+ public void setJcrSession(Session jcrSession) {
+ this.jcrSession = jcrSession;
+ }
+
+ public void setProxy(ResourceProxy resourceProxy) {
+ this.proxy = resourceProxy;
+ }
+
+}
}
/**
- * @deprecated use {@link #mkdirs(Session, String, String, String, Boolean)}
- * instead.
+ * use {@link #mkdirs(Session, String, String, String, Boolean)} instead.
+ *
+ * @deprecated
*/
@Deprecated
public static Node mkdirs(Session session, String path, String type,
--- /dev/null
+package org.argeo.jcr.proxy;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+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.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+
+/** Base class for URL based proxys. */
+public abstract class AbstractUrlProxy implements ResourceProxy {
+ private final static Log log = LogFactory.getLog(AbstractUrlProxy.class);
+
+ private Repository jcrRepository;
+ private Session jcrAdminSession;
+
+ protected abstract String retrieve(String relativePath);
+
+ void init() {
+ try {
+ jcrAdminSession = jcrRepository.login();
+ beforeInitSessionSave();
+ if (jcrAdminSession.hasPendingChanges())
+ jcrAdminSession.save();
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(jcrAdminSession);
+ throw new ArgeoException("Cannot initialize Maven proxy", e);
+ }
+ }
+
+ /**
+ * Called before the (admin) session is saved at the end of the
+ * initialization. Does nothing by default, to be overridden.
+ */
+ protected void beforeInitSessionSave() throws RepositoryException {
+ }
+
+ void destroy() {
+ JcrUtils.logoutQuietly(jcrAdminSession);
+ }
+
+ /**
+ * Called before the (admin) session is logged out when resources are
+ * released. Does nothing by default, to be overridden.
+ */
+ protected void beforeDestroySessionLogout() throws RepositoryException {
+ }
+
+ public Node proxy(Session jcrSession, String path) {
+ Node node;
+ try {
+ String nodePath = getNodePath(path);
+ if (!jcrSession.itemExists(nodePath)) {
+ String nodeIdentifier = retrieve(path);
+ if (nodeIdentifier == null) {
+ // log.warn("Could not proxy " + path);
+ return null;
+ } else {
+ node = jcrSession.getNodeByIdentifier(nodeIdentifier);
+ }
+ } else {
+ node = jcrSession.getNode(nodePath);
+ }
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot proxy " + path, e);
+ }
+ return node;
+ }
+
+ protected Node proxyUrl(String baseUrl, String path) {
+ Node node = null;
+ String remoteUrl = baseUrl + path;
+ if (log.isTraceEnabled())
+ log.trace("baseUrl=" + remoteUrl);
+ InputStream in = null;
+ try {
+ URL u = new URL(remoteUrl);
+ in = u.openStream();
+ node = importFile(getNodePath(path), in);
+ if (log.isDebugEnabled())
+ log.debug("Imported " + remoteUrl + " to " + node);
+ } catch (Exception e) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot read " + remoteUrl + ", skipping... "
+ + e.getMessage());
+ if (log.isTraceEnabled()) {
+ log.trace("Cannot read because of ", e);
+ }
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+
+ return node;
+ }
+
+ protected synchronized Node importFile(String nodePath, InputStream in) {
+ // FIXME allow parallel proxying
+ Binary binary = null;
+ try {
+ Node node = JcrUtils.mkdirs(jcrAdminSession, nodePath,
+ NodeType.NT_FILE, NodeType.NT_FOLDER, false);
+ Node content = node.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
+ binary = jcrAdminSession.getValueFactory().createBinary(in);
+ content.setProperty(Property.JCR_DATA, binary);
+ jcrAdminSession.save();
+ return node;
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(jcrAdminSession);
+ throw new ArgeoException("Cannot initialize Maven proxy", e);
+ } finally {
+ JcrUtils.closeQuietly(binary);
+ }
+ }
+
+ protected Session getJcrAdminSession() {
+ return jcrAdminSession;
+ }
+
+ public void setJcrRepository(Repository jcrRepository) {
+ this.jcrRepository = jcrRepository;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.proxy;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+/** A proxy which nows how to resolve and synchronize relative URLs */
+public interface ResourceProxy {
+ /** Path to the proxied node (which may not already exist) */
+ public String getNodePath(String relativePath);
+
+ /**
+ * Proxy the file referenced by this relative path in the underlying
+ * repository
+ *
+ * @return the unique identifier of the proxied Node, <code>null</code> if
+ * the resource was not found (e.g. HTPP 404)
+ */
+ public Node proxy(Session session,String relativePath);
+}