--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.server.jackrabbit.repo</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+#Wed Feb 23 10:53:42 CET 2011
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Repo
Bundle-SymbolicName: org.argeo.server.jackrabbit.repo
Bundle-Version: 0.2.3.SNAPSHOT
Import-Package: javax.jcr,
org.apache.jackrabbit.core,
org.apache.jackrabbit.core.config,
+ org.apache.lucene.util;version="2.4.1",
org.apache.xalan.processor,
org.argeo.server.jackrabbit,
org.springframework.beans.factory.config
http://www.springframework.org/schema/beans \r
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
\r
- <service ref="repository" interface="javax.jcr.Repository"\r
- context-class-loader="service-provider" />\r
+ <service ref="remoteJcrRepository" interface="javax.jcr.Repository">\r
+ <service-properties>\r
+ <beans:entry key="argeo.jcr.repository.name" value="remote_repo" />\r
+ </service-properties>\r
+ </service>\r
+\r
\r
</beans:beans>
\ No newline at end of file
</property>
</bean>
- <bean id="repository" class="org.argeo.server.jackrabbit.JackrabbitContainer">
- <property name="homeDirectory" value="${argeo.osgi.data.dir}/jackrabbit" />
- <property name="configuration" value="${argeo.jackrabbit.repo.configuration}" />
+ <bean id="remoteJcrRepository" class="org.argeo.server.jackrabbit.JackrabbitContainer">
+ <property name="uri"
+ value="http://localhost:7070/org.argeo.server.jcr.webapp/remoting/repo" />
+<!-- <property name="namespaces">-->
+<!-- <map>-->
+<!-- <entry key="slc" value="http://www.argeo.org/slc" />-->
+<!-- </map>-->
+<!-- </property>-->
+<!-- <property name="cndFiles">-->
+<!-- <list>-->
+<!-- <value>classpath:/org/argeo/slc/repo/repo.cnd</value>-->
+<!-- </list>-->
+<!-- </property>-->
</bean>
- <!--
- <bean id="repository"
- class="org.apache.jackrabbit.core.RepositoryImpl"
- factory-method="create"> <constructor-arg ref="repositoryConfig" />
- </bean> <bean id="repositoryConfig"
- class="org.apache.jackrabbit.core.config.RepositoryConfig"
- factory-method="create"> <constructor-arg
- value="osgibundle:repository.xml" type="java.io.InputStream" />
- <constructor-arg value="${argeo.osgi.data.dir}/jackrabbit"
- type="java.lang.String" /> </bean>
- -->
</beans>
\ No newline at end of file
--- /dev/null
+bin.includes = META-INF/
Bundle-Name: Webapp
Bundle-SymbolicName: org.argeo.server.jackrabbit.webapp
Bundle-Version: 1.0.0.qualifier
-Web-ContextPath: jcr
+Web-ContextPath: org.argeo.server.jcr.webapp
Bundle-Vendor: Argeo
Import-Package: javax.jcr,
javax.servlet,
</servlet-mapping>
<!-- Security -->
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
-
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
+<!-- <filter>-->
+<!-- <filter-name>springSecurityFilterChain</filter-name>-->
+<!-- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>-->
+<!-- </filter>-->
+<!---->
+<!-- <filter-mapping>-->
+<!-- <filter-name>springSecurityFilterChain</filter-name>-->
+<!-- <url-pattern>/*</url-pattern>-->
+<!-- </filter-mapping>-->
</web-app>
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.commons.NamespaceHelper;
import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.jackrabbit.core.RepositoryFactoryImpl;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.TransientRepository;
import org.apache.jackrabbit.core.config.RepositoryConfig;
import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
+import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
import org.argeo.ArgeoException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
private Resource variables;
private Boolean inMemory = false;
+ private String uri = null;
private Repository repository;
public void afterPropertiesSet() throws Exception {
// Load cnds as resources
for (String resUrl : cndFiles) {
-
Resource res = resourceLoader.getResource(resUrl);
byte[] arr = IOUtils.toByteArray(res.getInputStream());
cnds.add(arr);
}
- if (inMemory && homeDirectory.exists()) {
- FileUtils.deleteDirectory(homeDirectory);
- log.warn("Deleted Jackrabbit home directory " + homeDirectory);
- }
+ if (uri != null) {
+ // Thread.currentThread().setContextClassLoader(
+ // getClass().getClassLoader());
+ // repository = JcrUtils.getRepository(uri);
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(JcrUtils.REPOSITORY_URI, uri);
+ repository = new Jcr2davRepositoryFactory().getRepository(params);
+ if (repository == null)
+ throw new ArgeoException("Remote Davex repository " + uri
+ + " not found");
+ log.info("Initialized Jackrabbit repository " + repository
+ + " from uri " + uri);
+ } else {
+ if (inMemory && homeDirectory.exists()) {
+ FileUtils.deleteDirectory(homeDirectory);
+ log.warn("Deleted Jackrabbit home directory " + homeDirectory);
+ }
- RepositoryConfig config;
- InputStream in = configuration.getInputStream();
- InputStream propsIn = null;
- try {
- Properties vars = new Properties();
- if (variables != null) {
- propsIn = variables.getInputStream();
- vars.load(propsIn);
+ RepositoryConfig config;
+ InputStream in = configuration.getInputStream();
+ InputStream propsIn = null;
+ try {
+ Properties vars = new Properties();
+ if (variables != null) {
+ propsIn = variables.getInputStream();
+ vars.load(propsIn);
+ }
+ // override with system properties
+ vars.putAll(System.getProperties());
+ vars.put(
+ RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
+ homeDirectory.getCanonicalPath());
+ config = RepositoryConfig.create(new InputSource(in), vars);
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot read configuration", e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(propsIn);
}
- // override with system properties
- vars.putAll(System.getProperties());
- vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
- homeDirectory.getCanonicalPath());
- config = RepositoryConfig.create(new InputSource(in), vars);
- } catch (Exception e) {
- throw new RuntimeException("Cannot read configuration", e);
- } finally {
- IOUtils.closeQuietly(in);
- IOUtils.closeQuietly(propsIn);
- }
- if (inMemory)
- repository = new TransientRepository(config);
- else
- repository = RepositoryImpl.create(config);
+ if (inMemory)
+ repository = new TransientRepository(config);
+ else
+ repository = RepositoryImpl.create(config);
- log.info("Initialized Jackrabbit repository " + repository + " in "
- + homeDirectory + " with config " + configuration);
+ log.info("Initialized Jackrabbit repository " + repository + " in "
+ + homeDirectory + " with config " + configuration);
+ }
}
public void destroy() throws Exception {
if (repository != null) {
- if (repository instanceof RepositoryImpl)
+ if (repository instanceof JackrabbitRepository)
+ ((JackrabbitRepository) repository).shutdown();
+ else if (repository instanceof RepositoryImpl)
((RepositoryImpl) repository).shutdown();
else if (repository instanceof TransientRepository)
((TransientRepository) repository).shutdown();
log.debug("Deleted Jackrabbit home directory "
+ homeDirectory);
}
- log.info("Destroyed Jackrabbit repository " + repository + " in "
- + homeDirectory + " with config " + configuration);
+
+ if (uri != null)
+ log.info("Destroyed Jackrabbit repository with uri " + uri);
+ else
+ log.info("Destroyed Jackrabbit repository " + repository + " in "
+ + homeDirectory + " with config " + configuration);
}
// JCR REPOSITORY (delegated)
this.variables = variables;
}
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
}
import java.util.HashMap;
import java.util.Map;
+import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
private final static Log log = LogFactory
.getLog(CachingSessionProvider.class);
+ private Credentials credentials = null;
+
+ public CachingSessionProvider() {
+ }
+
+ public CachingSessionProvider(Credentials credentials) {
+ this.credentials = credentials;
+ }
+
@SuppressWarnings("unchecked")
public Session getSession(HttpServletRequest request, Repository rep,
String workspace) throws LoginException, ServletException,
Map<String, Session> sessions = (Map<String, Session>) httpSession
.getAttribute(JCR_SESSIONS_ATTRIBUTE);
if (!sessions.containsKey(workspace)) {
- Session session = rep.login(workspace);
+ Session session = rep.login(credentials, workspace);
sessions.put(workspace, session);
return session;
} else {
Session session = sessions.get(workspace);
if (!session.isLive()) {
- session = rep.login(workspace);
+ sessions.remove(workspace);
+ session = rep.login(credentials, workspace);
+ sessions.put(workspace, session);
}
return session;
}
public void releaseSession(Session session) {
if (log.isDebugEnabled())
log.debug("Releasing JCR session " + session);
- session.logout();
+ // session.logout();
+ // FIXME: find a way to log out when the HTTP session is expired
}
}
package org.argeo.server.jackrabbit.webdav;
-import java.util.Enumeration;
-
import javax.jcr.Repository;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
+import javax.jcr.SimpleCredentials;
import org.apache.jackrabbit.server.SessionProvider;
-import org.springframework.web.servlet.mvc.ServletWrappingController;
public class JcrRemotingServlet extends
org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet {
@Override
protected SessionProvider getSessionProvider() {
- return new CachingSessionProvider();
+ return new CachingSessionProvider(new SimpleCredentials("demo",
+ "demo".toCharArray()));
}
}
import javax.jcr.Repository;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
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.ArgeoException;
import org.argeo.jcr.RepositoryRegister;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
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 {
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());
+ if (log.isTraceEnabled()) {
+ log.trace("getContextPath=" + request.getContextPath());
+ log.trace("getServletPath=" + request.getServletPath());
+ log.trace("getPathInfo=" + request.getPathInfo());
+ }
- String repositoryName = "repo";
- String pathPrefix = "/remoting/repo";
- String beanName = "remoting_" + repositoryName;
+ String repositoryName = extractRepositoryName(request);
+ String pathPrefix = request.getServletPath() + '/' + repositoryName;
+ String beanName = pathPrefix;
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));
+ HttpServlet servlet = createServlet(repository, pathPrefix);
applicationContext.getBeanFactory().registerSingleton(beanName,
- jcrRemotingServlet);
+ servlet);
+ // TODO: unregister it as well
}
HttpServlet remotingServlet = (HttpServlet) applicationContext
.getBean(beanName);
return new HandlerExecutionChain(remotingServlet);
}
+ protected HttpServlet createServlet(Repository repository, String pathPrefix)
+ throws ServletException {
+ JcrRemotingServlet jcrRemotingServlet = new JcrRemotingServlet(
+ repository);
+ Properties initParameters = new Properties();
+ initParameters.setProperty(
+ JCRWebdavServerServlet.INIT_PARAM_RESOURCE_PATH_PREFIX,
+ pathPrefix);
+ jcrRemotingServlet.init(new DelegatingServletConfig(pathPrefix.replace(
+ '/', '_'), initParameters));
+ return jcrRemotingServlet;
+ }
+
+ /** The repository name is the first part of the path info */
+ protected String extractRepositoryName(HttpServletRequest request) {
+ String pathInfo = request.getPathInfo();
+ // TODO: optimize by checking character by character
+ String[] tokens = pathInfo.split("/");
+ StringBuffer currName = new StringBuffer("");
+ tokens: for (String token : tokens) {
+ if (token.equals(""))
+ continue tokens;
+ currName.append(token);
+ if (repositoryRegister.getRepositories().containsKey(
+ currName.toString()))
+ return currName.toString();
+ currName.append('/');
+ }
+ throw new ArgeoException("No repository can be found for request "
+ + pathInfo);
+ }
+
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
package org.argeo.jcr;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.SortedMap;
private final static Log log = LogFactory
.getLog(DefaultRepositoryRegister.class);
- private SortedMap<String, Repository> repositories = Collections
- .synchronizedSortedMap(new TreeMap<String, Repository>());
+ /** Read only map which will be directly exposed. */
+ private Map<String, Repository> repositories = Collections
+ .unmodifiableMap(new TreeMap<String, Repository>());
@SuppressWarnings("rawtypes")
public synchronized Repository getRepository(Map parameters)
return repositories.get(name);
}
- public Map<String, Repository> getRepositories() {
- return new TreeMap<String, Repository>(repositories);
+ /** Access to the read-only map */
+ public synchronized Map<String, Repository> getRepositories() {
+ return repositories;
}
/** Registers a service, typically called when OSGi services are bound. */
}
String name = properties.get(JCR_REPOSITORY_NAME).toString();
- repositories.put(name, repository);
+ Map<String, Repository> map = new TreeMap<String, Repository>(
+ repositories);
+ map.put(name, repository);
+ repositories = Collections.unmodifiableMap(map);
setChanged();
notifyObservers(repository);
}
}
String name = properties.get(JCR_REPOSITORY_NAME).toString();
- repositories.remove(name);
+ Map<String, Repository> map = new TreeMap<String, Repository>(
+ repositories);
+ map.put(name, repository);
+ repositories = Collections.unmodifiableMap(map);
setChanged();
notifyObservers(repository);
}
import javax.jcr.RepositoryFactory;
/** Allows to register repositories by name. */
-public interface RepositoryRegister extends RepositoryFactory{
+public interface RepositoryRegister extends RepositoryFactory {
public final static String JCR_REPOSITORY_NAME = "argeo.jcr.repository.name";
- public Map<String,Repository> getRepositories();
+ /**
+ * The registered {@link Repository} as a read-only map. Note that this
+ * method should be called for each access in order to be sure to be up to
+ * date in case repositories have registered/unregistered
+ */
+ public Map<String, Repository> getRepositories();
}
--- /dev/null
+package org.argeo.modeshape;
+
+import java.util.UUID;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.argeo.jcr.JcrUtils;
+import org.modeshape.connector.filesystem.FileSystemSource;
+import org.modeshape.jcr.JcrConfiguration;
+import org.modeshape.jcr.JcrEngine;
+
+public class FileSystemRepository {
+ public void init() {
+ try {
+ // Required in order to load mime type definitions
+ Thread.currentThread().setContextClassLoader(JcrConfiguration.class.getClassLoader());
+ JcrConfiguration config = new JcrConfiguration();
+ config.repositorySource("fsSource")
+ .usingClass(FileSystemSource.class)
+ .setDescription("The repository for our content")
+ .setProperty("workspaceRootPath", "/home/mbaudier/tmp")
+ .setProperty("defaultWorkspaceName", "prod")
+ .setProperty("predefinedWorkspaceNames",
+ new String[] { "staging", "dev" })
+ .setProperty(
+ "rootNodeUuid",
+ UUID.fromString("fd129c12-81a8-42ed-aa4b-820dba49e6f0"))
+ .setProperty("updatesAllowed", "true")
+ .setProperty("creatingWorkspaceAllowed", "false");
+ config.repository("fsRepo").setSource("fsSource");
+
+ JcrEngine jcrEngine = config.build();
+ jcrEngine.start();
+ Repository repository = jcrEngine.getRepository("fsRepo");
+ Session session = repository.login(new SimpleCredentials("demo",
+ "demo".toCharArray()));
+ JcrUtils.debug(session.getRootNode());
+ } catch (RepositoryException e) {
+ e.printStackTrace();
+ }
+ }
+}
<module>org.argeo.server.jxl</module>
<module>org.argeo.server.hibernate</module>
<module>org.argeo.server.ads</module>
- <module>org.argeo.server.jackrabbit</module>
<module>org.argeo.server.jcr</module>
+ <module>org.argeo.server.jackrabbit</module>
+ <module>org.argeo.server.modeshape</module>
</modules>
<build>
<resources>