Improve JCR remoting and proxying
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 14 Oct 2011 18:18:20 +0000 (18:18 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 14 Oct 2011 18:18:20 +0000 (18:18 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@4841 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

13 files changed:
pom.xml
security/modules/org.argeo.security.dao.ldap/pom.xml
server/modules/org.argeo.node.repo.jackrabbit/noderepo.properties
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java
server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java
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/JcrUtils.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java
server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd

diff --git a/pom.xml b/pom.xml
index c7011d39ecd88b7f46cd77d3d075125d5a8859ae..74f85b05fad3eadb577b06e52488e3e36b3ff269 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -382,12 +382,12 @@ limitations under the License.
                                <repository>
                                        <id>localrepo</id>
                                        <name>Internal Release Repository</name>
-                                       <url>dav:http://localrepo:7070/org.argeo.jcr.webapp/webdav/node/dev/slc/repo/artifacts</url>
+                                       <url>dav:http://localrepo:7070/org.argeo.jcr.webapp/webdav/node/dev/repo</url>
                                </repository>
                                <snapshotRepository>
                                        <id>localrepo.snapshots</id>
                                        <name>Internal Snapshot Repository</name>
-                                       <url>dav:http://localrepo:7070/org.argeo.jcr.webapp/webdav/node/dev/slc/repo/artifacts</url>
+                                       <url>dav:http://localrepo:7070/org.argeo.jcr.webapp/webdav/node/dev/repo</url>
                                </snapshotRepository>
                        </distributionManagement>
                </profile>
index 88358854d82371b72a4c714c974d46fe5b78ffb1..91058b37faa4cea2c27a0b372b06a4bb2d5b4b1e 100644 (file)
@@ -20,7 +20,8 @@
                                                        *,
                                                        org.argeo.jcr,
                                                        com.sun.jndi.ldap;resolution:=optional,
-                                                       org.springframework.ldap.core.support
+                                                       org.springframework.ldap.core.support,
+                                                       org.springframework.security
                                                </Import-Package>
                                        </instructions>
                                </configuration>
index a6c5b4bdc917bb8df0bbf8a7bfc97dfc33c1c721..046e1790a154a999d2cc0455859da86cba54ccd8 100644 (file)
@@ -2,11 +2,11 @@
 argeo.node.repo.workspace=dev
 
 # Repository base directory
-argeo.node.repo.home=${osgi.instance.area}/node/repo
+argeo.node.repo.home=${osgi.instance.area}/node
 
 ## H2 Embedded (DEFAULT)
 argeo.node.repo.configuration=osgibundle:repository-h2.xml
-argeo.node.repo.dburl=jdbc:h2:${osgi.instance.area}/node/h2/repo
+argeo.node.repo.dburl=jdbc:h2:${osgi.instance.area}/node/h2/repository
 argeo.node.repo.dbuser=sa
 argeo.node.repo.dbpassword=
 
index 5c0ef83135f88e4c452836669ba72bc83e86d7bc..ae00086818c654e79ba2a37cde7dc79c7ea0995c 100644 (file)
@@ -3,6 +3,7 @@ package org.argeo.jackrabbit.remote;
 import org.apache.jackrabbit.server.SessionProvider;
 import org.argeo.jcr.mvc.MultipleRepositoryHandlerMapping;
 
+/** Base class for Jackrabbit ahndler mappings. */
 public abstract class AbstractJackrabbitHandlerMapping extends
                MultipleRepositoryHandlerMapping {
        private SessionProvider sessionProvider;
index cff2c3b01053fac19d6333cbda0e0bce38981e96..e11087794ff5a933b538017e2393838017ceec2d 100644 (file)
@@ -37,16 +37,20 @@ public class ExtendedDispatcherServlet extends DispatcherServlet {
 
                // see http://forum.springsource.org/showthread.php?t=53472
                try {
-                       if (log.isTraceEnabled())
-                               log.trace("Received request " + request);
-//                     log.debug("PathTranslated="+request.getPathTranslated());
-                       log.debug("PathInfo="+request.getPathInfo());
-//                     log.debug("ServletPath="+request.getServletPath());
-//                     log.debug("ContextPath="+request.getContextPath());
+                       if (log.isTraceEnabled()) {
+                               log.trace("UserPrincipal = "
+                                               + request.getUserPrincipal().getName());
+                               log.trace("SessionID = " + request.getSession().getId());
+                               log.trace("ContextPath = " + request.getContextPath());
+                               log.trace("ServletPath = " + request.getServletPath());
+                               log.trace("PathInfo = " + request.getPathInfo());
+                               log.trace("Method = " + request.getMethod());
+                               log.trace("User-Agent = " + request.getHeader("User-Agent"));
+                       }
                        doService(request, response);
                } catch (Exception e) {
-//                     e.printStackTrace();
-//                     log.debug(request.getMethod());
+                       // e.printStackTrace();
+                       // log.debug(request.getMethod());
                        throw new ArgeoException("Cannot process request", e);
                }
        }
index aa9bfa5d6f16fd7e492bf9014d5301dcba426935..6647eb94bf77f958a9f5aa27884976aada8afd93 100644 (file)
@@ -16,6 +16,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.jackrabbit.server.SessionProvider;
 import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
 
 /** To be injected, typically of scope="session" */
 public class SimpleSessionProvider implements SessionProvider, Serializable {
@@ -26,39 +27,48 @@ public class SimpleSessionProvider implements SessionProvider, Serializable {
 
        private transient Map<String, Session> sessions;
 
+       private Boolean openSessionInView = true;
+
        public Session getSession(HttpServletRequest request, Repository rep,
                        String workspace) throws LoginException, ServletException,
                        RepositoryException {
-               // since sessions is transient it can't be restored from the session
-               if (sessions == null)
-                       sessions = Collections
-                                       .synchronizedMap(new HashMap<String, Session>());
 
-               if (!sessions.containsKey(workspace)) {
-                       try {
-                               Session session = rep.login(null, workspace);
-                               if (log.isTraceEnabled())
-                                       log.trace("User " + session.getUserID() + " logged into "
-                                                       + request.getServletPath());
-                               sessions.put(workspace, session);
-                               return session;
-                       } catch (Exception e) {
-                               throw new ArgeoException("Cannot open session", e);
-                       }
+               if (openSessionInView) {
+                       return rep.login(workspace);
                } else {
-                       Session session = sessions.get(workspace);
-                       if (!session.isLive()) {
-                               sessions.remove(workspace);
-                               session = rep.login(null, workspace);
-                               sessions.put(workspace, session);
+                       // since sessions is transient it can't be restored from the session
+                       if (sessions == null)
+                               sessions = Collections
+                                               .synchronizedMap(new HashMap<String, Session>());
+
+                       if (!sessions.containsKey(workspace)) {
+                               try {
+                                       Session session = rep.login(null, workspace);
+                                       if (log.isTraceEnabled())
+                                               log.trace("User " + session.getUserID()
+                                                               + " logged into " + request.getServletPath());
+                                       sessions.put(workspace, session);
+                                       return session;
+                               } catch (Exception e) {
+                                       throw new ArgeoException("Cannot open session", e);
+                               }
+                       } else {
+                               Session session = sessions.get(workspace);
+                               if (!session.isLive()) {
+                                       sessions.remove(workspace);
+                                       session = rep.login(null, workspace);
+                                       sessions.put(workspace, session);
+                               }
+                               return session;
                        }
-                       return session;
                }
        }
 
        public void releaseSession(Session session) {
                if (log.isTraceEnabled())
                        log.trace("Releasing JCR session " + session);
+               if (openSessionInView)
+                       JcrUtils.logoutQuietly(session);
        }
 
        public void init() {
index 6bc48fa07e8e4547d495fb5e99ede4701f943e9c..02f1fd371327c66cfeacaebcb4c36382681621fe 100644 (file)
@@ -20,7 +20,7 @@ import javax.jcr.Repository;
 
 import org.apache.jackrabbit.server.SessionProvider;
 
-/** WebDav servlet whoe repository is injected */
+/** WebDav servlet whose repository is injected */
 public class SimpleWebdavServlet extends
                org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet {
        private static final long serialVersionUID = -369787931175177080L;
index bc333ba4400d15d87e951c85ca8aa6400d295bb7..bd5b3700572094c3b248dfba15a27e7a6ce14d08 100644 (file)
@@ -1,6 +1,5 @@
 package org.argeo.jcr.mvc;
 
-import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Properties;
@@ -15,6 +14,7 @@ import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
 import org.argeo.jcr.RepositoryRegister;
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
@@ -51,26 +51,7 @@ public abstract class MultipleRepositoryHandlerMapping implements
                String pathInfo = request.getPathInfo();
 
                // tokenize path
-               // TODO factorize
-               List<String> tokens = new ArrayList<String>();
-               StringBuffer curr = new StringBuffer();
-               char[] arr = pathInfo.toCharArray();
-               chars: for (int i = 0; i < arr.length; i++) {
-                       char c = arr[i];
-                       if (c == '/') {
-                               if (i == 0 || (i == arr.length - 1))
-                                       continue chars;
-                               if (curr.length() > 0) {
-                                       tokens.add(curr.toString());
-                                       curr = new StringBuffer();
-                               }
-                       } else
-                               curr.append(c);
-               }
-               if (curr.length() > 0) {
-                       tokens.add(curr.toString());
-                       curr = new StringBuffer();
-               }
+               List<String> tokens = JcrUtils.tokenize(pathInfo);
 
                // check if repository can be found
                if (tokens.size() == 0
index 20306609f86cfa8306ce5bee5cb056d8fc9b0c2d..b92f776cd23bd2a83645281614ac1ac00d04d1dd 100644 (file)
@@ -40,8 +40,16 @@ public class ResourceProxyServlet extends HttpServlet implements ArgeoNames {
                String path = request.getPathInfo();
 
                String nodePath = proxy.getNodePath(path);
-               if (log.isTraceEnabled())
+               if (log.isTraceEnabled()) {
                        log.trace("path=" + path + ", nodePath=" + nodePath);
+                       log.trace("UserPrincipal = " + request.getUserPrincipal().getName());
+                       log.trace("SessionID = " + request.getSession().getId());
+                       log.trace("ContextPath = " + request.getContextPath());
+                       log.trace("ServletPath = " + request.getServletPath());
+                       log.trace("PathInfo = " + request.getPathInfo());
+                       log.trace("Method = " + request.getMethod());
+                       log.trace("User-Agent = " + request.getHeader("User-Agent"));
+               }
 
                Node node = proxy.proxy(jcrSession, path);
                if (node == null)
@@ -87,7 +95,7 @@ public class ResourceProxyServlet extends HttpServlet implements ArgeoNames {
                                binary = node.getNode(Property.JCR_CONTENT)
                                                .getProperty(Property.JCR_DATA).getBinary();
                        } catch (PathNotFoundException e) {
-                               log.error("Node "+node+" as no data under content");
+                               log.error("Node " + node + " as no data under content");
                                throw e;
                        }
                        in = binary.getStream();
index eeaff3a924f505cee38124e3ac85a090dbc5295e..5efc240498f198283b03848934a26adfd297f27b 100644 (file)
@@ -23,14 +23,15 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.text.DateFormat;
 import java.text.ParseException;
+import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.StringTokenizer;
 import java.util.TreeMap;
 
 import javax.jcr.Binary;
@@ -144,6 +145,46 @@ public class JcrUtils implements ArgeoJcrConstants {
                }
        }
 
+       /** Set the {@link NodeType#NT_ADDRESS} properties based on this URL. */
+       public static void urlToAddressProperties(Node node, String url) {
+               try {
+                       URL u = new URL(url);
+                       node.setProperty(Property.JCR_PROTOCOL, u.getProtocol());
+                       node.setProperty(Property.JCR_HOST, u.getHost());
+                       node.setProperty(Property.JCR_PORT, Integer.toString(u.getPort()));
+                       node.setProperty(Property.JCR_PATH, normalizePath(u.getPath()));
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot set URL " + url
+                                       + " as nt:address properties", e);
+               }
+       }
+
+       /** Build URL based on the {@link NodeType#NT_ADDRESS} properties. */
+       public static String urlFromAddressProperties(Node node) {
+               try {
+                       URL u = new URL(
+                                       node.getProperty(Property.JCR_PROTOCOL).getString(), node
+                                                       .getProperty(Property.JCR_HOST).getString(),
+                                       (int) node.getProperty(Property.JCR_PORT).getLong(), node
+                                                       .getProperty(Property.JCR_PATH).getString());
+                       return u.toString();
+               } catch (Exception e) {
+                       throw new ArgeoException(
+                                       "Cannot get URL from nt:address properties of " + node, e);
+               }
+       }
+
+       /** Make sure that: starts with '/', do not end with '/', do not have '//' */
+       public static String normalizePath(String path) {
+               List<String> tokens = tokenize(path);
+               StringBuffer buf = new StringBuffer(path.length());
+               for (String token : tokens) {
+                       buf.append('/');
+                       buf.append(token);
+               }
+               return buf.toString();
+       }
+
        /**
         * Creates a path from a FQDN, inverting the order of the component:
         * www.argeo.org => org.argeo.www
@@ -268,9 +309,33 @@ public class JcrUtils implements ArgeoJcrConstants {
                return mkdirs(session, path, type, null, false);
        }
 
+       /**
+        * Synchronized and save is performed, to avoid race conditions in
+        * initializers leading to duplicate nodes.
+        */
+       public synchronized static Node mkdirsSafe(Session session, String path,
+                       String type) {
+               try {
+                       if (session.hasPendingChanges())
+                               throw new ArgeoException(
+                                               "Session has pending changes, save them first.");
+                       Node node = mkdirs(session, path, type);
+                       session.save();
+                       return node;
+               } catch (RepositoryException e) {
+                       discardQuietly(session);
+                       throw new ArgeoException("Cannot safely make directories", e);
+               }
+       }
+
+       public synchronized static Node mkdirsSafe(Session session, String path) {
+               return mkdirsSafe(session, path, null);
+       }
+
        /**
         * Creates the nodes making path, if they don't exist. This is up to the
-        * caller to save the session.
+        * caller to save the session. Use with caution since it can create
+        * duplicate nodes if used concurrently.
         */
        public static Node mkdirs(Session session, String path, String type,
                        String intermediaryNodeType, Boolean versioning) {
@@ -291,16 +356,16 @@ public class JcrUtils implements ArgeoJcrConstants {
                                return node;
                        }
 
-                       StringTokenizer st = new StringTokenizer(path, "/");
                        StringBuffer current = new StringBuffer("/");
                        Node currentNode = session.getRootNode();
-                       while (st.hasMoreTokens()) {
-                               String part = st.nextToken();
+                       Iterator<String> it = tokenize(path).iterator();
+                       while (it.hasNext()) {
+                               String part = it.next();
                                current.append(part).append('/');
                                if (!session.itemExists(current.toString())) {
-                                       if (!st.hasMoreTokens() && type != null)
+                                       if (!it.hasNext() && type != null)
                                                currentNode = currentNode.addNode(part, type);
-                                       else if (st.hasMoreTokens() && intermediaryNodeType != null)
+                                       else if (it.hasNext() && intermediaryNodeType != null)
                                                currentNode = currentNode.addNode(part,
                                                                intermediaryNodeType);
                                        else
@@ -313,13 +378,47 @@ public class JcrUtils implements ArgeoJcrConstants {
                                        currentNode = (Node) session.getItem(current.toString());
                                }
                        }
-                       // session.save();
                        return currentNode;
                } catch (RepositoryException e) {
+                       discardQuietly(session);
                        throw new ArgeoException("Cannot mkdirs " + path, e);
+               } finally {
                }
        }
 
+       /** Convert a path to the list of its tokens */
+       public static List<String> tokenize(String path) {
+               List<String> tokens = new ArrayList<String>();
+               boolean optimized = false;
+               if (!optimized) {
+                       String[] rawTokens = path.split("/");
+                       for (String token : rawTokens) {
+                               if (!token.equals(""))
+                                       tokens.add(token);
+                       }
+               } else {
+                       StringBuffer curr = new StringBuffer();
+                       char[] arr = path.toCharArray();
+                       chars: for (int i = 0; i < arr.length; i++) {
+                               char c = arr[i];
+                               if (c == '/') {
+                                       if (i == 0 || (i == arr.length - 1))
+                                               continue chars;
+                                       if (curr.length() > 0) {
+                                               tokens.add(curr.toString());
+                                               curr = new StringBuffer();
+                                       }
+                               } else
+                                       curr.append(c);
+                       }
+                       if (curr.length() > 0) {
+                               tokens.add(curr.toString());
+                               curr = new StringBuffer();
+                       }
+               }
+               return Collections.unmodifiableList(tokens);
+       }
+
        /**
         * Safe and repository implementation independent registration of a
         * namespace.
@@ -996,14 +1095,29 @@ public class JcrUtils implements ArgeoJcrConstants {
         */
        public static void updateLastModified(Node node) {
                try {
-                       if (node.isNodeType(NodeType.MIX_LAST_MODIFIED)) {
-                               node.setProperty(Property.JCR_LAST_MODIFIED,
-                                               new GregorianCalendar());
-                               node.setProperty(Property.JCR_LAST_MODIFIED_BY, node
-                                               .getSession().getUserID());
-                       }
+                       if (!node.isNodeType(NodeType.MIX_LAST_MODIFIED))
+                               node.addMixin(NodeType.MIX_LAST_MODIFIED);
+                       node.setProperty(Property.JCR_LAST_MODIFIED,
+                                       new GregorianCalendar());
+                       node.setProperty(Property.JCR_LAST_MODIFIED_BY, node.getSession()
+                                       .getUserID());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot update last modified on " + node,
+                                       e);
+               }
+       }
+
+       /** Update lastModified recursively until this parent. */
+       public static void updateLastModifiedAndParents(Node node, String untilPath) {
+               try {
+                       if (!node.getPath().startsWith(untilPath))
+                               throw new ArgeoException(node + " is not under " + untilPath);
+                       updateLastModified(node);
+                       if (!node.getPath().equals(untilPath))
+                               updateLastModifiedAndParents(node.getParent(), untilPath);
                } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot update last modified", e);
+                       throw new ArgeoException("Cannot update lastModified from " + node
+                                       + " until " + untilPath, e);
                }
        }
 
index 8adbae78486d2e158382f21c370c9c7d11c47879..fc9bcaa86356525813fb604eeb65e3e1e561021e 100644 (file)
@@ -140,7 +140,7 @@ public abstract class ThreadBoundJcrSessionFactory {
 
                deactivate();
                for (Session sess : activeSessions.values()) {
-                       sess.logout();
+                       JcrUtils.logoutQuietly(sess);
                }
                activeSessions.clear();
        }
index 7bec5ee7a264c27653cb68c921d3294a3ad328e5..357ec1f37262aa0a847fcdc41309314d43b90453 100644 (file)
@@ -24,15 +24,15 @@ public abstract class AbstractUrlProxy implements ResourceProxy {
        private Repository jcrRepository;
        private Session jcrAdminSession;
 
-       protected abstract String retrieve(String relativePath);
+       protected abstract Node retrieve(Session session, String relativePath);
 
        void init() {
                try {
                        jcrAdminSession = jcrRepository.login();
-                       beforeInitSessionSave();
+                       beforeInitSessionSave(jcrAdminSession);
                        if (jcrAdminSession.hasPendingChanges())
                                jcrAdminSession.save();
-               } catch (RepositoryException e) {
+               } catch (Exception e) {
                        JcrUtils.discardQuietly(jcrAdminSession);
                        throw new ArgeoException("Cannot initialize Maven proxy", e);
                }
@@ -42,7 +42,8 @@ public abstract class AbstractUrlProxy implements ResourceProxy {
         * 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 {
+       protected void beforeInitSessionSave(Session session)
+                       throws RepositoryException {
        }
 
        void destroy() {
@@ -56,76 +57,75 @@ public abstract class AbstractUrlProxy implements ResourceProxy {
        protected void beforeDestroySessionLogout() throws RepositoryException {
        }
 
-       public Node proxy(Session jcrSession, String path) {
-               Node node;
+       public Node proxy(Session session, String path) {
                try {
+                       if (session.hasPendingChanges())
+                               throw new ArgeoException(
+                                               "Cannot proxy based on a session with pending changes");
                        String nodePath = getNodePath(path);
-                       if (!jcrSession.itemExists(nodePath)) {
-                               String nodeIdentifier = retrieve(path);
-                               if (nodeIdentifier == null) {
-                                       // log.warn("Could not proxy " + path);
+                       if (!session.itemExists(nodePath)) {
+                               Node nodeT = retrieveAndSave(path);
+                               if (nodeT == null)
                                        return null;
-                               } else {
-                                       node = jcrSession.getNodeByIdentifier(nodeIdentifier);
-                               }
-                       } else {
-                               node = jcrSession.getNode(nodePath);
                        }
+                       return session.getNode(nodePath);
                } catch (RepositoryException e) {
+                       JcrUtils.discardQuietly(jcrAdminSession);
                        throw new ArgeoException("Cannot proxy " + path, e);
                }
-               return node;
        }
 
-       protected Node proxyUrl(String baseUrl, String path) {
+       protected synchronized Node retrieveAndSave(String path) {
+               try {
+                       Node node = retrieve(jcrAdminSession, path);
+                       if (node == null)
+                               return null;
+                       jcrAdminSession.save();
+                       return node;
+               } catch (RepositoryException e) {
+                       JcrUtils.discardQuietly(jcrAdminSession);
+                       throw new ArgeoException("Cannot retrieve and save " + path, e);
+               }
+       }
+
+       /** Session is not saved */
+       protected Node proxyUrl(Session session, 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);
+                       node = importFile(session, getNodePath(path), in);
                } catch (Exception e) {
-                       if (log.isTraceEnabled())
+                       if (log.isTraceEnabled()) {
                                log.trace("Cannot read " + remoteUrl + ", skipping... "
                                                + e.getMessage());
-                       if (log.isTraceEnabled()) {
-                               log.trace("Cannot read because of ", e);
+                               // log.trace("Cannot read because of ", e);
                        }
+                       JcrUtils.discardQuietly(session);
                } finally {
                        IOUtils.closeQuietly(in);
                }
-
                return node;
        }
 
-       protected synchronized Node importFile(String nodePath, InputStream in) {
+       protected Node importFile(Session session, String nodePath, InputStream in)
+                       throws RepositoryException {
                // 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);
+                       binary = session.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;
        }
index 48bb997c61f09b794441976011c9736accbf0e3f..4038dccc2cd147179bbdb56f12e7adf680bd1bb5 100644 (file)
@@ -6,6 +6,9 @@ mixin
 // URI(s)
 - argeo:uri (STRING) m
 
+[argeo:references] > nt:unstructured
+- * (REFERENCE) *
+
 // USER NODES
 // user should be lower case, between 3 and 15 characters long
 [argeo:userHome] > mix:created, mix:lastModified