org.modeshape.jdbc.delegate.LocalRepositoryDelegate Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of modeshape-jdbc-local
Show all versions of modeshape-jdbc-local
JDBC driver to allow clients to use JCR-SQL2 to query a ModeShape JCR repository within the same JVM process.
/*
* ModeShape (http://www.modeshape.org)
*
* Licensed 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.modeshape.jdbc.delegate;
import java.sql.Connection;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import javax.jcr.LoginException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Workspace;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.modeshape.jcr.api.Repositories;
import org.modeshape.jdbc.JdbcLocalI18n;
import org.modeshape.jdbc.LocalJcrDriver;
import org.modeshape.jdbc.LocalJcrDriver.JcrContextFactory;
/**
* The LocalRepositoryDelegate provides a local Repository implementation to access the Jcr layer via JNDI Lookup.
*/
public class LocalRepositoryDelegate extends AbstractRepositoryDelegate {
public static final RepositoryDelegateFactory FACTORY = new RepositoryDelegateFactory() {};
private static final String JNDI_EXAMPLE_URL = LocalJcrDriver.JNDI_URL_PREFIX + "{jndiName}";
protected static final Set TRANSACTION_IDS = java.util.Collections.synchronizedSet(new HashSet());
private JcrContextFactory jcrContext = null;
private Repository repository = null;
public LocalRepositoryDelegate( String url,
Properties info,
JcrContextFactory contextFactory ) {
super(url, info);
if (contextFactory == null) {
jcrContext = new JcrContextFactory() {
@Override
public Context createContext( Properties properties ) throws NamingException {
return ((properties == null || properties.isEmpty()) ? new InitialContext() : new InitialContext(properties));
}
};
} else {
this.jcrContext = contextFactory;
}
}
@Override
protected ConnectionInfo createConnectionInfo( String url,
Properties info ) {
return new JNDIConnectionInfo(url, info);
}
protected JcrContextFactory getJcrContext() {
return jcrContext;
}
private LocalSession getLocalSession() throws LoginException, NoSuchWorkspaceException, RepositoryException {
return LocalSession.getLocalSessionInstance().getLocalSession(repository, getConnectionInfo());
}
private LocalSession getCurrentLocalSession() {
return LocalSession.getLocalSessionInstance().getLocalSession();
}
@Override
public String getDescriptor( String descriptorKey ) {
return repository.getDescriptor(descriptorKey);
}
@Override
public NodeType nodeType( String name ) throws RepositoryException {
LocalSession localSession = getLocalSession();
return localSession.getSession().getWorkspace().getNodeTypeManager().getNodeType(name);
}
@Override
public List nodeTypes() throws RepositoryException {
LocalSession localSession = getLocalSession();
List types = new ArrayList();
NodeTypeIterator its = localSession.getSession().getWorkspace().getNodeTypeManager().getAllNodeTypes();
while (its.hasNext()) {
types.add((NodeType)its.next());
}
return types;
}
/**
* This execute method is used for redirection so that the JNDI implementation can control calling execute.
*
* @see java.sql.Statement#execute(java.lang.String)
*/
@Override
public QueryResult execute( String query,
String language ) throws RepositoryException {
logger.trace("Executing query: {0}", query);
// Create the query ...
final Query jcrQuery = getLocalSession().getSession().getWorkspace().getQueryManager().createQuery(query, language);
return jcrQuery.execute();
}
@Override
public String explain( String query,
String language ) throws RepositoryException {
logger.trace("Explaining query: {0}", query);
// Create the query ...
final org.modeshape.jcr.api.query.Query jcrQuery = (org.modeshape.jcr.api.query.Query)getLocalSession().getSession().getWorkspace().getQueryManager().createQuery(query,
language);
return jcrQuery.explain().getPlan();
}
@Override
protected void initRepository() throws SQLException {
if (repository != null) {
return;
}
logger.debug("Creating repository for LocalRepositoryDelegate");
Set repositoryNames = null;
ConnectionInfo connInfo = this.getConnectionInfo();
assert connInfo != null;
// Look up the object in JNDI and find the JCR Repository object ...
String jndiName = connInfo.getRepositoryPath();
if (jndiName == null) {
String msg = JdbcLocalI18n.urlMustContainJndiNameOfRepositoryOrRepositoriesObject.text();
throw new SQLException(msg);
}
Context context = null;
try {
context = this.jcrContext.createContext(connInfo.getProperties());
} catch (NamingException e) {
throw new SQLException(JdbcLocalI18n.unableToGetJndiContext.text(e.getLocalizedMessage()));
}
if (context == null) {
throw new SQLException(JdbcLocalI18n.unableToFindObjectInJndi.text(jndiName));
}
String repositoryName = "NotAssigned";
try {
Object target = context.lookup(jndiName);
repositoryName = connInfo.getRepositoryName();
if (target instanceof Repositories) {
logger.trace("JNDI Lookup found Repositories ");
Repositories repositories = (Repositories)target;
if (repositoryName == null) {
repositoryNames = repositories.getRepositoryNames();
if (repositoryNames == null || repositoryNames.isEmpty()) {
throw new SQLException(JdbcLocalI18n.noRepositoryNamesFound.text());
}
if (repositoryNames.size() == 1) {
repositoryName = repositoryNames.iterator().next();
connInfo.setRepositoryName(repositoryName);
logger.trace("Setting Repository {0} as default", repositoryName);
} else {
throw new SQLException(JdbcLocalI18n.objectInJndiIsRepositories.text(jndiName));
}
}
try {
repository = repositories.getRepository(repositoryName);
} catch (RepositoryException e) {
throw new SQLException(JdbcLocalI18n.unableToFindNamedRepository.text(jndiName, repositoryName));
}
} else if (target instanceof Repository) {
logger.trace("JNDI Lookup found a Repository");
repository = (Repository)target;
repositoryNames = new HashSet(1);
if (repositoryName == null) {
repositoryName = ("DefaultRepository");
connInfo.setRepositoryName(repositoryName);
}
repositoryNames.add(repositoryName);
} else {
throw new SQLException(JdbcLocalI18n.objectInJndiMustBeRepositoryOrRepositories.text(jndiName));
}
assert repository != null;
} catch (NamingException e) {
throw new SQLException(JdbcLocalI18n.unableToFindObjectInJndi.text(jndiName), e);
}
this.setRepositoryName(repositoryName);
this.setRepositoryNames(repositoryNames);
}
@Override
public boolean isValid( final int timeout ) throws RepositoryException {
LocalSession ls = getLocalSession();
if (!ls.getSession().isLive()) {
ls.remove();
return false;
}
return true;
}
@Override
public void closeStatement() {
LocalSession session = getCurrentLocalSession();
try {
if (session != null) {
session.remove();
}
} catch (Exception e) {
// do nothing
}
}
@Override
public void close() {
for (LocalSession id : TRANSACTION_IDS) {
id.remove();
}
this.repository = null;
}
@SuppressWarnings( "unused" )
@Override
public void rollback() throws RepositoryException {
closeStatement();
}
@Override
public T unwrap( Class iface ) throws SQLException {
try {
if (iface.isInstance(this)) {
return iface.cast(this);
}
if (iface.isInstance(Workspace.class)) {
Workspace workspace = getLocalSession().getSession().getWorkspace();
return iface.cast(workspace);
}
} catch (RepositoryException re) {
throw new SQLException(re.getLocalizedMessage());
}
throw new SQLException(JdbcLocalI18n.classDoesNotImplementInterface.text(Connection.class.getSimpleName(),
iface.getName()));
}
class JNDIConnectionInfo extends ConnectionInfo {
protected JNDIConnectionInfo( String url,
Properties properties ) {
super(url, properties);
}
@Override
public String getUrlExample() {
return JNDI_EXAMPLE_URL;
}
@Override
public String getUrlPrefix() {
return LocalJcrDriver.JNDI_URL_PREFIX;
}
@Override
protected void addRepositoryNamePropertyInfo( List results ) {
boolean no_errors = results.size() == 0;
boolean nameRequired = false;
if (getRepositoryName() == null) {
boolean found = false;
if (no_errors) {
try {
Context context = getJcrContext().createContext(getProperties());
Object obj = context.lookup(getRepositoryPath());
if (obj instanceof Repositories) {
nameRequired = true;
found = true;
} else if (obj instanceof Repository) {
found = true;
}
} catch (NamingException e) {
// do nothing about it ...
}
}
if (nameRequired || !found) {
DriverPropertyInfo info = new DriverPropertyInfo(JdbcLocalI18n.repositoryNamePropertyName.text(), null);
info.description = JdbcLocalI18n.repositoryNamePropertyDescription.text();
info.required = nameRequired;
info.choices = null;
results.add(info);
}
}
}
}
}