From fea161ce3d77b81ae6ee0a7895f7bd64b4cb618e Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Tue, 22 Feb 2011 22:34:33 +0000 Subject: [PATCH] Work on JCR remoting git-svn-id: https://svn.argeo.org/commons/trunk@4166 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../ui/jcr/views/GenericJcrBrowser.java | 168 +++++++++++++++--- .../.project | 22 +++ .../.settings/org.eclipse.pde.core.prefs | 4 + .../META-INF/MANIFEST.MF | 19 ++ .../WEB-INF/applicationContext.xml | 15 ++ .../WEB-INF/osgi.xml | 18 ++ .../WEB-INF/remoting-servlet.xml | 21 +++ .../WEB-INF/security.xml | 14 ++ .../WEB-INF/web.xml | 53 ++++++ .../build.properties | 1 + .../jackrabbit/JackrabbitContainer.java | 12 +- .../webdav/CachingSessionProvider.java | 57 ++++++ .../webdav/ExtendedDispatcherServlet.java | 2 +- .../jackrabbit/webdav/JcrRemotingServlet.java | 33 ++++ .../MultipleRepositoryHandlerMapping.java | 105 +++++++++++ .../org.argeo.server.jcr/build.properties | 3 +- server/runtime/org.argeo.server.jcr/pom.xml | 7 + .../argeo/jcr/DefaultRepositoryRegister.java | 72 ++++++++ .../org/argeo/jcr/RepositoryRegister.java | 13 ++ 19 files changed, 610 insertions(+), 29 deletions(-) create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/.project create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/.settings/org.eclipse.pde.core.prefs create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/META-INF/MANIFEST.MF create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/applicationContext.xml create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/osgi.xml create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/remoting-servlet.xml create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/security.xml create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/web.xml create mode 100644 server/modules/org.argeo.server.jackrabbit.webapp.war/build.properties create mode 100644 server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/CachingSessionProvider.java create mode 100644 server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/JcrRemotingServlet.java create mode 100644 server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/MultipleRepositoryHandlerMapping.java create mode 100644 server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java create mode 100644 server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java diff --git a/eclipse/plugins/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/GenericJcrBrowser.java b/eclipse/plugins/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/GenericJcrBrowser.java index 069bf9758..e39bc5659 100644 --- a/eclipse/plugins/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/GenericJcrBrowser.java +++ b/eclipse/plugins/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/GenericJcrBrowser.java @@ -4,21 +4,28 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.TreeSet; import javax.jcr.Item; +import javax.jcr.LoginException; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Property; import javax.jcr.PropertyIterator; import javax.jcr.PropertyType; +import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.nodetype.NodeType; import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.RepositoryRegister; import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; @@ -27,6 +34,7 @@ import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TreeNode; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; @@ -44,7 +52,8 @@ public class GenericJcrBrowser extends ViewPart { private TreeViewer nodesViewer; private TableViewer propertiesViewer; - private Session jcrSession; + // private Session jcrSession; + private RepositoryRegister repositoryRegister; private Comparator itemComparator = new Comparator() { public int compare(Item o1, Item o2) { @@ -87,11 +96,19 @@ public class GenericJcrBrowser extends ViewPart { } } }); - try { - nodesViewer.setInput(jcrSession.getRootNode()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot initialize view", e); - } + nodesViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + Object obj = ((IStructuredSelection) event.getSelection()) + .getFirstElement(); + if (obj instanceof RepositoryNode) { + ((RepositoryNode) obj).login(); + } else if (obj instanceof WorkspaceNode) { + ((WorkspaceNode) obj).login(); + } + + } + }); + nodesViewer.setInput(repositoryRegister); Composite bottom = new Composite(sashForm, SWT.NONE); bottom.setLayout(new GridLayout(1, false)); @@ -168,13 +185,29 @@ public class GenericJcrBrowser extends ViewPart { return new int[] { 70, 30 }; } - public void setJcrSession(Session jcrSession) { - this.jcrSession = jcrSession; + public void setRepositoryRegister(RepositoryRegister repositoryRegister) { + this.repositoryRegister = repositoryRegister; } /* * NODES */ + protected Object[] childrenNodes(Node parentNode) { + try { + List children = new ArrayList(); + NodeIterator nit = parentNode.getNodes(); + while (nit.hasNext()) { + Node node = nit.nextNode(); + children.add(node); + } + Node[] arr = children.toArray(new Node[children.size()]); + Arrays.sort(arr, itemComparator); + return arr; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot list children of " + parentNode, e); + } + } + private class NodeContentProvider implements ITreeContentProvider { public Object[] getElements(Object inputElement) { @@ -182,23 +215,32 @@ public class GenericJcrBrowser extends ViewPart { } public Object[] getChildren(Object parentElement) { - try { - if (parentElement instanceof Node) { - List children = new ArrayList(); - NodeIterator nit = ((Node) parentElement).getNodes(); - while (nit.hasNext()) { - Node node = nit.nextNode(); - children.add(node); - } - Node[] arr = children.toArray(new Node[children.size()]); - Arrays.sort(arr, itemComparator); - return arr; - } else { - return null; + if (parentElement instanceof Node) { + return childrenNodes((Node) parentElement); + } else if (parentElement instanceof RepositoryNode) { + return ((RepositoryNode) parentElement).getChildren(); + } else if (parentElement instanceof WorkspaceNode) { + Session session = ((WorkspaceNode) parentElement).getSession(); + if (session == null) + return new Object[0]; + + try { + return childrenNodes(session.getRootNode()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot retrieve root node of " + + session, e); } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot retrieve children for " - + parentElement, e); + } else if (parentElement instanceof RepositoryRegister) { + RepositoryRegister repositoryRegister = (RepositoryRegister) parentElement; + List nodes = new ArrayList(); + Map repositories = repositoryRegister + .getRepositories(); + for (String name : repositories.keySet()) { + nodes.add(new RepositoryNode(name, repositories.get(name))); + } + return nodes.toArray(); + } else { + return new Object[0]; } } @@ -218,6 +260,10 @@ public class GenericJcrBrowser extends ViewPart { try { if (element instanceof Node) { return ((Node) element).hasNodes(); + } else if (element instanceof RepositoryNode) { + return ((RepositoryNode) element).hasChildren(); + } else if (element instanceof WorkspaceNode) { + return ((WorkspaceNode) element).getSession() != null; } return false; } catch (RepositoryException e) { @@ -297,4 +343,78 @@ public class GenericJcrBrowser extends ViewPart { } } + + private class RepositoryNode extends TreeParent { + private final String name; + private final Repository repository; + private Session defaultSession = null; + + public RepositoryNode(String name, Repository repository) { + super(name); + this.name = name; + this.repository = repository; + } + + public Repository getRepository() { + return repository; + } + + public Session getDefaultSession() { + return defaultSession; + } + + public void login() { + try { + defaultSession = repository.login(); + String[] wkpNames = defaultSession.getWorkspace() + .getAccessibleWorkspaceNames(); + for (String wkpName : wkpNames) { + if (wkpName.equals(defaultSession.getWorkspace().getName())) + addChild(new WorkspaceNode(repository, wkpName, + defaultSession)); + else + addChild(new WorkspaceNode(repository, wkpName)); + } + nodesViewer.refresh(this); + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot connect to repository " + name, e); + } + } + } + + private class WorkspaceNode extends TreeParent { + private final String name; + private final Repository repository; + private Session session = null; + + public WorkspaceNode(Repository repository, String name) { + this(repository, name, null); + } + + public WorkspaceNode(Repository repository, String name, Session session) { + super(name); + this.name = name; + this.repository = repository; + this.session = session; + } + + public Session getSession() { + return session; + } + + public void login() { + try { + if (session != null) + session.logout(); + + session = repository.login(name); + nodesViewer.refresh(this); + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot connect to repository " + name, e); + } + } + + } } diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/.project b/server/modules/org.argeo.server.jackrabbit.webapp.war/.project new file mode 100644 index 000000000..b3972fb62 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/.project @@ -0,0 +1,22 @@ + + + org.argeo.server.jackrabbit.webapp + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/.settings/org.eclipse.pde.core.prefs b/server/modules/org.argeo.server.jackrabbit.webapp.war/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..ee0c8b2c0 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Tue Feb 22 17:15:24 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/META-INF/MANIFEST.MF b/server/modules/org.argeo.server.jackrabbit.webapp.war/META-INF/MANIFEST.MF new file mode 100644 index 000000000..eadb4dc4b --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/META-INF/MANIFEST.MF @@ -0,0 +1,19 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Webapp +Bundle-SymbolicName: org.argeo.server.jackrabbit.webapp +Bundle-Version: 1.0.0.qualifier +Web-ContextPath: jcr +Bundle-Vendor: Argeo +Import-Package: javax.jcr, + javax.servlet, + javax.servlet.http, + javax.servlet.resources, + org.argeo.jcr, + org.argeo.server.jackrabbit.webdav, + org.springframework.osgi.web.context.support;version="1.2.1", + org.springframework.security;version="2.0.6.RELEASE", + org.springframework.security.ui.webapp;version="2.0.6.RELEASE", + org.springframework.web.context;version="2.5.6.SEC01", + org.springframework.web.filter;version="2.5.6.SEC01", + org.springframework.web.servlet.handler;version="2.5.6.SEC01" diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/applicationContext.xml b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/applicationContext.xml new file mode 100644 index 000000000..1aec32ee6 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/applicationContext.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/osgi.xml b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/osgi.xml new file mode 100644 index 000000000..80b804ef6 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/osgi.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/remoting-servlet.xml b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/remoting-servlet.xml new file mode 100644 index 000000000..c77def251 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/remoting-servlet.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/security.xml b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/security.xml new file mode 100644 index 000000000..2e08bfdb0 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/security.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/web.xml b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/web.xml new file mode 100644 index 000000000..b5a150944 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/WEB-INF/web.xml @@ -0,0 +1,53 @@ + + + + Argeo Jackrabbit Webapp + + + + contextConfigLocation + /WEB-INF/applicationContext.xml + + + + Spring Context + org.springframework.web.context.ContextLoaderListener + + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + + + + remoting + org.argeo.server.jackrabbit.webdav.ExtendedDispatcherServlet + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + + dispatchOptionsRequest + true + + 1 + + + + remoting + /remoting/* + + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + + springSecurityFilterChain + /* + + diff --git a/server/modules/org.argeo.server.jackrabbit.webapp.war/build.properties b/server/modules/org.argeo.server.jackrabbit.webapp.war/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/server/modules/org.argeo.server.jackrabbit.webapp.war/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/JackrabbitContainer.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/JackrabbitContainer.java index 1be03827a..6ec6065a5 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/JackrabbitContainer.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/JackrabbitContainer.java @@ -77,6 +77,8 @@ public class JackrabbitContainer implements InitializingBean, DisposableBean, /** Namespaces to register: key is prefix, value namespace */ private Map namespaces = new HashMap(); + private Boolean autocreateWorkspaces = false; + public void afterPropertiesSet() throws Exception { // Load cnds as resources for (String resUrl : cndFiles) { @@ -162,7 +164,10 @@ public class JackrabbitContainer implements InitializingBean, DisposableBean, try { session = repository.login(credentials, workspaceName); } catch (NoSuchWorkspaceException e) { - session = createWorkspaceAndLogsIn(credentials, workspaceName); + if (autocreateWorkspaces) + session = createWorkspaceAndLogsIn(credentials, workspaceName); + else + throw e; } processNewSession(session); return session; @@ -181,7 +186,10 @@ public class JackrabbitContainer implements InitializingBean, DisposableBean, try { session = repository.login(workspaceName); } catch (NoSuchWorkspaceException e) { - session = createWorkspaceAndLogsIn(null, workspaceName); + if (autocreateWorkspaces) + session = createWorkspaceAndLogsIn(null, workspaceName); + else + throw e; } processNewSession(session); return session; diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/CachingSessionProvider.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/CachingSessionProvider.java new file mode 100644 index 000000000..ad301871d --- /dev/null +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/CachingSessionProvider.java @@ -0,0 +1,57 @@ +package org.argeo.server.jackrabbit.webdav; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.LoginException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.server.SessionProvider; + +public class CachingSessionProvider implements SessionProvider { + private static final String JCR_SESSIONS_ATTRIBUTE = "jcrSessions"; + + private final static Log log = LogFactory + .getLog(CachingSessionProvider.class); + + @SuppressWarnings("unchecked") + public Session getSession(HttpServletRequest request, Repository rep, + String workspace) throws LoginException, ServletException, + RepositoryException { + HttpSession httpSession = request.getSession(); + + if (httpSession.getAttribute(JCR_SESSIONS_ATTRIBUTE) == null) { + httpSession + .setAttribute(JCR_SESSIONS_ATTRIBUTE, Collections + .synchronizedMap(new HashMap())); + } + Map sessions = (Map) httpSession + .getAttribute(JCR_SESSIONS_ATTRIBUTE); + if (!sessions.containsKey(workspace)) { + Session session = rep.login(workspace); + sessions.put(workspace, session); + return session; + } else { + Session session = sessions.get(workspace); + if (!session.isLive()) { + session = rep.login(workspace); + } + return session; + } + } + + public void releaseSession(Session session) { + if (log.isDebugEnabled()) + log.debug("Releasing JCR session " + session); + session.logout(); + } + +} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/ExtendedDispatcherServlet.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/ExtendedDispatcherServlet.java index 0db3dbda9..8c961c108 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/ExtendedDispatcherServlet.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/ExtendedDispatcherServlet.java @@ -26,7 +26,7 @@ import org.argeo.ArgeoException; import org.springframework.web.servlet.DispatcherServlet; public class ExtendedDispatcherServlet extends DispatcherServlet { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = -5584673209855752009L; private final static Log log = LogFactory .getLog(ExtendedDispatcherServlet.class); diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/JcrRemotingServlet.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/JcrRemotingServlet.java new file mode 100644 index 000000000..8fb580179 --- /dev/null +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/JcrRemotingServlet.java @@ -0,0 +1,33 @@ +package org.argeo.server.jackrabbit.webdav; + +import java.util.Enumeration; + +import javax.jcr.Repository; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; + +import org.apache.jackrabbit.server.SessionProvider; +import org.springframework.web.servlet.mvc.ServletWrappingController; + +public class JcrRemotingServlet extends + org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet { + + private static final long serialVersionUID = 3131835511468341309L; + + private final Repository repository; + + public JcrRemotingServlet(Repository repository) { + this.repository = repository; + } + + @Override + protected Repository getRepository() { + return repository; + } + + @Override + protected SessionProvider getSessionProvider() { + return new CachingSessionProvider(); + } + +} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/MultipleRepositoryHandlerMapping.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/MultipleRepositoryHandlerMapping.java new file mode 100644 index 000000000..077aa4fe6 --- /dev/null +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/webdav/MultipleRepositoryHandlerMapping.java @@ -0,0 +1,105 @@ +package org.argeo.server.jackrabbit.webdav; + +import java.util.Enumeration; +import java.util.Properties; + +import javax.jcr.Repository; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet; +import org.argeo.jcr.RepositoryRegister; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.web.context.ServletContextAware; +import org.springframework.web.servlet.HandlerExecutionChain; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.mvc.ServletWrappingController; + +public class MultipleRepositoryHandlerMapping implements HandlerMapping, + ApplicationContextAware, ServletContextAware { + private final static Log log = LogFactory + .getLog(MultipleRepositoryHandlerMapping.class); + + private ConfigurableApplicationContext applicationContext; + private ServletContext servletContext; + + private RepositoryRegister repositoryRegister; + + public HandlerExecutionChain getHandler(HttpServletRequest request) + throws Exception { + log.debug(request); + log.debug("getContextPath=" + request.getContextPath()); + log.debug("getServletPath=" + request.getServletPath()); + log.debug("getPathInfo=" + request.getPathInfo()); + + String repositoryName = "repo"; + String pathPrefix = "/remoting/repo"; + String beanName = "remoting_" + repositoryName; + + if (!applicationContext.containsBean(beanName)) { + Repository repository = repositoryRegister.getRepositories().get( + repositoryName); + JcrRemotingServlet jcrRemotingServlet = new JcrRemotingServlet( + repository); + Properties initParameters = new Properties(); + initParameters.setProperty( + JCRWebdavServerServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, + pathPrefix); + jcrRemotingServlet.init(new DelegatingServletConfig(beanName, + initParameters)); + applicationContext.getBeanFactory().registerSingleton(beanName, + jcrRemotingServlet); + } + HttpServlet remotingServlet = (HttpServlet) applicationContext + .getBean(beanName); + return new HandlerExecutionChain(remotingServlet); + } + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = (ConfigurableApplicationContext) applicationContext; + } + + public void setServletContext(ServletContext servletContext) { + this.servletContext = servletContext; + } + + public void setRepositoryRegister(RepositoryRegister repositoryRegister) { + this.repositoryRegister = repositoryRegister; + } + + private class DelegatingServletConfig implements ServletConfig { + private String name; + private Properties initParameters; + + public DelegatingServletConfig(String name, Properties initParameters) { + super(); + this.name = name; + this.initParameters = initParameters; + } + + public String getServletName() { + return name; + } + + public ServletContext getServletContext() { + return servletContext; + } + + public String getInitParameter(String paramName) { + return initParameters.getProperty(paramName); + } + + public Enumeration getInitParameterNames() { + return initParameters.keys(); + } + } + +} diff --git a/server/runtime/org.argeo.server.jcr/build.properties b/server/runtime/org.argeo.server.jcr/build.properties index 2f77ca900..a9dd55a1d 100644 --- a/server/runtime/org.argeo.server.jcr/build.properties +++ b/server/runtime/org.argeo.server.jcr/build.properties @@ -4,8 +4,7 @@ source.. = src/main/java/,\ output.. = target/classes/ bin.includes = META-INF/,\ . -additional.bundles = org.argeo.server.jackrabbit,\ - com.springsource.slf4j.api,\ +additional.bundles = com.springsource.slf4j.api,\ com.springsource.slf4j.log4j,\ com.springsource.org.apache.log4j,\ com.springsource.org.apache.commons.collections,\ diff --git a/server/runtime/org.argeo.server.jcr/pom.xml b/server/runtime/org.argeo.server.jcr/pom.xml index aa72e2870..1d30016fa 100644 --- a/server/runtime/org.argeo.server.jcr/pom.xml +++ b/server/runtime/org.argeo.server.jcr/pom.xml @@ -92,6 +92,13 @@ org.springframework.ws org.springframework.xml + + + + org.eclipse.osgi + org.eclipse.osgi + provided + diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java new file mode 100644 index 000000000..e2d985424 --- /dev/null +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java @@ -0,0 +1,72 @@ +package org.argeo.jcr; + +import java.util.Collections; +import java.util.Map; +import java.util.Observable; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class DefaultRepositoryRegister extends Observable implements + RepositoryRegister { + private final static Log log = LogFactory + .getLog(DefaultRepositoryRegister.class); + + private SortedMap repositories = Collections + .synchronizedSortedMap(new TreeMap()); + + @SuppressWarnings("rawtypes") + public synchronized Repository getRepository(Map parameters) + throws RepositoryException { + if (!parameters.containsKey(JCR_REPOSITORY_NAME)) + throw new RepositoryException("Parameter " + JCR_REPOSITORY_NAME + + " has to be defined."); + String name = parameters.get(JCR_REPOSITORY_NAME).toString(); + if (!repositories.containsKey(name)) + throw new RepositoryException("No repository registered with name " + + name); + + return repositories.get(name); + } + + public Map getRepositories() { + return new TreeMap(repositories); + } + + /** Registers a service, typically called when OSGi services are bound. */ + @SuppressWarnings("rawtypes") + public synchronized void register(Repository repository, Map properties) { + // TODO: also check bean name? + if (properties == null || !properties.containsKey(JCR_REPOSITORY_NAME)) { + log.warn("Cannot register a repository without property " + + JCR_REPOSITORY_NAME); + return; + } + + String name = properties.get(JCR_REPOSITORY_NAME).toString(); + repositories.put(name, repository); + setChanged(); + notifyObservers(repository); + } + + /** Unregisters a service, typically called when OSGi services are unbound. */ + @SuppressWarnings("rawtypes") + public synchronized void unregister(Repository repository, Map properties) { + // TODO: also check bean name? + if (properties == null || !properties.containsKey(JCR_REPOSITORY_NAME)) { + log.warn("Cannot unregister a repository without property " + + JCR_REPOSITORY_NAME); + return; + } + + String name = properties.get(JCR_REPOSITORY_NAME).toString(); + repositories.remove(name); + setChanged(); + notifyObservers(repository); + } +} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java new file mode 100644 index 000000000..8d317db25 --- /dev/null +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java @@ -0,0 +1,13 @@ +package org.argeo.jcr; + +import java.util.Map; + +import javax.jcr.Repository; +import javax.jcr.RepositoryFactory; + +/** Allows to register repositories by name. */ +public interface RepositoryRegister extends RepositoryFactory{ + public final static String JCR_REPOSITORY_NAME = "argeo.jcr.repository.name"; + + public Map getRepositories(); +} -- 2.39.2