]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org/argeo/jcr/ThreadBoundJcrSessionFactory.java
Prepare next development cycle
[lgpl/argeo-commons.git] / org / argeo / jcr / ThreadBoundJcrSessionFactory.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.jcr;
18
19 import java.lang.reflect.InvocationHandler;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Proxy;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25
26 import javax.jcr.Repository;
27 import javax.jcr.RepositoryException;
28 import javax.jcr.Session;
29 import javax.jcr.SimpleCredentials;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.argeo.ArgeoException;
34 import org.springframework.beans.factory.DisposableBean;
35 import org.springframework.beans.factory.FactoryBean;
36
37 /** Proxy JCR sessions and attach them to calling threads. */
38 public class ThreadBoundJcrSessionFactory implements FactoryBean,
39 DisposableBean {
40 private final static Log log = LogFactory
41 .getLog(ThreadBoundJcrSessionFactory.class);
42
43 private Repository repository;
44 private List<Session> activeSessions = Collections
45 .synchronizedList(new ArrayList<Session>());
46
47 private ThreadLocal<Session> session = new ThreadLocal<Session>();
48 private boolean destroying = false;
49 private final Session proxiedSession;
50
51 private String defaultUsername = "demo";
52 private String defaultPassword = "demo";
53
54 public ThreadBoundJcrSessionFactory() {
55 Class<?>[] interfaces = { Session.class };
56 proxiedSession = (Session) Proxy.newProxyInstance(getClass()
57 .getClassLoader(), interfaces, new InvocationHandler() {
58
59 public Object invoke(Object proxy, Method method, Object[] args)
60 throws Throwable {
61 Session threadSession = session.get();
62 if (threadSession == null) {
63 if ("logout".equals(method.getName()))// no need to login
64 return Void.TYPE;
65 threadSession = login();
66 session.set(threadSession);
67 }
68
69 Object ret = method.invoke(threadSession, args);
70 if ("logout".equals(method.getName())) {
71 session.remove();
72 if (!destroying)
73 activeSessions.remove(threadSession);
74 if (log.isTraceEnabled())
75 log.trace("Logged out from JCR session "
76 + threadSession + "; userId="
77 + threadSession.getUserID());
78 }
79 return ret;
80 }
81 });
82 }
83
84 protected Session login() {
85 try {
86 SimpleCredentials sc = new SimpleCredentials(defaultUsername,
87 defaultPassword.toCharArray());
88 Session sess = repository.login(sc);
89 if (log.isTraceEnabled())
90 log.trace("Log in to JCR session " + sess + "; userId="
91 + sess.getUserID());
92 // Thread.dumpStack();
93 activeSessions.add(sess);
94 return sess;
95 } catch (RepositoryException e) {
96 throw new ArgeoException("Cannot log in to repository", e);
97 }
98 }
99
100 public Object getObject() {
101 return proxiedSession;
102 }
103
104 public void destroy() throws Exception {
105 if (log.isDebugEnabled())
106 log.debug("Cleaning up " + activeSessions.size()
107 + " active JCR sessions...");
108
109 destroying = true;
110 for (Session sess : activeSessions) {
111 sess.logout();
112 }
113 activeSessions.clear();
114 }
115
116 public Class<? extends Session> getObjectType() {
117 return Session.class;
118 }
119
120 public boolean isSingleton() {
121 return true;
122 }
123
124 public void setRepository(Repository repository) {
125 this.repository = repository;
126 }
127
128 public void setDefaultUsername(String defaultUsername) {
129 this.defaultUsername = defaultUsername;
130 }
131
132 public void setDefaultPassword(String defaultPassword) {
133 this.defaultPassword = defaultPassword;
134 }
135
136 }