View Javadoc
1   /*
2    * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.xml.internal.ws.client;
27  
28  import com.sun.xml.internal.ws.api.message.Packet;
29  import com.sun.xml.internal.ws.api.message.AttachmentSet;
30  import com.sun.xml.internal.ws.api.message.Attachment;
31  
32  import javax.xml.ws.handler.MessageContext;
33  import javax.activation.DataHandler;
34  import java.util.AbstractMap;
35  import java.util.Collections;
36  import java.util.HashMap;
37  import java.util.Map;
38  import java.util.Set;
39  
40  /**
41   * Implements "response context" on top of {@link Packet}.
42   *
43   * <p>
44   * This class creates a read-only {@link Map} view that
45   * gets exposed to client applications after an invocation
46   * is complete.
47   *
48   * <p>
49   * The design goal of this class is to make it efficient
50   * to create a new {@link ResponseContext}, at the expense
51   * of making some {@link Map} operations slower. This is
52   * justified because the response context is mostly just
53   * used to query a few known values, and operations like
54   * enumeration isn't likely.
55   *
56   * <p>
57   * Some of the {@link Map} methods requre this class to
58   * build the complete {@link Set} of properties, but we
59   * try to avoid that as much as possible.
60   *
61   *
62   * <pre>
63   * TODO: are we exposing all strongly-typed fields, or
64   * do they have appliation/handler scope notion?
65   * </pre>
66   *
67   * @author Kohsuke Kawaguchi
68   */
69  @SuppressWarnings({"SuspiciousMethodCalls"})    // IDE doesn't like me calling Map methods with key typed as Object
70  public class ResponseContext extends AbstractMap<String,Object> {
71      private final Packet packet;
72  
73      /**
74       * Lazily computed.
75       */
76      private Set<Map.Entry<String,Object>> entrySet;
77  
78      /**
79       * @param packet
80       *      The {@link Packet} to wrap.
81       */
82      public ResponseContext(Packet packet) {
83          this.packet = packet;
84      }
85  
86      public boolean containsKey(Object key) {
87          if(packet.supports(key))
88              return packet.containsKey(key);    // strongly typed
89  
90          if(packet.invocationProperties.containsKey(key))
91              // if handler-scope, hide it
92              return !packet.getHandlerScopePropertyNames(true).contains(key);
93  
94          return false;
95      }
96  
97      public Object get(Object key) {
98          if(packet.supports(key))
99              return packet.get(key);    // strongly typed
100 
101         if(packet.getHandlerScopePropertyNames(true).contains(key))
102             return null;            // no such application-scope property
103 
104         Object value =  packet.invocationProperties.get(key);
105 
106         //add the attachments from the Message to the corresponding attachment property
107         if(key.equals(MessageContext.INBOUND_MESSAGE_ATTACHMENTS)){
108             Map<String, DataHandler> atts = (Map<String, DataHandler>) value;
109             if(atts == null)
110                 atts = new HashMap<String, DataHandler>();
111             AttachmentSet attSet = packet.getMessage().getAttachments();
112             for(Attachment att : attSet){
113                 atts.put(att.getContentId(), att.asDataHandler());
114             }
115             return atts;
116         }
117         return value;
118     }
119 
120     public Object put(String key, Object value) {
121         // response context is read-only
122         throw new UnsupportedOperationException();
123     }
124 
125     public Object remove(Object key) {
126         // response context is read-only
127         throw new UnsupportedOperationException();
128     }
129 
130     public void putAll(Map<? extends String, ? extends Object> t) {
131         // response context is read-only
132         throw new UnsupportedOperationException();
133     }
134 
135     public void clear() {
136         // response context is read-only
137         throw new UnsupportedOperationException();
138     }
139 
140     public Set<Entry<String, Object>> entrySet() {
141         if(entrySet==null) {
142             // this is where the worst case happens. we have to clone the whole properties
143             // to get this view.
144 
145             // use TreeSet so that toString() sort them nicely. It's easier for apps.
146             Map<String,Object> r = new HashMap<String,Object>();
147 
148             // export application-scope properties
149             r.putAll(packet.invocationProperties);
150 
151             // hide handler-scope properties
152             r.keySet().removeAll(packet.getHandlerScopePropertyNames(true));
153 
154             // and all strongly typed ones
155             r.putAll(packet.createMapView());
156 
157             entrySet = Collections.unmodifiableSet(r.entrySet());
158         }
159 
160         return entrySet;
161     }
162 
163 }