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.CloseableCoreSession; 033import org.nuxeo.ecm.core.api.CoreSession; 034import org.nuxeo.ecm.webengine.jaxrs.session.CoreSessionProvider; 035import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory; 036import org.nuxeo.ecm.webengine.jaxrs.session.SessionRef; 037import org.nuxeo.ecm.webengine.jaxrs.session.impl.PerSessionCoreProvider.Ref; 038import org.nuxeo.runtime.api.Framework; 039 040/** 041 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 042 */ 043public class PerSessionCoreProvider extends CoreSessionProvider<Ref> implements HttpSessionBindingListener { 044 045 private static final Log log = LogFactory.getLog(PerSessionCoreProvider.class); 046 047 public static class Ref implements SessionRef { 048 protected CloseableCoreSession session; 049 050 protected ReentrantLock lock; 051 052 public Ref(CloseableCoreSession session) { 053 this.session = session; 054 this.lock = new ReentrantLock(); 055 } 056 057 @Override 058 public CoreSession get() { 059 lock.lock(); 060 return session; 061 } 062 063 @Override 064 public void unget() { 065 // unlock only if the current thread holds the lock otherwise ignore. 066 try { 067 lock.unlock(); 068 } catch (IllegalMonitorStateException e) { 069 // do nothing 070 } 071 } 072 073 @Override 074 public void destroy() { 075 try { 076 session.close(); 077 } finally { 078 session = null; 079 lock = null; 080 } 081 } 082 083 } 084 085 public static synchronized void install(HttpServletRequest request) { 086 HttpSession s = request.getSession(true); 087 if (s.getAttribute(SessionFactory.SESSION_FACTORY_KEY) == null) { 088 s.setAttribute(SessionFactory.SESSION_FACTORY_KEY, new PerSessionCoreProvider()); 089 } 090 } 091 092 @Override 093 protected Ref createSessionRef(CloseableCoreSession session) { 094 return new Ref(session); 095 } 096 097 @Override 098 public void onRequestDone(HttpServletRequest request) { 099 // unlock sessions if any was locked 100 for (SessionRef ref : getSessions()) { 101 ref.unget(); 102 } 103 } 104 105 @Override 106 public void valueBound(HttpSessionBindingEvent event) { 107 // do nothing 108 } 109 110 @Override 111 public void valueUnbound(HttpSessionBindingEvent event) { 112 // destroy all sessions 113 if (!hasSessions()) { 114 destroy(); 115 return; 116 } 117 118 LoginContext lc = null; 119 try { 120 lc = Framework.login(); 121 destroy(); 122 } catch (LoginException e) { 123 log.error(e, e); 124 } finally { 125 if (lc != null) { 126 try { 127 lc.logout(); 128 } catch (LoginException e) { 129 log.error(e, e); 130 } 131 } 132 } 133 } 134 135 @Override 136 public synchronized SessionRef[] getSessions() { 137 return super.getSessions(); 138 } 139 140 @Override 141 public synchronized SessionRef getSessionRef(HttpServletRequest request, String repoName) { 142 return super.getSessionRef(request, repoName); 143 } 144 145 @Override 146 public synchronized boolean hasSessions() { 147 return super.hasSessions(); 148 } 149 150 @Override 151 protected synchronized void destroy() { 152 super.destroy(); 153 } 154 155}