Make proxy more generic
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 2 Jun 2013 20:37:32 +0000 (20:37 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 2 Jun 2013 20:37:32 +0000 (20:37 +0000)
https://www.argeo.org/bugzilla/show_bug.cgi?id=162

git-svn-id: https://svn.argeo.org/commons/branches/1.x@6321 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java

index 2ad44c71d28213d5360385c724d900f3f32fbbfa..c821be05418f229f31cb6708f94be3ce8dd34daa 100644 (file)
@@ -22,7 +22,7 @@ import javax.jcr.Binary;
 import javax.jcr.Node;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.Property;
-import javax.jcr.Session;
+import javax.jcr.RepositoryException;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -45,7 +45,6 @@ public class ResourceProxyServlet extends HttpServlet {
 
        private ResourceProxy proxy;
 
-       private Session jcrSession;
        private String contentTypeCharset = "UTF-8";
 
        @Override
@@ -53,9 +52,8 @@ public class ResourceProxyServlet extends HttpServlet {
                        HttpServletResponse response) throws ServletException, IOException {
                String path = request.getPathInfo();
 
-               String nodePath = proxy.getNodePath(path);
                if (log.isTraceEnabled()) {
-                       log.trace("path=" + path + ", nodePath=" + nodePath);
+                       log.trace("path=" + path);
                        log.trace("UserPrincipal = " + request.getUserPrincipal().getName());
                        log.trace("SessionID = " + request.getSession().getId());
                        log.trace("ContextPath = " + request.getContextPath());
@@ -65,16 +63,26 @@ public class ResourceProxyServlet extends HttpServlet {
                        log.trace("User-Agent = " + request.getHeader("User-Agent"));
                }
 
-               Node node = proxy.proxy(jcrSession, path);
-               if (node == null)
-                       response.sendError(404);
-               else
-                       processResponse(nodePath, node, response);
+               Node node = null;
+               try {
+                       node = proxy.proxy(path);
+                       if (node == null)
+                               response.sendError(404);
+                       else
+                               processResponse(node, response);
+               } finally {
+                       if (node != null)
+                               try {
+                                       JcrUtils.logoutQuietly(node.getSession());
+                               } catch (RepositoryException e) {
+                                       // silent
+                               }
+               }
+
        }
 
        /** Retrieve the content of the node. */
-       protected void processResponse(String path, Node node,
-                       HttpServletResponse response) {
+       protected void processResponse(Node node, HttpServletResponse response) {
                Binary binary = null;
                InputStream in = null;
                try {
@@ -92,8 +100,12 @@ public class ResourceProxyServlet extends HttpServlet {
                                contentType = "application/zip";
                        else if ("gz".equals(ext))
                                contentType = "application/x-gzip";
+                       else if ("bz2".equals(ext))
+                               contentType = "application/x-bzip2";
                        else if ("tar".equals(ext))
                                contentType = "application/x-tar";
+                       else if ("rpm".equals(ext))
+                               contentType = "application/x-redhat-package-manager";
                        else
                                contentType = "application/octet-stream";
                        contentType = contentType + ";name=\"" + fileName + "\"";
@@ -122,10 +134,6 @@ public class ResourceProxyServlet extends HttpServlet {
                }
        }
 
-       public void setJcrSession(Session jcrSession) {
-               this.jcrSession = jcrSession;
-       }
-
        public void setProxy(ResourceProxy resourceProxy) {
                this.proxy = resourceProxy;
        }
index 7b5188e9eeb1abe5c02fea64e41375975ea1008e..7692163e3a008a5ea4b70f71fc34e9933c68c93f 100644 (file)
@@ -39,12 +39,14 @@ public abstract class AbstractUrlProxy implements ResourceProxy {
 
        private Repository jcrRepository;
        private Session jcrAdminSession;
+       private String proxyWorkspace = "proxy";
 
-       protected abstract Node retrieve(Session session, String relativePath);
+       protected abstract Node retrieve(Session session, String path);
 
        void init() {
                try {
-                       jcrAdminSession = jcrRepository.login();
+                       jcrAdminSession = JcrUtils.loginOrCreateWorkspace(jcrRepository,
+                                       proxyWorkspace);
                        beforeInitSessionSave(jcrAdminSession);
                        if (jcrAdminSession.hasPendingChanges())
                                jcrAdminSession.save();
@@ -73,20 +75,20 @@ public abstract class AbstractUrlProxy implements ResourceProxy {
        protected void beforeDestroySessionLogout() throws RepositoryException {
        }
 
-       public Node proxy(Session session, String path) {
+       public Node proxy(String path) {
+               // we open a JCR session with client credentials in order not to use the
+               // admin session in multiple thread or make it a bottleneck.
+               Session clientSession = null;
                try {
-                       if (session.hasPendingChanges())
-                               throw new ArgeoException(
-                                               "Cannot proxy based on a session with pending changes");
-                       String nodePath = getNodePath(path);
-                       if (!session.itemExists(nodePath)) {
+                       clientSession = jcrRepository.login(proxyWorkspace);
+                       if (!clientSession.itemExists(path)
+                                       || shouldUpdate(clientSession, path)) {
                                Node nodeT = retrieveAndSave(path);
                                if (nodeT == null)
                                        return null;
                        }
-                       return session.getNode(nodePath);
+                       return clientSession.getNode(path);
                } catch (RepositoryException e) {
-                       JcrUtils.discardQuietly(jcrAdminSession);
                        throw new ArgeoException("Cannot proxy " + path, e);
                }
        }
@@ -101,25 +103,26 @@ public abstract class AbstractUrlProxy implements ResourceProxy {
                } catch (RepositoryException e) {
                        JcrUtils.discardQuietly(jcrAdminSession);
                        throw new ArgeoException("Cannot retrieve and save " + path, e);
+               } finally {
+                       notifyAll();
                }
        }
 
        /** Session is not saved */
-       protected Node proxyUrl(Session session, String baseUrl, String path)
-                       throws RepositoryException {
-               String nodePath = getNodePath(path);
-               if (jcrAdminSession.itemExists(nodePath))
-                       throw new ArgeoException("Node " + nodePath + " already exists");
+       protected synchronized Node proxyUrl(Session session, String remoteUrl,
+                       String path) throws RepositoryException {
                Node node = null;
-               String remoteUrl = baseUrl + path;
+               if (session.itemExists(path)) {
+                       // throw new ArgeoException("Node " + path + " already exists");
+               }
                InputStream in = null;
                try {
                        URL u = new URL(remoteUrl);
                        in = u.openStream();
-                       node = importFile(session, nodePath, in);
+                       node = importFile(session, path, in);
                } catch (IOException e) {
-                       if (log.isTraceEnabled()) {
-                               log.trace("Cannot read " + remoteUrl + ", skipping... "
+                       if (log.isDebugEnabled()) {
+                               log.debug("Cannot read " + remoteUrl + ", skipping... "
                                                + e.getMessage());
                                // log.trace("Cannot read because of ", e);
                        }
@@ -130,24 +133,40 @@ public abstract class AbstractUrlProxy implements ResourceProxy {
                return node;
        }
 
-       protected Node importFile(Session session, String nodePath, InputStream in)
-                       throws RepositoryException {
-               // FIXME allow parallel proxying
+       protected synchronized Node importFile(Session session, String path,
+                       InputStream in) throws RepositoryException {
                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);
+                       Node content = null;
+                       Node node = null;
+                       if (!session.itemExists(path)) {
+                               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);
+                               content = node.getNode(Node.JCR_CONTENT);
+                       }
                        binary = session.getValueFactory().createBinary(in);
                        content.setProperty(Property.JCR_DATA, binary);
+                       JcrUtils.updateLastModifiedAndParents(node, null);
                        return node;
                } finally {
                        JcrUtils.closeQuietly(binary);
                }
        }
 
+       /** Whether the file should be updated. */
+       protected Boolean shouldUpdate(Session clientSession, String nodePath) {
+               return false;
+       }
+
        public void setJcrRepository(Repository jcrRepository) {
                this.jcrRepository = jcrRepository;
        }
 
+       public void setProxyWorkspace(String localWorkspace) {
+               this.proxyWorkspace = localWorkspace;
+       }
+
 }
index 45c7c16a2dff71dbd15019d71db7570615312c07..b4fb33286c555514072fec44caa2b57df0c05189 100644 (file)
 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
+        * repository. A new session is created by each call, so the underlying
+        * session of the returned node must be closed by the caller.
         * 
-        * @return the unique identifier of the proxied Node, <code>null</code> if
-        *         the resource was not found (e.g. HTPP 404)
+        * @return the proxied Node, <code>null</code> if the resource was not found
+        *         (e.g. HTTP 404)
         */
-       public Node proxy(Session session,String relativePath);
+       public Node proxy(String relativePath);
 }