From b3c78b01a72d0ddc6e709e6c14ce6e12c2c89270 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 2 Jun 2013 20:37:32 +0000 Subject: [PATCH] Make proxy more generic 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 --- .../argeo/jcr/mvc/ResourceProxyServlet.java | 38 ++++++---- .../org/argeo/jcr/proxy/AbstractUrlProxy.java | 69 ++++++++++++------- .../org/argeo/jcr/proxy/ResourceProxy.java | 13 ++-- 3 files changed, 72 insertions(+), 48 deletions(-) diff --git a/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java b/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java index 2ad44c71d..c821be054 100644 --- a/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java +++ b/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java @@ -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; } diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java index 7b5188e9e..7692163e3 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java @@ -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; + } + } diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java index 45c7c16a2..b4fb33286 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java @@ -16,19 +16,16 @@ 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, null if - * the resource was not found (e.g. HTPP 404) + * @return the proxied Node, null if the resource was not found + * (e.g. HTTP 404) */ - public Node proxy(Session session,String relativePath); + public Node proxy(String relativePath); } -- 2.30.2