SLING-1212 - upgrading to Jackrabbit 2. Also includes re-revert of SLING-1363 and implementation of SLING-1330. Thanks to Felix for getting this started.
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@911430 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index d66fdca..cb6b01a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,9 +7,9 @@
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -64,9 +64,6 @@
<Private-Package>
org.apache.sling.jcr.base.internal.*
</Private-Package>
- <Embed-Dependency>
- jackrabbit-jcr-rmi;inline=true
- </Embed-Dependency>
</instructions>
</configuration>
</plugin>
@@ -90,21 +87,30 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.jcr.api</artifactId>
- <version>2.0.6</version>
+ <version>2.0.7-SNAPSHOT</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.jackrabbit</groupId>
- <artifactId>jackrabbit-api</artifactId>
- <version>1.5.0</version>
+ <version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-rmi</artifactId>
- <version>1.5.0</version>
+ <version>2.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-api</artifactId>
+ <version>2.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-jcr-commons</artifactId>
+ <version>2.0.0</version>
<scope>provided</scope>
</dependency>
<!-- OSGi Libraries -->
diff --git a/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java b/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java
index b02b704..697fa70 100644
--- a/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java
+++ b/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java
@@ -27,9 +27,11 @@
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
import javax.jcr.Workspace;
import org.apache.jackrabbit.api.JackrabbitWorkspace;
+import org.apache.sling.jcr.api.NamespaceMapper;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.base.internal.loader.Loader;
import org.apache.sling.jcr.base.util.RepositoryAccessor;
@@ -39,6 +41,7 @@
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
/**
* The <code>AbstractSlingRepository</code> is an abstract implementation of
@@ -135,6 +138,8 @@
// the background thread constantly checking the repository
private Thread repositoryPinger;
+ private ServiceTracker namespaceMapperTracker;
+
protected AbstractSlingRepository() {
}
@@ -247,7 +252,7 @@
throw new RepositoryException(re.getMessage(), re);
}
}
-
+
/**
* @param anonUser the user name of the anon user.
* @return a Credentials implementation that represents the anon user.
@@ -256,7 +261,7 @@
// NB: this method is overridden in the Jackrabbit Service bundle to avoid using the anon password. SLING-1282
return new SimpleCredentials(anonUser, anonPass);
}
-
+
/**
* @param adminUser the name of the administrative user.
* @return a Credentials implementation that represents the administrative user.
@@ -265,7 +270,7 @@
// NB: this method is overridden in the Jackrabbit Service bundle to avoid using the admin password. SLING-1282
return new SimpleCredentials(adminUser, adminPass);
}
-
+
/*
@@ -298,6 +303,58 @@
return new String[0];
}
+ /**
+ * {@inheritDoc}
+ */
+ public Value getDescriptorValue(String key) {
+ Repository repo = getRepository();
+ if (repo != null) {
+ return repo.getDescriptorValue(key);
+ }
+
+ log(LogService.LOG_ERROR, "getDescriptorValue: Repository not available");
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Value[] getDescriptorValues(String key) {
+ Repository repo = getRepository();
+ if (repo != null) {
+ return repo.getDescriptorValues(key);
+ }
+
+ log(LogService.LOG_ERROR, "getDescriptorValues: Repository not available");
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSingleValueDescriptor(String key) {
+ Repository repo = getRepository();
+ if (repo != null) {
+ return repo.isSingleValueDescriptor(key);
+ }
+
+ log(LogService.LOG_ERROR, "isSingleValueDescriptor: Repository not available");
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isStandardDescriptor(String key) {
+ Repository repo = getRepository();
+ if (repo != null) {
+ return repo.isStandardDescriptor(key);
+ }
+
+ log(LogService.LOG_ERROR, "isStandardDescriptor: Repository not available");
+ return false;
+ }
+
// ---------- logging ------------------------------------------------------
protected void log(int level, String message) {
@@ -552,6 +609,9 @@
* @throws nothing, but allow derived classes to throw any Exception
*/
protected void activate(ComponentContext componentContext) throws Exception {
+ this.namespaceMapperTracker = new ServiceTracker(componentContext.getBundleContext(), NamespaceMapper.class.getName(), null);
+ this.namespaceMapperTracker.open();
+
this.componentContext = componentContext;
@SuppressWarnings("unchecked")
@@ -598,6 +658,7 @@
* @param componentContext
*/
protected void deactivate(ComponentContext componentContext) {
+ this.namespaceMapperTracker.close();
componentContext.getBundleContext().removeBundleListener(this);
@@ -691,6 +752,14 @@
// apply namespace mapping
this.namespaceHandler.defineNamespacePrefixes(session);
}
+
+ // call namespace mappers
+ Object[] nsMappers = namespaceMapperTracker.getServices();
+ if (nsMappers != null) {
+ for (int i = 0; i < nsMappers.length; i++) {
+ ((NamespaceMapper) nsMappers[i]).defineNamespacePrefixes(session);
+ }
+ }
}
// ---------- Background operation checking repository availability --------
diff --git a/src/main/java/org/apache/sling/jcr/base/NodeTypeLoader.java b/src/main/java/org/apache/sling/jcr/base/NodeTypeLoader.java
index f979709..b841ed5 100644
--- a/src/main/java/org/apache/sling/jcr/base/NodeTypeLoader.java
+++ b/src/main/java/org/apache/sling/jcr/base/NodeTypeLoader.java
@@ -20,14 +20,16 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
import java.net.URL;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Workspace;
-import javax.jcr.nodetype.NodeTypeManager;
-import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
+import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.jackrabbit.commons.cnd.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -108,37 +110,17 @@
*/
public static boolean registerNodeType(Session session, InputStream source)
throws IOException, RepositoryException {
- final Workspace workspace = session.getWorkspace();
- final NodeTypeManager ntm = workspace.getNodeTypeManager();
- if (ntm instanceof JackrabbitNodeTypeManager) {
- log.debug("Using Jackrabbit to import node types");
- JackrabbitNodeTypeManager jntm = (JackrabbitNodeTypeManager) ntm;
- try {
- jntm.registerNodeTypes(source,
- JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
- return true;
- } catch (RepositoryException re) {
- Throwable t = re.getCause();
- if (t != null
- && t.getClass().getName().endsWith(
- ".InvalidNodeTypeDefException")) {
- // hacky wacky: interpret message to check whether it is for
- // duplicate node type -> very bad, that this is the only
- // way to check !!!
- if (re.getCause().getMessage().indexOf("already exists") >= 0) {
- // alright, node types are already registered, ignore
- // this
- log.debug("Node types already registered...");
- return true;
- }
- }
+ return registerNodeType(session, "cnd input stream", new InputStreamReader(source), false);
+ }
- // get here to rethrow the RepositoryException
- throw re;
- }
+ public static boolean registerNodeType(Session session, String systemId, Reader reader, boolean reregisterExisting)
+ throws IOException, RepositoryException {
+ try {
+ Workspace wsp = session.getWorkspace();
+ CndImporter.registerNodeTypes(reader, systemId, wsp.getNodeTypeManager(), wsp.getNamespaceRegistry(), session.getValueFactory(), reregisterExisting);
+ } catch (ParseException e) {
+ throw new IOException("Unable to parse CND Input.", e);
}
-
- log.warn("Repository does not implement JackrabbitNodeTypeManager, cannot import node types");
- return false;
+ return true;
}
}
diff --git a/src/main/java/org/apache/sling/jcr/base/internal/NamespaceMapper.java b/src/main/java/org/apache/sling/jcr/base/internal/NamespaceMapper.java
deleted file mode 100644
index 1d1a387..0000000
--- a/src/main/java/org/apache/sling/jcr/base/internal/NamespaceMapper.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sling.jcr.base.internal;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-/**
- * This interface is used to customize the namespace mapping of
- * a session.
- */
-public interface NamespaceMapper {
-
- void defineNamespacePrefixes(Session session)
- throws RepositoryException;
-}
diff --git a/src/main/java/org/apache/sling/jcr/base/internal/loader/Loader.java b/src/main/java/org/apache/sling/jcr/base/internal/loader/Loader.java
index cd5531f..2f71907 100644
--- a/src/main/java/org/apache/sling/jcr/base/internal/loader/Loader.java
+++ b/src/main/java/org/apache/sling/jcr/base/internal/loader/Loader.java
@@ -20,6 +20,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -33,9 +34,9 @@
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import org.apache.sling.jcr.api.NamespaceMapper;
import org.apache.sling.jcr.base.AbstractSlingRepository;
import org.apache.sling.jcr.base.NodeTypeLoader;
-import org.apache.sling.jcr.base.internal.NamespaceMapper;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -188,6 +189,17 @@
StringTokenizer tokener = new StringTokenizer(typesHeader, ",");
while (tokener.hasMoreTokens()) {
String nodeTypeFile = tokener.nextToken().trim();
+ Map<String,String> nodeTypeFileParams = new HashMap<String,String>();
+ nodeTypeFileParams.put("reregister", "true");
+
+ if (nodeTypeFile.contains(";")) {
+ int idx = nodeTypeFile.indexOf(';');
+ String nodeTypeFileParam = nodeTypeFile.substring(idx + 1);
+ String[] params = nodeTypeFileParam.split(":=");
+ nodeTypeFileParams.put(params[0], params[1]);
+ nodeTypeFile = nodeTypeFile.substring(0, idx);
+
+ }
URL mappingURL = bundle.getEntry(nodeTypeFile);
if (mappingURL == null) {
@@ -202,7 +214,9 @@
try {
// laod the node types
ins = mappingURL.openStream();
- NodeTypeLoader.registerNodeType(session, ins);
+ String reregister = nodeTypeFileParams.get("reregister");
+ boolean reregisterBool = Boolean.valueOf(reregister);
+ NodeTypeLoader.registerNodeType(session, mappingURL.toString(), new InputStreamReader(ins), reregisterBool);
// log a message if retry is successful
if ( isRetry ) {
log.info("Retrytring to register node types from {} in bundle {} succeeded.",
diff --git a/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java b/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java
index 5b893c8..d84a0b7 100644
--- a/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java
+++ b/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java
@@ -27,13 +27,13 @@
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
import org.apache.jackrabbit.api.JackrabbitSession;
-import org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
-import org.apache.jackrabbit.api.jsr283.security.AccessControlException;
-import org.apache.jackrabbit.api.jsr283.security.AccessControlList;
-import org.apache.jackrabbit.api.jsr283.security.AccessControlManager;
-import org.apache.jackrabbit.api.jsr283.security.Privilege;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.api.security.user.UserManager;