blob: 081473a63734c2f4bceacc87efcb6516d91387c2 [file] [log] [blame]
/*
* 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.registration.impl;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Properties;
import javax.jcr.Repository;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Property;
import org.apache.sling.jcr.registration.AbstractRegistrationSupport;
import org.osgi.service.log.LogService;
/**
* The <code>JndiRegistrationSupport</code> extends the
* {@link AbstractRegistrationSupport} class to register repositories with a
* JNDI context whose provider URL and initial factory class name may be
* configured.
* <p>
* Note: Currently, only these two properties are declared to be configurable,
* in the future a mechanism should be devised to support declaration of more
* properties.
*/
@Component(
immediate = true,
metatype = true,
label = "%jndi.name",
description = "%jndi.description",
name = "org.apache.sling.jcr.jackrabbit.server.JndiRegistrationSupport",
policy = ConfigurationPolicy.REQUIRE
)
@org.apache.felix.scr.annotations.Properties({
@Property(
name = "java.naming.factory.initial",
value = "org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory",
label = "%jndi.factory.name",
description = "%jndi.factory.description"),
@Property(
name = "java.naming.provider.url",
value = "http://sling.apache.org",
label = "%jndi.providerurl.name",
description = "%jndi.providerurl.description"),
@Property(name = "service.vendor", value = "The Apache Software Foundation", propertyPrivate = true),
@Property(name = "service.description", value = "JNDI Repository Registration", propertyPrivate = true)
})
public class JndiRegistrationSupport extends AbstractRegistrationSupport {
private Context jndiContext;
// ---------- SCR intergration ---------------------------------------------
protected boolean doActivate() {
@SuppressWarnings("unchecked")
Dictionary<String, Object> props = this.getComponentContext().getProperties();
Properties env = new Properties();
for (Enumeration<String> pe = props.keys(); pe.hasMoreElements();) {
String key = pe.nextElement();
if (key.startsWith("java.naming.")) {
env.setProperty(key, (String) props.get(key));
}
}
try {
// create the JNDI context for registration
this.jndiContext = this.createInitialContext(env);
this.log(LogService.LOG_INFO, "Using JNDI context "
+ this.jndiContext.getEnvironment() + " to register repositories",
null);
return true;
} catch (NamingException ne) {
this.log(
LogService.LOG_ERROR,
"Problem setting up JNDI initial context, repositories will not be registered. Reason: "
+ ne.getMessage(), null);
}
// fallback to false
return false;
}
protected void doDeactivate() {
if (this.jndiContext != null) {
try {
this.jndiContext.close();
} catch (NamingException ne) {
this.log(LogService.LOG_INFO, "Problem closing JNDI context", ne);
}
this.jndiContext = null;
}
}
private Context createInitialContext(final Properties env) throws NamingException {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<Context>() {
public Context run() throws NamingException {
Thread currentThread = Thread.currentThread();
ClassLoader old = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(JndiRegistrationSupport.this.getClass().getClassLoader());
try {
return new InitialContext(env);
} finally {
currentThread.setContextClassLoader(old);
}
}
});
} catch (PrivilegedActionException pae) {
// we now that this method only throws a NamingException
throw (NamingException) pae.getCause();
}
}
protected Object bindRepository(String name, Repository repository) {
if (this.jndiContext != null) {
try {
this.jndiContext.bind(name, repository);
this.log(LogService.LOG_INFO, "Repository bound to JNDI as " + name,
null);
return repository;
} catch (NamingException ne) {
this.log(LogService.LOG_ERROR, "Failed to register repository " + name, ne);
}
}
// fall back to unregistered in case of failures or no context
return null;
}
protected void unbindRepository(String name, Object data) {
if (this.jndiContext != null) {
try {
this.jndiContext.unbind(name);
this.log(LogService.LOG_INFO, "Repository " + name
+ " unbound from JNDI", null);
} catch (NamingException ne) {
this.log(LogService.LOG_ERROR, "Problem unregistering repository "
+ name, ne);
}
}
}
}