/*
* (C) Copyright 2009 Nuxeo SA (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Contributors:
* Florent Guillaume
*/
package org.nuxeo.runtime.datasource;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.common.jndi.NamingContext;
import org.nuxeo.common.jndi.NamingContextFactory;
import org.nuxeo.runtime.api.DataSourceHelper;
import org.nuxeo.runtime.model.ComponentContext;
import org.nuxeo.runtime.model.ComponentInstance;
import org.nuxeo.runtime.model.DefaultComponent;
/**
* Nuxeo component allowing the JNDI registration of datasources by extension
* point contributions.
* <p>
* For now only the internal Nuxeo JNDI server is supported.
*/
public class DataSourceComponent extends DefaultComponent {
private static final Log log = LogFactory.getLog(DataSourceComponent.class);
public static final String DATASOURCES_XP = "datasources";
public static final String ENV_CTX_NAME = "java:comp/env";
protected Context envCtx;
@Override
public void activate(ComponentContext context) throws Exception {
Context ctx = DataSourceHelper.getDefaultInitCtx();
if (ctx != null && !(ctx instanceof NamingContext)) {
throw new RuntimeException(String.format(
"A JNDI server already exists (%s), "
+ "nuxeo-runtime-datasource cannot be deployed",
ctx.getClass().getName()));
}
NamingContextFactory.setAsInitial();
ctx = new InitialContext();
Name name = new CompositeName(ENV_CTX_NAME);
for (int i = 0; i < name.size(); i++) {
try {
ctx = (Context) ctx.lookup(name.get(i));
} catch (NamingException e) {
ctx = ctx.createSubcontext(name.get(i));
}
}
envCtx = ctx;
}
@Override
public void deactivate(ComponentContext context) throws Exception {
NamingContextFactory.revertSetAsInitial();
}
@Override
public void registerContribution(Object contrib, String extensionPoint,
ComponentInstance component) throws Exception {
if (DATASOURCES_XP.equals(extensionPoint)) {
if (contrib instanceof DataSourceDescriptor) {
addDataSource((DataSourceDescriptor) contrib);
} else {
log.error("Invalid datasource contribution: "
+ contrib.getClass().getName());
}
} else {
log.error("Ignoring unknown extension point: " + extensionPoint);
}
}
@Override
public void unregisterContribution(Object contrib, String extensionPoint,
ComponentInstance component) throws Exception {
if (DATASOURCES_XP.equals(extensionPoint)) {
if (contrib instanceof DataSourceDescriptor) {
removeDataSource((DataSourceDescriptor) contrib);
} else {
log.error("Invalid datasource contribution: "
+ contrib.getClass().getName());
}
} else {
log.error("Ignoring unknown extension point: " + extensionPoint);
}
}
protected void addDataSource(DataSourceDescriptor descr) {
log.info("Registering datasource: " + descr.name);
try {
Name name = new CompositeName(descr.name);
Context ctx = envCtx;
// bind intermediate names as subcontexts (jdbc/foo)
for (int i = 0; i < name.size() - 1; i++) {
try {
ctx = (Context) ctx.lookup(name.get(i));
} catch (NamingException e) {
ctx = ctx.createSubcontext(name.get(i));
}
}
ctx.bind(name.get(name.size() - 1), descr.getReference());
} catch (NamingException e) {
log.error("Cannot bind datasource '" + descr.name + "' in JNDI", e);
}
}
protected void removeDataSource(DataSourceDescriptor descr) {
log.info("Unregistering datasource: " + descr.name);
try {
envCtx.unbind(descr.name);
} catch (NamingException e) {
log.error("Cannot unbind datasource '" + descr.name + "' in JNDI",
e);
}
}
}