Author: fmeschbe
Date: Wed Jul 3 09:36:42 2013
New Revision: 1499293
URL: http://svn.apache.org/r1499293
Log:
Implement support for service based ResourceResolver and Session access
- Use a proxy handler instead of a proxy to be able to implement
all interfaces exposed by the Repository service.
- Expose the jcr.base API at a version which matches the current
value.
- Implement the loginService method
- Register the service as a service factory to make sure each
bundle gets its own instance to be able to know the calling
bundle. This requires to make the registerService method final
and provide a new method to provide the actual service
registration interfaces. Extensions of the AbstractSlingRepository
base class may need to be fixed.
Added:
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/SlingRepositoryProxyHandler.java
Removed:
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/SlingRepositoryProxy.java
Modified:
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/pom.xml
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java
Modified:
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/pom.xml
URL:
http://svn.apache.org/viewvc/sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/pom.xml?rev=1499293&r1=1499292&r2=1499293&view=diff
==============================================================================
--- sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/pom.xml
(original)
+++ sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/pom.xml
Wed Jul 3 09:36:42 2013
@@ -58,7 +58,7 @@
sling,jcr,jackrabbit
</Bundle-Category>
<Export-Package>
- org.apache.sling.jcr.base;version=1.0,
+ org.apache.sling.jcr.base;version=2.2,
org.apache.sling.jcr.base.util;version=2.1.0
</Export-Package>
<Private-Package>
Modified:
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java?rev=1499293&r1=1499292&r2=1499293&view=diff
==============================================================================
---
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java
(original)
+++
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository.java
Wed Jul 3 09:36:42 2013
@@ -38,7 +38,6 @@ import org.apache.sling.jcr.base.util.Re
import org.apache.sling.serviceusermapping.ServiceUserMapper;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.log.LogService;
@@ -249,6 +248,33 @@ public abstract class AbstractSlingRepos
}
/**
+ * Actual implementation of the {@link #loginService(String, String)}
+ * method taking into account the bundle calling this method.
+ *
+ * @param usingBundle
+ * @param serviceInfo
+ * @param workspace
+ * @return
+ * @throws LoginException
+ * @throws RepositoryException
+ */
+ final Session loginService(final Bundle usingBundle, final String
serviceInfo, final String workspace)
+ throws LoginException, RepositoryException {
+ final String userName =
this.serviceUserMapper.getUserForService(usingBundle, serviceInfo);
+ final SimpleCredentials creds = new SimpleCredentials(userName, new
char[0]);
+
+ Session admin = null;
+ try {
+ admin = this.loginAdministrative(workspace);
+ return admin.impersonate(creds);
+ } finally {
+ if (admin != null) {
+ admin.logout();
+ }
+ }
+ }
+
+ /**
* @param anonUser the user name of the anon user.
* @return a Credentials implementation that represents the anon user.
*/
@@ -440,38 +466,59 @@ public abstract class AbstractSlingRepos
}
/**
- * Registers this component as an OSGi service with type
- * <code>javax.jcr.Repository</code> and
- * <code>org.apache.sling.jcr.api.SlingRepository</code> using the
- * component properties as service registration properties.
+ * Registers this component as an OSGi service with the types provided by
+ * the {@link #getServiceRegistrationInterfaces()} method and properties
+ * provided by the {@link #getServiceRegistrationProperties()} method.
* <p>
- * This method may be overwritten to register the component with different
- * types.
+ * This method is final and cannot be overwritten because the mechanism of
+ * service registration using a service factory is required to fully
+ * implement the {@link #loginService(String, String)} method.
*
- * @return The OSGi <code>ServiceRegistration</code> object representing
- * the registered service.
+ * @return The OSGi <code>ServiceRegistration</code> object representing
the
+ * registered service.
*/
protected final ServiceRegistration registerService() {
- Dictionary<String, Object> props = getServiceRegistrationProperties();
- String[] interfaces = getServiceRegistrationInterfaces();
+ final Dictionary<String, Object> props =
getServiceRegistrationProperties();
+ final String[] interfaces = getServiceRegistrationInterfaces();
return componentContext.getBundleContext().registerService(interfaces,
new ServiceFactory() {
public Object getService(Bundle bundle, ServiceRegistration
registration) {
- return new SlingRepositoryProxy(AbstractSlingRepository.this,
bundle, AbstractSlingRepository.this.serviceUserMapper);
+ return SlingRepositoryProxyHandler.createProxy(interfaces,
AbstractSlingRepository.this, bundle);
}
public void ungetService(Bundle bundle, ServiceRegistration
registration, Object service) {
// nothing to do (GC does the work for us)
}
- }, // was: this
- props);
+ }, props);
}
+ /**
+ * Return the service registration properties to be used to register the
+ * repository service in {@link #registerService()}.
+ * <p>
+ * This method may be overwritten to return additional service registration
+ * properties. But it is strongly recommended to always include the
+ * properties returned from this method.
+ *
+ * @return The service registration properties to be used to register the
+ * repository service in {@link #registerService()}
+ */
@SuppressWarnings("unchecked")
protected Dictionary<String, Object> getServiceRegistrationProperties() {
return componentContext.getProperties();
}
+ /**
+ * Returns the service types to be used to register the repository service
+ * in {@link #registerService()}. All interfaces returned must be
accessible
+ * to the class loader of the class of this instance.
+ * <p>
+ * This method may be overwritten to return additional types but the types
+ * returned from this base implementation must always be included.
+ *
+ * @return The service types to be used to register the repository service
+ * in {@link #registerService()}
+ */
protected String[] getServiceRegistrationInterfaces() {
return new String[] {
SlingRepository.class.getName(), Repository.class.getName()
Added:
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/SlingRepositoryProxyHandler.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/SlingRepositoryProxyHandler.java?rev=1499293&view=auto
==============================================================================
---
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/SlingRepositoryProxyHandler.java
(added)
+++
sling/whiteboard/fmeschbe/deprecate_login_administrative/jcr/base/src/main/java/org/apache/sling/jcr/base/SlingRepositoryProxyHandler.java
Wed Jul 3 09:36:42 2013
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.apache.sling.jcr.api.SlingRepository;
+import org.osgi.framework.Bundle;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>SlingRepositoryProxyHandler</code> class implements a proxy for
all
+ * service interfaces under which the {@link AbstractSlingRepository}
+ * implementation is registered.
+ * <p>
+ * All calls a directly handed through to the object except for the
+ * {@code loginService} call which is routed through
+ * {@code AbstractSlingRepository.loginService(Bundle, String, String)} method
+ * to influence logging in by the calling bundle.
+ */
+class SlingRepositoryProxyHandler implements InvocationHandler {
+
+ // The name of the method to re-route
+ private static final String LOGIN_SERVICE_NAME = "loginService";
+
+ // The signature of the loginService method to re-route
+ private static final Class<?>[] LOGIN_SERVICE_SIG = {
+ String.class, String.class
+ };
+
+ // The actual longService method object used for re-routing
+ private static final Method LOGIN_SERVICE;
+
+ // The delegatee object to which all calls are routed
+ private final AbstractSlingRepository delegatee;
+
+ // The bundle using this proxy service instance
+ private final Bundle usingBundle;
+
+ static {
+ Method tmplsm = null;
+ try {
+ tmplsm = SlingRepository.class.getMethod(LOGIN_SERVICE_NAME,
LOGIN_SERVICE_SIG);
+ } catch (Exception e) { // SecurityException e, NoSuchMethodException
+ LoggerFactory.getLogger(SlingRepositoryProxyHandler.class).error(
+ "[init]: Cannot get " + LOGIN_SERVICE_NAME + " method from
SlingRepository interface", e);
+ }
+ LOGIN_SERVICE = tmplsm;
+ }
+
+ /**
+ * Creates a new proxy instance for the given {@code delegatee} object. The
+ * proxy is handled by a new instance of this
+ * {@code SlingRepositoryProxyHandler} handler.
+ *
+ * @param interfaceNames The list of interfaces to implement and expose in
+ * the proxy
+ * @param delegatee The object to which to route all method calls
+ * @param usingBundle The bundle making use of the proxy
+ * @return The proxy to be used by client code or {@code null} if not all
+ * service interfaces can be loaded by the class loader of the
+ * {@code delegatee} object.
+ */
+ static Object createProxy(final String[] interfaceNames, final
AbstractSlingRepository delegatee,
+ final Bundle usingBundle) {
+
+ // get the interface classes to create the proxy
+ final ClassLoader cl = delegatee.getClass().getClassLoader();
+ final Class<?>[] interfaces = new Class<?>[interfaceNames.length];
+ for (int i = 0; i < interfaces.length; i++) {
+ try {
+ interfaces[i] = cl.loadClass(interfaceNames[i]);
+ } catch (ClassNotFoundException e) {
+
LoggerFactory.getLogger(SlingRepositoryProxyHandler.class).error(
+ "createProxy: Cannot load interface class " +
interfaceNames[i], e);
+ return null;
+ }
+ }
+
+ // create the proxy
+ final InvocationHandler handler = new
SlingRepositoryProxyHandler(delegatee, usingBundle);
+ return Proxy.newProxyInstance(cl, interfaces, handler);
+ }
+
+ private SlingRepositoryProxyHandler(final AbstractSlingRepository
delegatee, final Bundle usingBundle) {
+ this.delegatee = delegatee;
+ this.usingBundle = usingBundle;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
+ if (method == SlingRepositoryProxyHandler.LOGIN_SERVICE) {
+ return this.delegatee.loginService(this.usingBundle, (String)
args[0], (String) args[1]);
+ }
+
+ // otherwise forward to the AbstractSlingRepository implementation
+ return method.invoke(this.delegatee, args);
+ }
+}