001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.ecm.webengine.jaxrs.session.impl; 020 021import java.util.concurrent.locks.ReentrantLock; 022 023import javax.security.auth.login.LoginContext; 024import javax.security.auth.login.LoginException; 025import javax.servlet.http.HttpServletRequest; 026import javax.servlet.http.HttpSession; 027import javax.servlet.http.HttpSessionBindingEvent; 028import javax.servlet.http.HttpSessionBindingListener; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.ecm.core.api.CoreSession; 033import org.nuxeo.ecm.webengine.jaxrs.session.CoreSessionProvider; 034import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory; 035import org.nuxeo.ecm.webengine.jaxrs.session.SessionRef; 036import org.nuxeo.ecm.webengine.jaxrs.session.impl.PerSessionCoreProvider.Ref; 037import org.nuxeo.runtime.api.Framework; 038 039/** 040 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 041 */ 042public class PerSessionCoreProvider extends CoreSessionProvider<Ref> implements HttpSessionBindingListener { 043 044 private static final Log log = LogFactory.getLog(PerSessionCoreProvider.class); 045 046 public static class Ref implements SessionRef { 047 protected CoreSession session; 048 049 protected ReentrantLock lock; 050 051 public Ref(CoreSession session) { 052 this.session = session; 053 this.lock = new ReentrantLock(); 054 } 055 056 @Override 057 public CoreSession get() { 058 lock.lock(); 059 return session; 060 } 061 062 @Override 063 public void unget() { 064 // unlock only if the current thread holds the lock otherwise ignore. 065 try { 066 lock.unlock(); 067 } catch (IllegalMonitorStateException e) { 068 // do nothing 069 } 070 } 071 072 @Override 073 public void destroy() { 074 try { 075 session.close(); 076 } finally { 077 session = null; 078 lock = null; 079 } 080 } 081 082 } 083 084 public static synchronized void install(HttpServletRequest request) { 085 HttpSession s = request.getSession(true); 086 if (s.getAttribute(SessionFactory.SESSION_FACTORY_KEY) == null) { 087 s.setAttribute(SessionFactory.SESSION_FACTORY_KEY, new PerSessionCoreProvider()); 088 } 089 } 090 091 @Override 092 protected Ref createSessionRef(CoreSession session) { 093 return new Ref(session); 094 } 095 096 @Override 097 public void onRequestDone(HttpServletRequest request) { 098 // unlock sessions if any was locked 099 for (SessionRef ref : getSessions()) { 100 ref.unget(); 101 } 102 } 103 104 @Override 105 public void valueBound(HttpSessionBindingEvent event) { 106 // do nothing 107 } 108 109 @Override 110 public void valueUnbound(HttpSessionBindingEvent event) { 111 // destroy all sessions 112 if (!hasSessions()) { 113 destroy(); 114 return; 115 } 116 117 LoginContext lc = null; 118 try { 119 lc = Framework.login(); 120 destroy(); 121 } catch (LoginException e) { 122 log.error(e, e); 123 } finally { 124 if (lc != null) { 125 try { 126 lc.logout(); 127 } catch (LoginException e) { 128 log.error(e, e); 129 } 130 } 131 } 132 } 133 134 @Override 135 public synchronized SessionRef[] getSessions() { 136 return super.getSessions(); 137 } 138 139 @Override 140 public synchronized SessionRef getSessionRef(HttpServletRequest request, String repoName) { 141 return super.getSessionRef(request, repoName); 142 } 143 144 @Override 145 public synchronized boolean hasSessions() { 146 return super.hasSessions(); 147 } 148 149 @Override 150 protected synchronized void destroy() { 151 super.destroy(); 152 } 153 154}