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.Map;
024:
025: import javax.servlet.ServletContext;
026:
027: import de.schlund.pfixcore.workflow.context.ServerContextImpl;
028:
029: /**
030: * Stores context instances within a servlet context. The ContextXMLServlet uses
031: * this class to store a context instance within the servlet context. All
032: * servlets use this class to get existing instances.
033: *
034: * @author Sebastian Marsching <sebastian.marsching@1und1.de>
035: */
036: public class ServerContextStore {
037: private final static String SERVLETCONTEXT_ATTRIBUTE = "__PFX_CONTEXTSTORE__";
038:
039: private Map<String, ServerContextImpl> servletMap = Collections
040: .synchronizedMap(new HashMap<String, ServerContextImpl>());
041: private Map<String, ServerContextImpl> nameMap = Collections
042: .synchronizedMap(new HashMap<String, ServerContextImpl>());
043: private Map<String, ServerContextImpl> pathMap = Collections
044: .synchronizedMap(new HashMap<String, ServerContextImpl>());
045:
046: private ServerContextStore() {
047: // Intentionally empty
048: }
049:
050: /**
051: * Provides store instance associated with a servlet context. If no store is
052: * available for the servlet context a new one will be created.
053: *
054: * @param servletContext servlet context
055: * @return store instance stored in the specified servlet context
056: */
057: public static ServerContextStore getInstance(
058: ServletContext servletContext) {
059: ServerContextStore instance = (ServerContextStore) servletContext
060: .getAttribute(SERVLETCONTEXT_ATTRIBUTE);
061: if (instance == null) {
062: synchronized (servletContext) {
063: instance = (ServerContextStore) servletContext
064: .getAttribute(SERVLETCONTEXT_ATTRIBUTE);
065: if (instance == null) {
066: instance = new ServerContextStore();
067: servletContext.setAttribute(
068: SERVLETCONTEXT_ATTRIBUTE, instance);
069: }
070: }
071: }
072: return instance;
073: }
074:
075: /**
076: * Stores a context instance.
077: *
078: * @param servlet servlet the context instance is associated to
079: * @param preq current servlet request
080: * @param name name of the servlet (if configured)
081: * @param context the context instance to store
082: */
083: public void storeContext(ContextXMLServlet servlet,
084: PfixServletRequest preq, String name,
085: ServerContextImpl context) {
086: // We use the servlet name provided by the container. This might
087: // cause problems for "unregistered" servlets, however a Pustefix
088: // environment only uses servlets with well-defined names in the
089: // webapplication deployment descriptor.
090: ServerContextImpl oldContext = this .servletMap.get(servlet
091: .getServletName());
092: this .servletMap.put(servlet.getServletName(), context);
093: if (name != null) {
094: synchronized (this .nameMap) {
095: this .nameMap.put(name, context);
096: // Delete entries for old names
097: for (String key : this .nameMap.keySet()) {
098: if (this .nameMap.get(key) == oldContext) {
099: this .nameMap.remove(key);
100: }
101: }
102: }
103: }
104: synchronized (this .pathMap) {
105: String path = preq.getRequest().getServletPath();
106: this .pathMap.put(path, context);
107: // Update entries for old paths
108: for (String key : this .pathMap.keySet()) {
109: if (this .pathMap.get(key) == oldContext) {
110: this .pathMap.put(key, context);
111: }
112: }
113: }
114: }
115:
116: /**
117: * Returns context instance associated with a servlet
118: *
119: * @param servlet servlet for which context instance is to be returned
120: * @param preq current servlet request
121: * @return context instance or <code>null</code> if no context instance is
122: * stored for the supplied parameters
123: */
124: public ServerContextImpl getContext(ContextXMLServlet servlet,
125: PfixServletRequest preq) {
126: ServerContextImpl context = servletMap.get(servlet
127: .getServletName());
128: if (context != null) {
129: synchronized (this .pathMap) {
130: this .pathMap.put(preq.getRequest().getServletPath(),
131: context);
132: }
133: }
134: return context;
135: }
136:
137: /**
138: * Returns the context instance for the servlet identified by the supplied
139: * identifier. The identifier can be the path (starting with a '/') of
140: * the ContextXMLServlet, the name manually specified in its configuration
141: * or the name provided by the webapplication deployment descriptor. The
142: * method will try to guess the type of identifier.
143: *
144: * @param identifier string identifying the origin servlet
145: * @return context instance or <code>null</code> if no matching instance ca
146: * be found
147: */
148: public ServerContextImpl getContext(String identifier) {
149: if (identifier.startsWith("/")) {
150: return this .pathMap.get(identifier);
151: } else {
152: ServerContextImpl instance = this.nameMap.get(identifier);
153: if (instance == null) {
154: instance = this.servletMap.get(identifier);
155: }
156: return instance;
157: }
158: }
159: }
|