001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package de.schlund.pfixxml;
020:
021: import java.util.Collections;
022: import java.util.HashMap;
023: import java.util.HashSet;
024: import java.util.Map;
025: import java.util.Set;
026:
027: import javax.servlet.http.HttpSession;
028: import javax.servlet.http.HttpSessionBindingEvent;
029: import javax.servlet.http.HttpSessionBindingListener;
030:
031: import de.schlund.pfixcore.workflow.ContextImpl;
032:
033: /**
034: * Stores context instances within a session. The ContextXMLServlet uses this
035: * class to store a context instance within a session. All servlets use this
036: * class to get existing instances.
037: *
038: * @author Sebastian Marsching <sebastian.marsching@1und1.de>
039: */
040: public class SessionContextStore implements HttpSessionBindingListener {
041: private final static String SESSION_ATTRIBUTE = "__PFX_CONTEXTSTORE__";
042:
043: private Map<String, ContextImpl> servletMap = Collections
044: .synchronizedMap(new HashMap<String, ContextImpl>());
045: private Map<String, ContextImpl> nameMap = Collections
046: .synchronizedMap(new HashMap<String, ContextImpl>());
047: private Map<String, ContextImpl> pathMap = Collections
048: .synchronizedMap(new HashMap<String, ContextImpl>());
049:
050: private SessionContextStore() {
051: // Intentionally empty
052: }
053:
054: /**
055: * Provides store instance associated with a session. If no store is
056: * available for the session a new one will be created.
057: *
058: * @param session HTTP session
059: * @return store instance stored in the specified session
060: */
061: public static SessionContextStore getInstance(HttpSession session) {
062: SessionContextStore instance = (SessionContextStore) session
063: .getAttribute(SESSION_ATTRIBUTE);
064: if (instance == null) {
065: synchronized (session) {
066: instance = (SessionContextStore) session
067: .getAttribute(SESSION_ATTRIBUTE);
068: if (instance == null) {
069: instance = new SessionContextStore();
070: session.setAttribute(SESSION_ATTRIBUTE, instance);
071: }
072: }
073: }
074: return instance;
075: }
076:
077: /**
078: * Stores a context instance.
079: *
080: * @param servlet servlet the context instance is associated to
081: * @param preq current servlet request
082: * @param name name of the servlet (if configured)
083: * @param context the context instance to store
084: */
085: public void storeContext(ContextXMLServlet servlet,
086: PfixServletRequest preq, String name, ContextImpl context) {
087: // We use the servlet name provided by the container. This might
088: // cause problems for "unregistered" servlets, however a Pustefix
089: // environment only uses servlets with well-defined names in the
090: // webapplication deployment descriptor.
091: this .servletMap.put(servlet.getServletName(), context);
092: if (name != null) {
093: this .nameMap.put(name, context);
094: }
095: this .pathMap.put(preq.getRequest().getServletPath(), context);
096: }
097:
098: /**
099: * Returns context instance associated with a servlet
100: *
101: * @param servlet servlet for which context instance is to be returned
102: * @param preq current servlet request
103: * @return context instance or <code>null</code> if no context instance is
104: * stored for the supplied parameters
105: */
106: public ContextImpl getContext(ContextXMLServlet servlet,
107: PfixServletRequest preq) {
108: ContextImpl context = servletMap.get(servlet.getServletName());
109: if (context != null) {
110: this .pathMap.put(preq.getRequest().getServletPath(),
111: context);
112: }
113: return context;
114: }
115:
116: /**
117: * Returns the context instance for the servlet identified by the supplied
118: * identifier. The identifier can be the path (starting with a '/') of
119: * the ContextXMLServlet, the name manually specified in its configuration
120: * or the name provided by the webapplication deployment descriptor. The
121: * method will try to guess the type of identifier.
122: *
123: * @param identifier string identifying the origin servlet
124: * @return context instance or <code>null</code> if no matching instance ca
125: * be found
126: */
127: public ContextImpl getContext(String identifier) {
128: if (identifier.startsWith("/")) {
129: return this .pathMap.get(identifier);
130: } else {
131: ContextImpl instance = this .nameMap.get(identifier);
132: if (instance == null) {
133: instance = this .servletMap.get(identifier);
134: }
135: return instance;
136: }
137: }
138:
139: public Set<String> getServletNames() {
140: return Collections.unmodifiableSet(servletMap.keySet());
141: }
142:
143: public void valueBound(HttpSessionBindingEvent ev) {
144: HashSet<ContextImpl> contexts = getAllContexts();
145: for (ContextImpl context : contexts) {
146: if (context instanceof HttpSessionBindingListener) {
147: HttpSessionBindingListener l = (HttpSessionBindingListener) context;
148: l.valueBound(ev);
149: }
150: }
151: }
152:
153: public void valueUnbound(HttpSessionBindingEvent ev) {
154: HashSet<ContextImpl> contexts = getAllContexts();
155: for (ContextImpl context : contexts) {
156: if (context instanceof HttpSessionBindingListener) {
157: HttpSessionBindingListener l = (HttpSessionBindingListener) context;
158: l.valueUnbound(ev);
159: }
160: }
161: }
162:
163: private HashSet<ContextImpl> getAllContexts() {
164: HashSet<ContextImpl> contexts = new HashSet<ContextImpl>();
165: contexts.addAll(servletMap.values());
166: contexts.addAll(nameMap.values());
167: contexts.addAll(pathMap.values());
168: return contexts;
169: }
170:
171: }
|