Hello to everyone ^__^
Since I need to put all the repository credentials (username, password,
workspace) outside my application, I managed to write a simple jndi
session factory. It is basically similar to the ClientRepositoryFactory
but, instead of returning a Repository instance during lookups, will
return an already authenticated Session.
This approach is, imho, more similar to the way that databases configure
their connections : usually jndi factories return a
javax.sql.Datasource which is to me more similar to the Session than to
the Repository
I write it here just in case it could be of any help to anyone, please
let me know if there is any conceptual mistake or risk with this
approach (thanks in advance for that :-)
Luca
Here is a sample client code (you can notice that lookup returns a
javax.jcr.Session) :
InitialContext context = new InitialContext();
Context environment = (Context) context.lookup("java:comp/env");
session = (javax.jcr.Session)
environment.lookup("jcr/CentralRepository");
Here is a snippet for a Tomcat context.xml (such as in
http://jackrabbit.apache.org/doc/deploy/howto-model3.html , you can
notice the additional parameters (username, password and workspace), the
factory returned type (Session, not Repositories) and the factory class
(you can find the code below in this email)) :
<Resource name="jcr/CentralRepository" auth="Container"
type="javax.jcr.Session"
factory="org.apache.jackrabbit.rmi.client.JackrabbitAuthSessionFactory"
username="johndoe"
password="cat75"
workspace="mainws"
url="//host:1099/jackrabbit"/>
Here is the usual resource-ref for web.xml (obviously res-type changes):
<resource-ref>
<description>Session to the Central Repository</description>
<res-ref-name>jcr/CentralRepository</res-ref-name>
<res-type>javax.jcr.Session</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Here is the factory code :
package org.apache.jackrabbit.rmi.client;
import java.util.Hashtable;
import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import org.apache.jackrabbit.rmi.client.ClientRepositoryFactory;
public class JackrabbitAuthSessionFactory implements ObjectFactory {
private static final String WORKSPACE_PARAMETER = "workspace";
private static final String PASSWORD_PARAMETER = "password";
private static final String USERNAME_PARAMETER = "username";
private Repository repository;
public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Hashtable<?, ?> environment) throws Exception {
if (this.repository == null) {
createRepository(obj, name, nameCtx, environment);
}
Session session = createSession(obj);
return session;
}
private Session createSession(Object obj) throws LoginException,
NoSuchWorkspaceException, RepositoryException {
Session session = null;
if (obj instanceof Reference) {
Reference reference = (Reference) obj;
if (Session.class.getName().equals(reference.getClassName())) {
String username = (String)
reference.get(USERNAME_PARAMETER).getContent();
String password = (String)
reference.get(PASSWORD_PARAMETER).getContent();
String workspace = (String)
reference.get(WORKSPACE_PARAMETER).getContent();
Credentials credentials = new SimpleCredentials(username,
password.toCharArray());
session = this.repository.login(credentials, workspace);
}
}
return session;
}
private void createRepository(Object obj, Name name, Context nameCtx,
Hashtable<?, ?> environment) {
ClientRepositoryFactory repositoryFactory = new
ClientRepositoryFactory();
Object objectInstance = repositoryFactory.getObjectInstance(obj,
name,
nameCtx, environment);
this.repository = (Repository) objectInstance;
}
}