001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.jaxws.handler;
020:
021: import org.apache.axis2.jaxws.core.MessageContext;
022: import org.apache.axis2.jaxws.description.EndpointDescription;
023: import org.apache.axis2.jaxws.message.Message;
024:
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.Map;
029: import java.util.Set;
030:
031: /**
032: * The <tt>MEPContext</tt> is the version of the MessageContext
033: * that will be given to application handlers as the handler list
034: * is traversed. It is only to be used by application handlers.
035: *
036: * The MEPContext object is constructed using a non-null request
037: * context. Once the request has been fully processed in the JAX-WS engine,
038: * the response context should be set on this. Since the response context
039: * is always last, it takes priority in all MEPContext methods.
040: *
041: */
042: public class MEPContext implements javax.xml.ws.handler.MessageContext {
043:
044: protected MessageContext requestMC;
045: protected MessageContext responseMC;
046:
047: private Map<String, Scope> scopes; // APPLICATION or HANDLER scope for properties
048:
049: /*
050: * Flag to indicate whether we're being called from a handler or an application
051: * (endpoint or client). Users of MEPContext should use the 'is' and
052: * 'set' appropriately for this flag. The most likely scenario is to set the
053: * flag to true after the server-side inbound handlers are complete.
054: *
055: * TODO, all methods should use this flag to check for access rights
056: */
057: private boolean ApplicationAccessLocked = false;
058:
059: /*
060: * Ideally this would be "protected", but we want the junit tests to see it.
061: */
062: public MEPContext(MessageContext requestMsgCtx) {
063: this .requestMC = requestMsgCtx;
064: scopes = new HashMap<String, Scope>();
065: // make sure the MessageContext points back to this
066: requestMsgCtx.setMEPContext(this );
067: }
068:
069: public EndpointDescription getEndpointDesc() {
070: if (responseMC != null) {
071: return responseMC.getEndpointDescription();
072: }
073: return requestMC.getEndpointDescription();
074: }
075:
076: public MessageContext getRequestMessageContext() {
077: return requestMC;
078: }
079:
080: public MessageContext getResponseMessageContext() {
081: return responseMC;
082: }
083:
084: public MessageContext getMessageContext() {
085: if (responseMC != null) {
086: return responseMC;
087: }
088: return requestMC;
089: }
090:
091: public void setResponseMessageContext(MessageContext responseMC) {
092: // TODO does ApplicationAccessLocked mean anything here? -- method is protected, so probably not
093: this .responseMC = responseMC;
094: // if callers are being careful, the responseMC should not be set
095: // until the engine is done invoking the endpoint, on both server and
096: // client side. At that point, we can start allowing callers access
097: // to HANDLER scoped properties again. Set the flag:
098: ApplicationAccessLocked = false;
099: }
100:
101: public void setMessage(Message msg) {
102: if (responseMC != null) {
103: responseMC.setMessage(msg);
104: } else {
105: requestMC.setMessage(msg);
106: }
107: }
108:
109: public Scope getScope(String s) {
110: if (scopes.get(s) == null) {
111: // JAX-WS default 9.4.1. However, we try to set the scope for
112: // every incoming property to HANDLER. If a property is coming from
113: // the axis2 AbstractContext properties bag, we want those to be
114: // APPLICATION scoped. Those properties may have been set by an
115: // axis application handler, and may need to be accessible by
116: // a client app or endpoint.
117: return Scope.APPLICATION;
118: }
119: return scopes.get(s);
120: }
121:
122: public void setScope(String s, Scope scope) {
123: // TODO review next two lines
124: if (isApplicationAccessLocked()) { // endpoints are not allowed to change property scope. They should all be APPLICATION scoped anyway
125: return;
126: }
127: scopes.put(s, scope);
128: }
129:
130: //--------------------------------------------------
131: // java.util.Map methods
132: //--------------------------------------------------
133:
134: public void clear() {
135: // TODO review
136: if (isApplicationAccessLocked()) { // endpoints are allowed to clear APPLICATION scoped properties only
137: Map<String, Object> appScopedProps = getApplicationScopedProperties();
138: for (Iterator it = appScopedProps.keySet().iterator(); it
139: .hasNext();) {
140: String key = (String) it.next();
141: remove(key);
142: // TODO also remove Scope setting for "key"? How?
143: }
144: return;
145: }
146: // TODO: REVIEW
147: // I don't think this will work if the message contexts have a copy
148: // of the map
149: if (responseMC != null) {
150: responseMC.getProperties().clear();
151: }
152: requestMC.getProperties().clear();
153: }
154:
155: public boolean containsKey(Object key) {
156: if (isApplicationAccessLocked()) {
157: return getApplicationScopedProperties().containsKey(key);
158: }
159: if (responseMC != null) {
160: boolean containsKey = responseMC.getProperties()
161: .containsKey(key)
162: || requestMC.getProperties().containsKey(key);
163: if ((getScope((String) key) == Scope.APPLICATION)
164: || (!isApplicationAccessLocked())) {
165: return containsKey;
166: }
167: }
168: if ((getScope((String) key) == Scope.APPLICATION)
169: || (!isApplicationAccessLocked())) {
170: return requestMC.getProperties().containsKey(key);
171: }
172: return false;
173: }
174:
175: public boolean containsValue(Object value) {
176: if (isApplicationAccessLocked()) {
177: return getApplicationScopedProperties()
178: .containsValue(value);
179: }
180: if (responseMC != null) {
181: return responseMC.getProperties().containsValue(value)
182: || requestMC.getProperties().containsValue(value);
183: }
184: return requestMC.getProperties().containsValue(value);
185: }
186:
187: public Set entrySet() {
188: // TODO should check ApplicationAccessLocked flag
189: // and return only APPLICATION scoped properties if true
190: if (isApplicationAccessLocked()) {
191: return getApplicationScopedProperties().entrySet();
192: }
193: HashMap tempProps = new HashMap();
194: tempProps.putAll(requestMC.getProperties());
195: if (responseMC != null) {
196: tempProps.putAll(responseMC.getProperties());
197: }
198: return tempProps.entrySet();
199: }
200:
201: public Object get(Object keyObject) {
202: String key = (String) keyObject;
203: if (responseMC != null) {
204: if (responseMC.getProperty(key) != null) {
205: if ((getScope((String) key) == Scope.APPLICATION)
206: || (!isApplicationAccessLocked())) {
207: return responseMC.getProperty(key);
208: }
209: }
210: }
211: if ((getScope((String) key) == Scope.APPLICATION)
212: || (!isApplicationAccessLocked())) {
213: return requestMC.getProperty(key);
214: }
215: return null;
216: }
217:
218: public boolean isEmpty() {
219: if (isApplicationAccessLocked()) {
220: return getApplicationScopedProperties().isEmpty();
221: }
222: if (responseMC != null) {
223: return requestMC.getProperties().isEmpty()
224: && requestMC.getProperties().isEmpty();
225: }
226: return requestMC.getProperties().isEmpty();
227: }
228:
229: public Set keySet() {
230: if (isApplicationAccessLocked()) {
231: return getApplicationScopedProperties().keySet();
232: }
233: HashMap tempProps = new HashMap();
234: tempProps.putAll(requestMC.getProperties());
235: if (responseMC != null) {
236: tempProps.putAll(responseMC.getProperties());
237: }
238: return tempProps.keySet();
239: }
240:
241: public Object put(String key, Object value) {
242: // TODO careful: endpoints may overwrite pre-existing key/value pairs.
243: // Those key/value pairs may already have a scope attached to them, which
244: // means an endpoint could "put" a property that is wrongly scoped
245: if (scopes.get(key) == null) { // check the scopes object directly, not through getScope()!!
246: setScope(key, Scope.HANDLER);
247: }
248: if (requestMC.getProperties().containsKey(key)) {
249: return requestMC.setProperty(key, value);
250: }
251: if (responseMC != null) {
252: return responseMC.setProperty(key, value);
253: }
254: return requestMC.setProperty(key, value);
255: }
256:
257: public void putAll(Map t) {
258: // TODO similar problem as "put"
259: for (Iterator it = t.entrySet().iterator(); it.hasNext();) {
260: Entry<String, Object> entry = (Entry) it.next();
261: if (getScope(entry.getKey()) == null) {
262: setScope(entry.getKey(), Scope.HANDLER);
263: }
264: }
265: if (responseMC != null) {
266: responseMC.setProperties(t);
267: } else {
268: requestMC.setProperties(t);
269: }
270: }
271:
272: public Object remove(Object key) {
273: // check ApplicationAccessLocked flag and prevent removal of HANDLER scoped props
274: if (isApplicationAccessLocked()) {
275: if (getScope((String) key).equals(Scope.HANDLER)) {
276: return null;
277: }
278: }
279:
280: // yes, remove from both and return the right object
281: Object retVal = null;
282: if (responseMC != null) {
283: retVal = responseMC.getProperties().remove(key);
284: }
285: if (retVal == null) {
286: return requestMC.getProperties().remove(key);
287: } else {
288: requestMC.getProperties().remove(key);
289: }
290: return retVal;
291: }
292:
293: public int size() {
294: if (isApplicationAccessLocked()) {
295: return getApplicationScopedProperties().size();
296: }
297:
298: // The properties must be combined together because some
299: // keys may be the same on the request and the response.
300: HashMap tempProps = new HashMap();
301: tempProps.putAll(requestMC.getProperties());
302: if (responseMC != null) {
303: tempProps.putAll(responseMC.getProperties());
304: }
305: return tempProps.size();
306: }
307:
308: public Collection values() {
309: if (isApplicationAccessLocked()) {
310: return getApplicationScopedProperties().values();
311: }
312: HashMap tempProps = new HashMap();
313: tempProps.putAll(requestMC.getProperties());
314: if (responseMC != null) {
315: tempProps.putAll(responseMC.getProperties());
316: }
317: return tempProps.values();
318: }
319:
320: public Message getMessageObject() {
321: // TODO does ApplicationAccessLocked apply here?
322: if (responseMC != null) {
323: return responseMC.getMessage();
324: }
325: return requestMC.getMessage();
326: }
327:
328: public boolean isApplicationAccessLocked() {
329: // since MEPContext is both a wrapper and a subclass, we need to be careful to set it only on the wrapper object:
330: if (this == requestMC.getMEPContext()) { // object compare, I am the wrapper object
331: return ApplicationAccessLocked;
332: }
333: if (responseMC == null) {
334: return requestMC.getMEPContext()
335: .isApplicationAccessLocked();
336: } else {
337: return responseMC.getMEPContext()
338: .isApplicationAccessLocked()
339: || requestMC.getMEPContext()
340: .isApplicationAccessLocked();
341: }
342: }
343:
344: public void setApplicationAccessLocked(
345: boolean applicationAccessLocked) {
346: // since MEPContext is both a wrapper and a subclass, we need to be careful to set it only on the wrapper object:
347: if (this == requestMC.getMEPContext()) { // object compare, I am the wrapper object
348: ApplicationAccessLocked = applicationAccessLocked;
349: } else {
350: requestMC.getMEPContext().setApplicationAccessLocked(
351: applicationAccessLocked);
352: }
353:
354: }
355:
356: /**
357: * The returned tempMap should be used as a read-only map as changes to it will
358: * not propogate into the requestMC or responseMC
359: *
360: * Watch out for infinite loop if you call another method in this class that uses this method.
361: *
362: * @return
363: */
364: public Map<String, Object> getApplicationScopedProperties() {
365: Map<String, Object> tempMap = new HashMap<String, Object>();
366: // better performance:
367: if (!scopes.containsValue(Scope.APPLICATION)) {
368: return tempMap;
369: }
370: for (Iterator it = requestMC.getProperties().keySet()
371: .iterator(); it.hasNext();) {
372: String key = (String) it.next();
373: if ((getScope(key).equals(Scope.APPLICATION) && (requestMC
374: .getProperties().containsKey(key)))) {
375: tempMap.put(key, get(key));
376: }
377: }
378: if (responseMC != null) {
379: for (Iterator it = responseMC.getProperties().keySet()
380: .iterator(); it.hasNext();) {
381: String key = (String) it.next();
382: if ((getScope(key).equals(Scope.APPLICATION) && (responseMC
383: .getProperties().containsKey(key)))) {
384: tempMap.put(key, get(key));
385: }
386: }
387: }
388: return tempMap;
389: }
390:
391: }
|