]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java
Improve JCR
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jcr / src / main / java / org / argeo / jcr / ThreadBoundJcrSessionFactory.java
index f26a255abebc7fdcfee7c3f0e78213b816034b8d..aaafdc26a704f2781c11164c07aec708a3a00769 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.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.argeo.jcr;
 
 import java.lang.reflect.InvocationHandler;
@@ -7,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import javax.jcr.LoginException;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -18,63 +35,66 @@ import org.argeo.ArgeoException;
 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() {
@@ -105,4 +125,46 @@ public class ThreadBoundJcrSessionFactory implements FactoryBean,
                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;
+               }
+       }
 }