You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ol...@apache.org on 2016/08/12 11:02:39 UTC
svn commit: r1756146 - in
/sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling: jcr/
jcr/oak/ jcr/oak/server/ oak/
Author: olli
Date: Fri Aug 12 11:02:39 2016
New Revision: 1756146
URL: http://svn.apache.org/viewvc?rev=1756146&view=rev
Log:
Move package oak into org.apache.sling.jcr
Added:
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepository.java
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManager.java
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManagerConfiguration.java
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitRepository.java
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitSession.java
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/package-info.java
Removed:
sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/oak/
Added: sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepository.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepository.java?rev=1756146&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepository.java (added)
+++ sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepository.java Fri Aug 12 11:02:39 2016
@@ -0,0 +1,85 @@
+/*
+ * 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 SF 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.oak.server;
+
+import java.security.Principal;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.security.auth.Subject;
+
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.oak.api.AuthInfo;
+import org.apache.jackrabbit.oak.spi.security.authentication.AuthInfoImpl;
+import org.apache.jackrabbit.oak.spi.security.principal.AdminPrincipal;
+import org.apache.sling.jcr.base.AbstractSlingRepository2;
+import org.apache.sling.jcr.base.AbstractSlingRepositoryManager;
+import org.osgi.framework.Bundle;
+
+import static java.util.Collections.singleton;
+
+/**
+ * A Sling repository implementation that wraps the Oak OSGi repository
+ * implementation from the Oak project.
+ */
+public class OakSlingRepository extends AbstractSlingRepository2 {
+
+ private final String adminId;
+
+ protected OakSlingRepository(final AbstractSlingRepositoryManager manager, final Bundle usingBundle, final String adminId) {
+ super(manager, usingBundle);
+ this.adminId = adminId;
+ }
+
+ @Override
+ protected Session createAdministrativeSession(String workspace) throws RepositoryException {
+ // TODO: use principal provider to retrieve admin principal
+ Set<? extends Principal> principals = singleton(new AdminPrincipal() {
+ @Override
+ public String getName() {
+ return OakSlingRepository.this.adminId;
+ }
+ });
+ AuthInfo authInfo = new AuthInfoImpl(this.adminId, Collections.<String, Object> emptyMap(), principals);
+ Subject subject = new Subject(true, principals, singleton(authInfo), Collections.<Object> emptySet());
+ Session adminSession;
+ try {
+ adminSession = Subject.doAsPrivileged(subject, new PrivilegedExceptionAction<Session>() {
+ @Override
+ public Session run() throws Exception {
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put("oak.refresh-interval", 0);
+ // TODO OAK-803: Backwards compatibility of long-lived sessions
+ JackrabbitRepository repo = (JackrabbitRepository) getRepository();
+ return repo.login(null, null, attrs);
+ }
+ }, null);
+ } catch (PrivilegedActionException e) {
+ throw new RepositoryException("failed to retrieve admin session.", e);
+ }
+
+ return adminSession;
+ }
+
+}
Added: sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManager.java?rev=1756146&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManager.java (added)
+++ sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManager.java Fri Aug 12 11:02:39 2016
@@ -0,0 +1,327 @@
+/*
+ * 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 SF 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.oak.server;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.Executor;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
+import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
+import org.apache.jackrabbit.oak.plugins.commit.JcrConflictHandler;
+import org.apache.jackrabbit.oak.plugins.index.aggregate.NodeAggregator;
+import org.apache.jackrabbit.oak.plugins.index.aggregate.SimpleNodeAggregator;
+import org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper;
+import org.apache.jackrabbit.oak.plugins.name.NameValidatorProvider;
+import org.apache.jackrabbit.oak.plugins.name.NamespaceEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.apache.jackrabbit.oak.plugins.observation.CommitRateLimiter;
+import org.apache.jackrabbit.oak.plugins.version.VersionHook;
+import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardIndexEditorProvider;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardIndexProvider;
+import org.apache.sling.commons.threads.ThreadPool;
+import org.apache.sling.commons.threads.ThreadPoolManager;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.base.AbstractSlingRepository2;
+import org.apache.sling.jcr.base.AbstractSlingRepositoryManager;
+import org.apache.sling.serviceusermapping.ServiceUserMapper;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.osgi.service.metatype.annotations.Designate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.collect.ImmutableSet.of;
+import static java.util.Collections.singleton;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexUtils.createIndexDefinition;
+
+/**
+ * A Sling repository implementation that wraps the Oak repository
+ * implementation from the Jackrabbit Oak project.
+ */
+@Component(
+ immediate = true
+)
+@Designate(
+ ocd = OakSlingRepositoryManagerConfiguration.class
+)
+public class OakSlingRepositoryManager extends AbstractSlingRepositoryManager {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference
+ private ServiceUserMapper serviceUserMapper;
+
+ @Reference
+ private NodeStore nodeStore;
+
+ private ComponentContext componentContext;
+
+ @Reference
+ private ThreadPoolManager threadPoolManager = null;
+
+ private ThreadPool threadPool;
+
+ private ServiceRegistration oakExecutorServiceReference;
+
+ private final WhiteboardIndexProvider indexProvider = new WhiteboardIndexProvider();
+
+ private final WhiteboardIndexEditorProvider indexEditorProvider = new WhiteboardIndexEditorProvider();
+
+ private CommitRateLimiter commitRateLimiter;
+
+ private OakSlingRepositoryManagerConfiguration configuration;
+
+ @Reference(
+ policy = ReferencePolicy.STATIC,
+ policyOption = ReferencePolicyOption.GREEDY
+ )
+ private SecurityProvider securityProvider = null;
+
+ private ServiceRegistration nodeAggregatorRegistration;
+
+ public OakSlingRepositoryManager() {
+ }
+
+ @Override
+ protected ServiceUserMapper getServiceUserMapper() {
+ return this.serviceUserMapper;
+ }
+
+ @Override
+ protected Repository acquireRepository() {
+ final BundleContext bundleContext = componentContext.getBundleContext();
+ final Whiteboard whiteboard = new OsgiWhiteboard(bundleContext);
+ this.indexProvider.start(whiteboard);
+ this.indexEditorProvider.start(whiteboard);
+ this.oakExecutorServiceReference = bundleContext.registerService(
+ Executor.class.getName(), new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ threadPool.execute(command);
+ }
+ }, new Hashtable<String, Object>());
+
+ final Oak oak = new Oak(nodeStore)
+ .withAsyncIndexing("async", 5);
+
+ final Jcr jcr = new Jcr(oak, false)
+ .with(new InitialContent())
+ .with(new ExtraSlingContent())
+
+ .with(JcrConflictHandler.createJcrConflictHandler())
+ .with(new VersionHook())
+
+ .with(securityProvider)
+
+ .with(new NameValidatorProvider())
+ .with(new NamespaceEditorProvider())
+ .with(new TypeEditorProvider())
+ .with(new ConflictValidatorProvider())
+
+ // index stuff
+ .with(indexProvider)
+ .with(indexEditorProvider)
+ .with(getDefaultWorkspace())
+ .with(whiteboard)
+ .withFastQueryResultSize(true)
+ .withObservationQueueLength(configuration.oak_observation_queue_length());
+
+ if (commitRateLimiter != null) {
+ jcr.with(commitRateLimiter);
+ }
+
+ jcr.createContentRepository();
+
+ return new TCCLWrappingJackrabbitRepository((JackrabbitRepository) jcr.createRepository());
+ }
+
+ private void setup(final SlingRepository repository) {
+ final boolean anonymous_read_all = configuration.anonymous_read_all();
+ if (anonymous_read_all) {
+ log.warn("anonymous.read.all is true, granting anonymous user read access on /");
+ Session session = null;
+ try {
+ // TODO do we need to go via PrivilegeManager for the names? See OAK-1016 example.
+ session = repository.loginAdministrative(getDefaultWorkspace());
+ final String[] privileges = new String[]{Privilege.JCR_READ};
+ AccessControlUtils.addAccessControlEntry(
+ session,
+ "/",
+ EveryonePrincipal.getInstance(),
+ privileges,
+ true);
+ session.save();
+ } catch (RepositoryException re) {
+ log.error("TODO: Failed setting up anonymous access", re);
+ } finally {
+ if (session != null) {
+ session.logout();
+ }
+ }
+ } else {
+ log.warn("TODO: should disable anonymous access when anonymous.read.all becomes false");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Dictionary<String, Object> getServiceRegistrationProperties() {
+ return componentContext.getProperties();
+ }
+
+ @Override
+ protected AbstractSlingRepository2 create(Bundle usingBundle) {
+ final String adminId = getAdminId();
+ final AbstractSlingRepository2 slingRepository = new OakSlingRepository(this, usingBundle, adminId);
+ setup(slingRepository);
+ return slingRepository;
+ }
+
+ @Override
+ protected void destroy(AbstractSlingRepository2 repositoryServiceInstance) {
+ // nothing to do, just drop the reference
+ }
+
+ @Override
+ protected void disposeRepository(Repository repository) {
+ this.indexProvider.stop();
+ this.indexEditorProvider.stop();
+ this.oakExecutorServiceReference.unregister();
+ this.oakExecutorServiceReference = null;
+ ((JackrabbitRepository) repository).shutdown();
+ }
+
+ @Activate
+ private void activate(final OakSlingRepositoryManagerConfiguration configuration, final ComponentContext componentContext) {
+ this.configuration = configuration;
+ this.componentContext = componentContext;
+ final BundleContext bundleContext = componentContext.getBundleContext();
+
+ final String defaultWorkspace = configuration.defaultWorkspace();
+ final boolean disableLoginAdministrative = !configuration.admin_login_enabled();
+
+ if (configuration.oak_observation_limitCommitRate()) {
+ commitRateLimiter = new CommitRateLimiter();
+ }
+ this.threadPool = threadPoolManager.get("oak-observation");
+ this.nodeAggregatorRegistration = bundleContext.registerService(NodeAggregator.class.getName(), getNodeAggregator(), null);
+
+ super.start(bundleContext, defaultWorkspace, disableLoginAdministrative);
+ }
+
+ @Deactivate
+ private void deactivate() {
+ super.stop();
+ this.componentContext = null;
+ this.threadPoolManager.release(this.threadPool);
+ this.threadPool = null;
+ this.nodeAggregatorRegistration.unregister();
+ }
+
+ private String getAdminId() {
+ return securityProvider.getConfiguration(UserConfiguration.class).getParameters().getConfigValue(UserConstants.PARAM_ADMIN_ID, UserConstants.DEFAULT_ADMIN_ID);
+ }
+
+ private static NodeAggregator getNodeAggregator() {
+ return new SimpleNodeAggregator().newRuleWithName(JcrConstants.NT_FILE, Collections.singletonList(JcrConstants.JCR_CONTENT));
+ }
+
+ private static final class ExtraSlingContent implements RepositoryInitializer {
+
+
+ @Override
+ public void initialize(NodeBuilder root) {
+ if (root.hasChildNode(INDEX_DEFINITIONS_NAME)) {
+ NodeBuilder index = root.child(INDEX_DEFINITIONS_NAME);
+
+ // jcr:
+ property(index, "jcrLanguage", "jcr:language");
+ property(index, "jcrLockOwner", "jcr:lockOwner");
+
+ // sling:
+ property(index, "slingAlias", "sling:alias");
+ property(index, "slingResource", "sling:resource");
+ property(index, "slingResourceType", "sling:resourceType");
+ property(index, "slingVanityPath", "sling:vanityPath");
+
+ // various
+ property(index, "event.job.topic", "event.job.topic");
+ property(index, "slingeventEventId", "slingevent:eventId");
+ property(index, "extensionType", "extensionType");
+ property(index, "lockCreated", "lock.created");
+ property(index, "status", "status");
+ property(index, "type", "type");
+
+ // lucene full-text index
+ if (!index.hasChildNode("lucene")) {
+ LuceneIndexHelper.newLuceneIndexDefinition(
+ index, "lucene", LuceneIndexHelper.JR_PROPERTY_INCLUDES,
+ of(
+ "jcr:createdBy",
+ "jcr:lastModifiedBy",
+ "sling:alias",
+ "sling:resourceType",
+ "sling:vanityPath"),
+ "async");
+ }
+
+ }
+ }
+
+ /**
+ * A convenience method to create a non-unique property index.
+ */
+ private static void property(NodeBuilder index, String indexName, String propertyName) {
+ if (!index.hasChildNode(indexName)) {
+ createIndexDefinition(index, indexName, true, false, singleton(propertyName), null);
+ }
+ }
+
+ }
+
+}
Added: sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManagerConfiguration.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManagerConfiguration.java?rev=1756146&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManagerConfiguration.java (added)
+++ sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/OakSlingRepositoryManagerConfiguration.java Fri Aug 12 11:02:39 2016
@@ -0,0 +1,74 @@
+/*
+ * 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 SF 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.oak.server;
+
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@ObjectClassDefinition(
+ name = "Apache Sling JCR Oak Repository",
+ description = "Configuration to launch an embedded JCR Repository and provide it as a SlingRepository and a standard JCR Repository. In addition, if the registration URL is not empty, the repository is registered as defined."
+)
+@interface OakSlingRepositoryManagerConfiguration {
+
+ @AttributeDefinition(
+ name = "Repository Name",
+ description = "The name under which the repository will be registered in JNDI and RMI registries."
+ )
+ String name() default "oak-sling-repository";
+
+ @AttributeDefinition(
+ name = "Default Workspace",
+ description = "Name of the workspace to use by default if not is given in any of the login methods. This name is used "
+ + "to implement the SlingRepository.getDefaultWorkspace() "
+ + "method. If this name is empty, a null value is used in "
+ + "JCR calls so that the default workspace provided by the JCR repository is used."
+ )
+ String defaultWorkspace() default "default";
+
+ // For backwards compatibility loginAdministrative is still enabled
+ // In future releases, this default may change to false.
+ @AttributeDefinition(
+ name = "Enable Administrator Login",
+ description = "Whether to enable or disable the SlingRepository.loginAdministrative "
+ + "method. The default is 'true'. See "
+ + "http://sling.apache.org/documentation/the-sling-engine/service-authentication.html "
+ + "for information on deprecating and disabling the loginAdministrative method."
+ )
+ boolean admin_login_enabled() default true;
+
+ @AttributeDefinition(
+ name = "Allow anonymous reads",
+ description = "If true, the anonymous user has read access to the whole repository (for backwards compatibility)"
+ )
+ boolean anonymous_read_all() default true;
+
+ @AttributeDefinition(
+ name = "Observation queue length",
+ description = "Maximum number of pending revisions in a observation listener queue"
+ )
+ int oak_observation_queue_length() default 1000;
+
+ @AttributeDefinition(
+ name = "Commit rate limiter",
+ description = "Limit the commit rate once the number of pending revisions in the observation "
+ + "queue exceed 90% of its capacity."
+ )
+ boolean oak_observation_limitCommitRate() default false;
+
+}
Added: sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitRepository.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitRepository.java?rev=1756146&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitRepository.java (added)
+++ sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitRepository.java Fri Aug 12 11:02:39 2016
@@ -0,0 +1,127 @@
+/*
+ * 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.oak.server;
+
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.oak.Oak;
+
+/**
+ * Custom <tt>JackrabbitRepository</tt> that ensures that the correct <tt>TCCL</tt> is set in OSGi environments
+ *
+ * <p>Oak still requires that for {@link JackrabbitRepository#login()} and
+ * {@link JackrabbitSession#impersonate(Credentials)} calls a custom thread context class loader is set. This wrapper
+ * simply ensures that the TCCL is set for all calls.</p>
+ */
+public class TCCLWrappingJackrabbitRepository implements JackrabbitRepository {
+
+ private final JackrabbitRepository wrapped;
+
+ public TCCLWrappingJackrabbitRepository(JackrabbitRepository wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ // calls setting the TCCL
+
+ @Override
+ public Session login(Credentials credentials, String workspaceName)
+ throws LoginException, NoSuchWorkspaceException, RepositoryException {
+ return login(credentials, workspaceName, null);
+ }
+
+ @Override
+ public Session login(Credentials credentials) throws LoginException, RepositoryException {
+ return login(credentials, null, null);
+ }
+
+ @Override
+ public Session login(String workspaceName) throws LoginException, NoSuchWorkspaceException, RepositoryException {
+ return login(null, workspaceName, null);
+ }
+
+ @Override
+ public Session login() throws LoginException, RepositoryException {
+ return login(null, null);
+ }
+
+ @Override
+ public Session login(Credentials credentials, String workspaceName, Map<String, Object> attributes)
+ throws LoginException, NoSuchWorkspaceException, RepositoryException {
+
+ Thread thread = Thread.currentThread();
+
+ ClassLoader oldClassLoader = thread.getContextClassLoader();
+ thread.setContextClassLoader(Oak.class.getClassLoader());
+
+ try {
+ Session session = wrapped.login(credentials, workspaceName,attributes);
+ return new TCCLWrappingJackrabbitSession((JackrabbitSession) session);
+ } finally {
+ thread.setContextClassLoader(oldClassLoader);
+ }
+ }
+
+ // only pure delegate methods below
+
+ @Override
+ public String[] getDescriptorKeys() {
+ return wrapped.getDescriptorKeys();
+ }
+
+ @Override
+ public boolean isStandardDescriptor(String key) {
+ return wrapped.isStandardDescriptor(key);
+ }
+
+ @Override
+ public boolean isSingleValueDescriptor(String key) {
+ return wrapped.isSingleValueDescriptor(key);
+ }
+
+ @Override
+ public Value getDescriptorValue(String key) {
+ return wrapped.getDescriptorValue(key);
+ }
+
+ @Override
+ public Value[] getDescriptorValues(String key) {
+ return wrapped.getDescriptorValues(key);
+ }
+
+ @Override
+ public String getDescriptor(String key) {
+ return wrapped.getDescriptor(key);
+ }
+
+ @Override
+ public void shutdown() {
+ wrapped.shutdown();
+
+ }
+
+}
Added: sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitSession.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitSession.java?rev=1756146&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitSession.java (added)
+++ sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/TCCLWrappingJackrabbitSession.java Fri Aug 12 11:02:39 2016
@@ -0,0 +1,340 @@
+/*
+ * 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.oak.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.AccessControlException;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.InvalidSerializedDataException;
+import javax.jcr.Item;
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.LoginException;
+import javax.jcr.NamespaceException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFactory;
+import javax.jcr.Workspace;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.retention.RetentionManager;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.version.VersionException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.Oak;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Custom <tt>JackrabbitSession</tt> that ensures that the correct <tt>TCCL</tt> is set in OSGi environments
+ *
+ *
+ * @see #TCCLWrappingJackrabbitSession(JackrabbitSession)
+ */
+public class TCCLWrappingJackrabbitSession implements JackrabbitSession {
+
+ private final JackrabbitSession wrapped;
+
+ public TCCLWrappingJackrabbitSession(JackrabbitSession wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ // calls setting the TCCL
+
+ @Override
+ public Session impersonate(Credentials credentials) throws LoginException, RepositoryException {
+
+ Thread thread = Thread.currentThread();
+
+ ClassLoader oldClassLoader = thread.getContextClassLoader();
+ thread.setContextClassLoader(Oak.class.getClassLoader());
+
+ try {
+ Session session = wrapped.impersonate(credentials);
+ return new TCCLWrappingJackrabbitSession((JackrabbitSession) session);
+ } finally {
+ thread.setContextClassLoader(oldClassLoader);
+ }
+ }
+
+ // only pure delegate methods below
+
+ @Override
+ public Repository getRepository() {
+ return wrapped.getRepository();
+ }
+
+ @Override
+ public String getUserID() {
+ return wrapped.getUserID();
+ }
+
+ @Override
+ public String[] getAttributeNames() {
+ return wrapped.getAttributeNames();
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ return wrapped.getAttribute(name);
+ }
+
+ @Override
+ public boolean hasPermission(String absPath, String... actions) throws RepositoryException {
+ return wrapped.hasPermission(absPath, actions);
+ }
+
+ @Override
+ public Workspace getWorkspace() {
+ return wrapped.getWorkspace();
+ }
+
+ @Override
+ public Node getRootNode() throws RepositoryException {
+ return wrapped.getRootNode();
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public Node getNodeByUUID(String uuid) throws ItemNotFoundException, RepositoryException {
+ return wrapped.getNodeByUUID(uuid);
+ }
+
+ @Override
+ public Node getNodeByIdentifier(String id) throws ItemNotFoundException, RepositoryException {
+ return wrapped.getNodeByIdentifier(id);
+ }
+
+ @Override
+ public Item getItem(String absPath) throws PathNotFoundException, RepositoryException {
+ return wrapped.getItem(absPath);
+ }
+
+ @Override
+ public PrincipalManager getPrincipalManager()
+ throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
+ return wrapped.getPrincipalManager();
+ }
+
+ @Override
+ public Node getNode(String absPath) throws PathNotFoundException, RepositoryException {
+ return wrapped.getNode(absPath);
+ }
+
+ @Override
+ public Property getProperty(String absPath) throws PathNotFoundException, RepositoryException {
+ return wrapped.getProperty(absPath);
+ }
+
+ @Override
+ public UserManager getUserManager()
+ throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
+ return wrapped.getUserManager();
+ }
+
+ @Override
+ public boolean itemExists(String absPath) throws RepositoryException {
+ return wrapped.itemExists(absPath);
+ }
+
+ @Override
+ public Item getItemOrNull(String absPath) throws RepositoryException {
+ return wrapped.getItemOrNull(absPath);
+ }
+
+ @Override
+ public boolean nodeExists(String absPath) throws RepositoryException {
+ return wrapped.nodeExists(absPath);
+ }
+
+ @Override
+ public Property getPropertyOrNull(String absPath) throws RepositoryException {
+ return wrapped.getPropertyOrNull(absPath);
+ }
+
+ @Override
+ public boolean propertyExists(String absPath) throws RepositoryException {
+ return wrapped.propertyExists(absPath);
+ }
+
+ @Override
+ public Node getNodeOrNull(String absPath) throws RepositoryException {
+ return wrapped.getNodeOrNull(absPath);
+ }
+
+ @Override
+ public void move(String srcAbsPath, String destAbsPath) throws ItemExistsException, PathNotFoundException,
+ VersionException, ConstraintViolationException, LockException, RepositoryException {
+ wrapped.move(srcAbsPath, destAbsPath);
+ }
+
+ @Override
+ public void removeItem(String absPath) throws VersionException, LockException, ConstraintViolationException,
+ AccessDeniedException, RepositoryException {
+ wrapped.removeItem(absPath);
+ }
+
+ @Override
+ public void save() throws AccessDeniedException, ItemExistsException, ReferentialIntegrityException,
+ ConstraintViolationException, InvalidItemStateException, VersionException, LockException,
+ NoSuchNodeTypeException, RepositoryException {
+ wrapped.save();
+ }
+
+ @Override
+ public void refresh(boolean keepChanges) throws RepositoryException {
+ wrapped.refresh(keepChanges);
+ }
+
+ @Override
+ public boolean hasPendingChanges() throws RepositoryException {
+ return wrapped.hasPendingChanges();
+ }
+
+ @Override
+ public ValueFactory getValueFactory() throws UnsupportedRepositoryOperationException, RepositoryException {
+ return wrapped.getValueFactory();
+ }
+
+ @Override
+ public boolean hasPermission(String absPath, String actions) throws RepositoryException {
+ return wrapped.hasPermission(absPath, actions);
+ }
+
+ @Override
+ public void checkPermission(String absPath, String actions) throws AccessControlException, RepositoryException {
+ wrapped.checkPermission(absPath, actions);
+ }
+
+ @Override
+ public boolean hasCapability(String methodName, Object target, Object[] arguments) throws RepositoryException {
+ return wrapped.hasCapability(methodName, target, arguments);
+ }
+
+ @Override
+ public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) throws PathNotFoundException,
+ ConstraintViolationException, VersionException, LockException, RepositoryException {
+ return wrapped.getImportContentHandler(parentAbsPath, uuidBehavior);
+ }
+
+ @Override
+ public void importXML(String parentAbsPath, InputStream in, int uuidBehavior)
+ throws IOException, PathNotFoundException, ItemExistsException, ConstraintViolationException,
+ VersionException, InvalidSerializedDataException, LockException, RepositoryException {
+ wrapped.importXML(parentAbsPath, in, uuidBehavior);
+ }
+
+ @Override
+ public void exportSystemView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse)
+ throws PathNotFoundException, SAXException, RepositoryException {
+ wrapped.exportSystemView(absPath, contentHandler, skipBinary, noRecurse);
+ }
+
+ @Override
+ public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse)
+ throws IOException, PathNotFoundException, RepositoryException {
+ wrapped.exportSystemView(absPath, out, skipBinary, noRecurse);
+ }
+
+ @Override
+ public void exportDocumentView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse)
+ throws PathNotFoundException, SAXException, RepositoryException {
+ wrapped.exportDocumentView(absPath, contentHandler, skipBinary, noRecurse);
+ }
+
+ @Override
+ public void exportDocumentView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse)
+ throws IOException, PathNotFoundException, RepositoryException {
+ wrapped.exportDocumentView(absPath, out, skipBinary, noRecurse);
+ }
+
+ @Override
+ public void setNamespacePrefix(String prefix, String uri) throws NamespaceException, RepositoryException {
+ wrapped.setNamespacePrefix(prefix, uri);
+ }
+
+ @Override
+ public String[] getNamespacePrefixes() throws RepositoryException {
+ return wrapped.getNamespacePrefixes();
+ }
+
+ @Override
+ public String getNamespaceURI(String prefix) throws NamespaceException, RepositoryException {
+ return wrapped.getNamespaceURI(prefix);
+ }
+
+ @Override
+ public String getNamespacePrefix(String uri) throws NamespaceException, RepositoryException {
+ return wrapped.getNamespacePrefix(uri);
+ }
+
+ @Override
+ public void logout() {
+ wrapped.logout();
+ }
+
+ @Override
+ public boolean isLive() {
+ return wrapped.isLive();
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public void addLockToken(String lt) {
+ wrapped.addLockToken(lt);
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public String[] getLockTokens() {
+ return wrapped.getLockTokens();
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public void removeLockToken(String lt) {
+ wrapped.removeLockToken(lt);
+ }
+
+ @Override
+ public AccessControlManager getAccessControlManager()
+ throws UnsupportedRepositoryOperationException, RepositoryException {
+ return wrapped.getAccessControlManager();
+ }
+
+ @Override
+ public RetentionManager getRetentionManager() throws UnsupportedRepositoryOperationException, RepositoryException {
+ return wrapped.getRetentionManager();
+ }
+}
Added: sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/package-info.java?rev=1756146&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/package-info.java (added)
+++ sling/trunk/bundles/jcr/oak-server/src/main/java/org/apache/sling/jcr/oak/server/package-info.java Fri Aug 12 11:02:39 2016
@@ -0,0 +1,23 @@
+/*
+ * 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 SF 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.
+ */
+
+/**
+ * Contains an implementation of a SlingRepository based on Apache Jackrabbit Oak.
+ * The package is not exported.
+ */
+package org.apache.sling.jcr.oak.server;