001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.webapps.session.components;
018:
019: import java.io.IOException;
020: import java.util.HashMap;
021: import java.util.Map;
022:
023: import org.apache.avalon.framework.activity.Disposable;
024: import org.apache.avalon.framework.component.Component;
025: import org.apache.avalon.framework.context.Context;
026: import org.apache.avalon.framework.context.ContextException;
027: import org.apache.avalon.framework.context.Contextualizable;
028: import org.apache.avalon.framework.logger.AbstractLogEnabled;
029: import org.apache.avalon.framework.service.ServiceException;
030: import org.apache.avalon.framework.service.ServiceManager;
031: import org.apache.avalon.framework.service.ServiceSelector;
032: import org.apache.avalon.framework.service.Serviceable;
033: import org.apache.avalon.framework.thread.ThreadSafe;
034: import org.apache.cocoon.ProcessingException;
035: import org.apache.cocoon.components.ContextHelper;
036: import org.apache.cocoon.environment.Request;
037: import org.apache.cocoon.environment.Session;
038: import org.apache.cocoon.util.Deprecation;
039: import org.apache.cocoon.webapps.session.ContextManager;
040: import org.apache.cocoon.webapps.session.context.SessionContext;
041: import org.apache.cocoon.webapps.session.context.SessionContextProvider;
042: import org.apache.cocoon.webapps.session.context.SimpleSessionContext;
043: import org.apache.excalibur.source.SourceResolver;
044: import org.apache.excalibur.xml.xpath.XPathProcessor;
045: import org.xml.sax.SAXException;
046:
047: /**
048: * Context manager
049: *
050: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
051: * @deprecated This block is deprecated and will be removed in future versions.
052: * @version CVS $Id: DefaultContextManager.java 433543 2006-08-22 06:22:54Z crossley $
053: */
054: public final class DefaultContextManager extends AbstractLogEnabled
055: implements Serviceable, ContextManager, ThreadSafe, Component,
056: Contextualizable, Disposable {
057:
058: /** The <code>ServiceManager</code> */
059: private ServiceManager manager;
060:
061: /** The context */
062: private Context context;
063:
064: /** selector for context provider */
065: private ServiceSelector contextSelector;
066:
067: /** The xpath processor */
068: private XPathProcessor xpathProcessor;
069:
070: /** The source resolver */
071: private SourceResolver resolver;
072:
073: /* The list of reserved contexts */
074: static private final String[] reservedContextNames = { "session",
075: "context" };
076:
077: /**
078: * Avalon Serviceable Interface
079: */
080: public void service(ServiceManager manager) throws ServiceException {
081: this .manager = manager;
082: this .contextSelector = (ServiceSelector) this .manager
083: .lookup(SessionContextProvider.ROLE + "Selector");
084: this .xpathProcessor = (XPathProcessor) this .manager
085: .lookup(XPathProcessor.ROLE);
086: this .resolver = (SourceResolver) this .manager
087: .lookup(SourceResolver.ROLE);
088: Deprecation.logger
089: .warn("The session-fw block is deprecated. Please use the provided alternatives instead.");
090: }
091:
092: /**
093: * Get the session
094: */
095: private Session getSession(boolean create) {
096: final Request request = ContextHelper.getRequest(this .context);
097: return request.getSession(create);
098: }
099:
100: /**
101: * Get the list of contexts
102: */
103: private Map getSessionContexts(Session session) {
104: Map contexts;
105: contexts = (Map) session.getAttribute(SessionContext.class
106: .getName());
107: if (contexts == null) {
108: contexts = new HashMap(5, 3);
109: session.setAttribute(SessionContext.class.getName(),
110: contexts);
111: }
112: return contexts;
113: }
114:
115: /**
116: * Checks if the context name is a reserved context.
117: */
118: private boolean isReservedContextName(String name) {
119: // synchronized (not needed)
120: int i, l;
121: boolean found;
122: found = false;
123: i = 0;
124: l = reservedContextNames.length;
125: while (i < l && found == false) {
126: found = reservedContextNames[i].equals(name);
127: i++;
128: }
129: if (!found) {
130: found = false;
131: SessionContextProvider provider = null;
132: try {
133: provider = (SessionContextProvider) this .contextSelector
134: .select(name);
135: found = true;
136: } catch (ServiceException ignore) {
137: } finally {
138: this .contextSelector.release(provider);
139: }
140: }
141: return found;
142: }
143:
144: /**
145: * Get a reserved context
146: */
147: private boolean existsReservedContext(String name)
148: throws ProcessingException {
149: // synchronized (not needed)
150: boolean exists = false;
151: SessionContextProvider provider = null;
152: try {
153: provider = (SessionContextProvider) this .contextSelector
154: .select(name);
155: exists = provider.existsSessionContext(name);
156: } catch (ServiceException ignore) {
157: } finally {
158: this .contextSelector.release(provider);
159: }
160:
161: return exists;
162: }
163:
164: /**
165: * Get a reserved context
166: */
167: private SessionContext getReservedContext(String name)
168: throws ProcessingException {
169: // synchronized
170: SessionContext context = null;
171: SessionContextProvider provider = null;
172: try {
173: provider = (SessionContextProvider) this .contextSelector
174: .select(name);
175: synchronized (provider) {
176: context = provider.getSessionContext(name);
177: }
178: } catch (ServiceException ignore) {
179: } finally {
180: this .contextSelector.release(provider);
181: }
182:
183: return context;
184: }
185:
186: /**
187: * Create a new public context in the session.
188: * Create a new public session context for this user. If this context
189: * already exists no new context is created and the old one will be used
190: * instead.
191: */
192: public SessionContext createContext(String name, String loadURI,
193: String saveURI) throws IOException, SAXException,
194: ProcessingException {
195: // synchronized
196: if (this .getLogger().isDebugEnabled()) {
197: this .getLogger().debug(
198: "BEGIN createContext name=" + name + "load="
199: + loadURI + "save=" + saveURI);
200: }
201: // test arguments
202: if (name == null) {
203: throw new ProcessingException(
204: "CreateContext: Name is required");
205: }
206: Session session = this .getSession(true);
207: if (session == null) {
208: throw new ProcessingException(
209: "CreateContext: Session is required");
210: }
211:
212: SessionContext context;
213: synchronized (session) {
214: // test for reserved context
215: if (this .isReservedContextName(name)) {
216: throw new ProcessingException(
217: "SessionContext with name "
218: + name
219: + " is reserved and cannot be created manually.");
220: }
221:
222: if (this .existsContext(name)) {
223: context = this .getContext(name);
224: } else {
225: Map contexts = this .getSessionContexts(session);
226: context = new SimpleSessionContext(this .xpathProcessor,
227: this .resolver);
228: context.setup(name, loadURI, saveURI);
229: contexts.put(name, context);
230: }
231: }
232:
233: if (this .getLogger().isDebugEnabled()) {
234: this .getLogger().debug(
235: "END createContext context=" + context);
236: }
237:
238: return context;
239: }
240:
241: /**
242: * Delete a public context in the session.
243: * If the context exists for this user, it and all of its information
244: * is deleted.
245: */
246: public void deleteContext(String name) throws ProcessingException {
247: // synchronized
248: if (this .getLogger().isDebugEnabled()) {
249: this .getLogger().debug("BEGIN deleteContext name=" + name);
250: }
251:
252: // test arguments
253: if (name == null) {
254: throw new ProcessingException(
255: "SessionManager.deleteContext: Name is required");
256: }
257: if (this .isReservedContextName(name)) {
258: throw new ProcessingException("SessionContext with name "
259: + name
260: + " is reserved and cannot be deleted manually.");
261: }
262: Session session = this .getSession(false);
263: if (session == null) {
264: throw new ProcessingException(
265: "SessionManager.deleteContext: Session is required");
266: }
267:
268: synchronized (session) {
269: final Map contexts = this .getSessionContexts(session);
270: if (contexts.containsKey(name)) {
271: contexts.remove(name);
272: }
273: }
274:
275: if (this .getLogger().isDebugEnabled()) {
276: this .getLogger().debug("END deleteContext");
277: }
278: }
279:
280: /**
281: * Get a public context.
282: * The session context with the given name is returned. If the context does
283: * not exist <CODE>null</CODE> is returned.
284: */
285: public SessionContext getContext(String name)
286: throws ProcessingException {
287: // synchronized
288: if (this .getLogger().isDebugEnabled()) {
289: this .getLogger().debug("BEGIN getContext name=" + name);
290: }
291:
292: SessionContext context;
293: if (this .isReservedContextName(name)) {
294: context = this .getReservedContext(name);
295: } else {
296: Session session = this .getSession(false);
297: if (session != null) {
298: synchronized (session) {
299: final Map contexts = this
300: .getSessionContexts(session);
301: context = (SessionContext) contexts.get(name);
302: }
303: } else {
304: context = null;
305: }
306: }
307:
308: if (this .getLogger().isDebugEnabled()) {
309: this .getLogger().debug("END getContext context=" + context);
310: }
311:
312: return context;
313: }
314:
315: /**
316: * Check if a context exists
317: */
318: public boolean hasSessionContext() throws ProcessingException {
319: Session session = this .getSession(false);
320: if (session == null) {
321: throw new ProcessingException(
322: "SessionManager.hasSessionContext: Session is required.");
323: }
324: synchronized (session) {
325: final Map contexts = this .getSessionContexts(session);
326: return !(contexts.isEmpty());
327: }
328: }
329:
330: /**
331: * Check if a public context exists.
332: * If the session context with the given name exists, <CODE>true</CODE> is
333: * returned.
334: */
335: public boolean existsContext(String name)
336: throws ProcessingException {
337: Session session = this .getSession(false);
338: if (session == null) {
339: throw new ProcessingException(
340: "SessionManager.existsContext: Session is required.");
341: }
342: synchronized (session) {
343: final Map contexts = this .getSessionContexts(session);
344: boolean result = contexts.containsKey(name);
345: if (!result && this .isReservedContextName(name)) {
346: result = this .existsReservedContext(name);
347: }
348: return result;
349: }
350: }
351:
352: /* (non-Javadoc)
353: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
354: */
355: public void contextualize(Context context) throws ContextException {
356: this .context = context;
357: }
358:
359: /* (non-Javadoc)
360: * @see org.apache.avalon.framework.activity.Disposable#dispose()
361: */
362: public void dispose() {
363: if (this.manager != null) {
364: this.manager.release(this.contextSelector);
365: this.manager.release(this.xpathProcessor);
366: this.manager.release(this.resolver);
367: this.contextSelector = null;
368: this.xpathProcessor = null;
369: this.resolver = null;
370: this.manager = null;
371: }
372: }
373:
374: }
|