View Javadoc

1   /*
2    *  Copyright (c) 2008 Rodrigo Ruiz
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.apache.ws.addressing.handler;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.StringTokenizer;
22  
23  import javax.xml.namespace.QName;
24  import javax.xml.rpc.JAXRPCException;
25  import javax.xml.rpc.handler.GenericHandler;
26  import javax.xml.rpc.handler.HandlerInfo;
27  import javax.xml.rpc.handler.MessageContext;
28  
29  import org.apache.axis.message.addressing.Constants;
30  import org.apache.axis.message.addressing.MessageID;
31  import org.apache.axis.types.URI;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.ws.addressing.uuid.UUIdGeneratorFactory;
35  
36  /**
37   * Abstract JAX-RPC {@link javax.xml.rpc.handler.Handler} containing base WS-Addressing
38   * functionality that is used by both client-side and server-side subclasses.
39   *
40   * @author Davanum Srinivas
41   * @author Ian P. Springer
42   * @version $Revision: 14 $
43   */
44  public abstract class AbstractAddressingHandler extends GenericHandler {
45  
46    /**
47     * Configuration property name for the Actor URI.
48     */
49    public static final String CONFIG_PROP_ACTOR = "actor";
50  
51    /**
52     * Configuration property name for a list of reference property names.
53     */
54    public static final String CONFIG_PROP_REFERENCE_PROPERTY_NAMES
55      = "referencePropertyNames";
56  
57    /**
58     * Configuration property name for the "processed header removal" flag.
59     */
60    public static final String CONFIG_PROP_REMOVE_HEADERS = "removeHeaders";
61  
62    /**
63     * URI scheme used in UUIDs.
64     */
65    static final String UUID_URI_SCHEME = "uuid";
66  
67    /**
68     * List of understood addressing headers.
69     */
70    private static final QName[] UNDERSTOOD_HEADERS = new QName[] {
71      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.ACTION),
72      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.FAULT_TO),
73      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.FROM),
74      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.MESSAGE_ID),
75      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.RECIPIENT),
76      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.RELATES_TO),
77      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.REPLY_TO),
78      new QName(Constants.NS_URI_ADDRESSING_2003_03, Constants.TO),
79      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.ACTION),
80      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.FAULT_TO),
81      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.FROM),
82      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.MESSAGE_ID),
83      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.RECIPIENT),
84      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.RELATES_TO),
85      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.REPLY_TO),
86      new QName(Constants.NS_URI_ADDRESSING_2004_03, Constants.TO),
87      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.ACTION),
88      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.FAULT_TO),
89      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.FROM),
90      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.MESSAGE_ID),
91      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.RECIPIENT),
92      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.RELATES_TO),
93      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.REPLY_TO),
94      new QName(Constants.NS_URI_ADDRESSING_2004_08, Constants.TO)
95    };
96  
97    /**
98     * Constant to be returned by handleRequest(), handleResponse(), and handleFault().
99     */
100   protected static final boolean CONTINUE_HANDLER_CHAIN_PROCESSING = true;
101 
102   /**
103    * Class logger.
104    */
105   private static final Log LOG = LogFactory.getLog(AbstractAddressingHandler.class);
106 
107   /**
108    * Handler configuration.
109    */
110   private Map<String, String> handlerConfigProps;
111 
112   /**
113    * Reference property names to process.
114    */
115   private List<QName> refPropQNames;
116 
117   /**
118    * Returns a list QNames of the SOAP headers that this handler processes.
119    *
120    * @return Returns a list QNames of the SOAP headers that this handler processes
121    */
122   public QName[] getHeaders() {
123     return UNDERSTOOD_HEADERS.clone();
124   }
125 
126   /**
127    * Initializes this handler. This handler supports the following configuration
128    * properties:
129    * <ul>
130    *   <li>actor (optional) - only SOAP headers with this actor URI will be processed</li>
131    *   <li>referencePropertyNames (optional) - a list of QNames of reference properties
132    *       (i.e. - non-WSA SOAP headers) that should be processed; if set to "*", all
133    *       properties will be processed, if not specified, only WSA headers will be
134    *       processed</li>
135    *   <li>removeHeaders (optional) - if set to "true", headers will be removed from the
136    *       SOAP envelope after they have been processed</li>
137    * </ul>
138    *
139    * @param handlerInfo
140    *            handler info containing handler configuration properties from deployment
141    *            descriptor
142    */
143   @SuppressWarnings("unchecked")
144   @Override
145   public void init(HandlerInfo handlerInfo) {
146     super.init(handlerInfo);
147     LOG.info("Initializing JAX-RPC handler " + this.getClass().getName() + "...");
148     handlerConfigProps = handlerInfo.getHandlerConfig();
149     initReferencePropertyQNames();
150   }
151 
152   /**
153    * Returns this handler's configuration properties.
154    *
155    * @return this handler's configuration properties
156    */
157   protected Map<String, String> getHandlerConfigProperties() {
158     return handlerConfigProps;
159   }
160 
161   /**
162    * Returns the value of the specified handler configuration property.
163    *
164    * @param propName
165    *            the name of a configuration property
166    *
167    * @return the value of the specified handler configuration property
168    */
169   protected String getHandlerConfigProperty(String propName) {
170     return (String) getHandlerConfigProperties().get(propName);
171   }
172 
173   /**
174    * Returns true if the value of the specified handler configuration property is "true",
175    * or false otherwise.
176    *
177    * @param propName
178    *            the name of a configuration property
179    *
180    * @return true if the value of the specified handler configuration property is "true",
181    *         or false otherwise
182    */
183   protected boolean isHandlerConfigPropertyTrue(String propName) {
184     return Boolean.TRUE.toString().equalsIgnoreCase(getHandlerConfigProperty(propName));
185   }
186 
187   /**
188    * This method uses the Java UUID Generator library found through discovery.
189    * <p>
190    * Subclasses can optionally override it to use a different UUID generator.
191    *
192    * @return A unique identifier
193    */
194   protected String generateUUId() {
195     try {
196       return UUIdGeneratorFactory.getGenerator().generateUUId();
197     } catch (RuntimeException re) {
198       throw new JAXRPCException("Failed to generate UUId using default UUId generator",
199           re);
200     }
201   }
202 
203   /**
204    * Gets the value of the "MustUnderstandEnabled" field.
205    *
206    * @param msgContext Context to get the information from
207    * @return Field value
208    */
209   protected boolean isMustUnderstandEnabled(MessageContext msgContext) {
210     return isPropertyTrue(msgContext, Constants.ENV_ADDRESSING_SET_MUST_UNDERSTAND);
211   }
212 
213   /**
214    * Gets if the specified property has a "true" as its value.
215    *
216    * @param msgContext Context to get the information from
217    * @param propName   Property name
218    * @return true if the property is set to "true"
219    */
220   protected boolean isPropertyTrue(MessageContext msgContext, String propName) {
221     return Boolean.TRUE.toString().equals(msgContext.getProperty(propName));
222   }
223 
224   /**
225    * Creates a new random message identifier.
226    *
227    * @return The message identifier URI
228    * @throws URI.MalformedURIException If an invalid URI is created
229    */
230   protected MessageID createMessageID() throws URI.MalformedURIException {
231     return new MessageID(new URI(UUID_URI_SCHEME + ":" + generateUUId()));
232   }
233 
234   /**
235    * Gets the list of processed property names.
236    *
237    * @return The list of property names
238    */
239   protected List<QName> getReferencePropertyQNames() {
240     return refPropQNames;
241   }
242 
243   /**
244    * Returns the value of the "actor" handler config property.
245    *
246    * @return the value of the "actor" handler config property
247    */
248   protected String getActor() {
249     return getHandlerConfigProperty(CONFIG_PROP_ACTOR);
250   }
251 
252   /**
253    * Returns the value of the "removeHeaders" handler config property.
254    *
255    * @return the value of the "removeHeaders" handler config property
256    */
257   protected boolean isRemoveHeadersEnabled() {
258     return isHandlerConfigPropertyTrue(CONFIG_PROP_REMOVE_HEADERS);
259   }
260 
261   /**
262    * Retrieves QNames for reference properties from WSDD and initializes
263    * refPropQNames - the list of reference properties that this handler
264    * should care about.
265    */
266   protected void initReferencePropertyQNames() {
267     String refPropNamesConfigPropValue
268       = getHandlerConfigProperty(CONFIG_PROP_REFERENCE_PROPERTY_NAMES);
269 
270     if (refPropNamesConfigPropValue == null) {
271       LOG.debug("No reference properties will be processed.");
272       refPropQNames = new ArrayList<QName>();
273     } else if (refPropNamesConfigPropValue.equals("*")) {
274       LOG.debug("All reference properties will be processed.");
275       refPropQNames = null;
276     } else {
277       refPropQNames = new ArrayList<QName>();
278       StringTokenizer tokenizer = new StringTokenizer(refPropNamesConfigPropValue, ",");
279       while (tokenizer.hasMoreTokens()) {
280         String qnameString = tokenizer.nextToken().trim();
281         try {
282           QName qname = QName.valueOf(qnameString);
283           LOG.debug("Reference properties with QName '" + qnameString
284               + "' will be processed.");
285           refPropQNames.add(qname);
286         } catch (IllegalArgumentException iae) {
287           LOG.warn("Invalid QName '" + qnameString + "' specified in handler config.");
288         }
289       }
290     }
291   }
292 
293 }