import java.util.Collections;
import java.util.List;
+import javax.jcr.LoginException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
+/** Proxy JCR sessions and attach them to calling threads. */
public class ThreadBoundJcrSessionFactory implements FactoryBean,
DisposableBean {
private final static Log log = LogFactory
.getLog(ThreadBoundJcrSessionFactory.class);
private Repository repository;
- private List<Session> activeSessions = Collections
+ private final List<Session> activeSessions = Collections
.synchronizedList(new ArrayList<Session>());
private ThreadLocal<Session> session = new ThreadLocal<Session>();
private boolean destroying = false;
private final Session proxiedSession;
+ /** If workspace is null, default will be used. */
+ private String workspace = null;
+
+ private String defaultUsername = "demo";
+ private String defaultPassword = "demo";
+ private Boolean forceDefaultCredentials = false;
public ThreadBoundJcrSessionFactory() {
Class<?>[] interfaces = { Session.class };
proxiedSession = (Session) Proxy.newProxyInstance(getClass()
- .getClassLoader(), interfaces, new InvocationHandler() {
-
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- Session threadSession = session.get();
- if (threadSession == null) {
- if ("logout".equals(method.getName()))// no need to login
- return Void.TYPE;
- threadSession = login();
- session.set(threadSession);
- }
-
- Object ret = method.invoke(threadSession, args);
- if ("logout".equals(method.getName())) {
- session.remove();
- if (!destroying)
- activeSessions.remove(threadSession);
- if (log.isTraceEnabled())
- log.trace("Logged out from JCR session "
- + threadSession + "; userId="
- + threadSession.getUserID());
- }
- return ret;
- }
- });
+ .getClassLoader(), interfaces,
+ new JcrSessionInvocationHandler());
}
+ /** Logs in to the repository using various strategies. */
protected Session login() {
- try {
- SimpleCredentials sc = new SimpleCredentials("demo", "demo"
- .toCharArray());
- Session sess = repository.login(sc);
- if (log.isTraceEnabled())
- log.trace("Log in to JCR session " + sess + "; userId="
- + sess.getUserID());
- // Thread.dumpStack();
- activeSessions.add(sess);
- return sess;
- } catch (RepositoryException e) {
- throw new ArgeoException("Cannot log in to repository", e);
- }
+ Session newSession = null;
+ // first try to login without credentials, assuming the underlying login
+ // module will have dealt with authentication (typically using Spring
+ // Security)
+ if (!forceDefaultCredentials)
+ try {
+ newSession = repository.login(workspace);
+ } catch (LoginException e1) {
+ log.warn("Cannot login without credentials: " + e1.getMessage());
+ // invalid credentials, go to the next step
+ } catch (RepositoryException e1) {
+ // other kind of exception, fail
+ throw new ArgeoException("Cannot log in to repository", e1);
+ }
+
+ // log using default username / password (useful for testing purposes)
+ if (newSession == null)
+ try {
+ SimpleCredentials sc = new SimpleCredentials(defaultUsername,
+ defaultPassword.toCharArray());
+ newSession = repository.login(sc, workspace);
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot log in to repository", e);
+ }
+
+ // Log and monitor new session
+ if (log.isTraceEnabled())
+ log.trace("Logged in to JCR session " + newSession + "; userId="
+ + newSession.getUserID());
+ activeSessions.add(newSession);
+ return newSession;
}
public Object getObject() {
this.repository = repository;
}
+ public void setDefaultUsername(String defaultUsername) {
+ this.defaultUsername = defaultUsername;
+ }
+
+ public void setDefaultPassword(String defaultPassword) {
+ this.defaultPassword = defaultPassword;
+ }
+
+ public void setForceDefaultCredentials(Boolean forceDefaultCredentials) {
+ this.forceDefaultCredentials = forceDefaultCredentials;
+ }
+
+ public void setWorkspace(String workspace) {
+ this.workspace = workspace;
+ }
+
+ protected class JcrSessionInvocationHandler implements InvocationHandler {
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ Session threadSession = session.get();
+ if (threadSession == null) {
+ if ("logout".equals(method.getName()))// no need to login
+ return Void.TYPE;
+ else if ("toString".equals(method.getName()))// maybe logging
+ return "Uninitialized Argeo thread bound JCR session";
+ threadSession = login();
+ session.set(threadSession);
+ }
+
+ Object ret = method.invoke(threadSession, args);
+ if ("logout".equals(method.getName())) {
+ session.remove();
+ if (!destroying)
+ activeSessions.remove(threadSession);
+ if (log.isTraceEnabled())
+ log.trace("Logged out from JCR session " + threadSession
+ + "; userId=" + threadSession.getUserID());
+ }
+ return ret;
+ }
+ }
}