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.handler; 27 28 import com.sun.xml.internal.ws.api.BindingID; 29 import com.sun.xml.internal.ws.api.WSBinding; 30 import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil; 31 import com.sun.xml.internal.ws.transport.http.DeploymentDescriptorParser; 32 import com.sun.xml.internal.ws.util.HandlerAnnotationInfo; 33 import com.sun.xml.internal.ws.util.JAXWSUtils; 34 import com.sun.xml.internal.ws.util.UtilException; 35 36 import javax.annotation.PostConstruct; 37 import javax.xml.namespace.QName; 38 import javax.xml.stream.XMLStreamConstants; 39 import javax.xml.stream.XMLStreamReader; 40 import javax.xml.ws.handler.Handler; 41 import javax.xml.ws.handler.PortInfo; 42 import java.lang.reflect.Method; 43 import java.util.ArrayList; 44 import java.util.HashSet; 45 import java.util.List; 46 import java.util.Set; 47 import java.util.StringTokenizer; 48 import java.util.logging.Logger; 49 50 51 public class HandlerChainsModel { 52 private static final Logger logger = Logger.getLogger( 53 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".util"); 54 55 private Class annotatedClass; 56 private List<HandlerChainType> handlerChains; 57 private String id; 58 /** Creates a new instance of HandlerChains */ HandlerChainsModel(Class annotatedClass)59 private HandlerChainsModel(Class annotatedClass) { 60 this.annotatedClass = annotatedClass; 61 } 62 getHandlerChain()63 private List<HandlerChainType> getHandlerChain() { 64 if (handlerChains == null) { 65 handlerChains = new ArrayList<HandlerChainType>(); 66 } 67 return handlerChains; 68 } 69 getId()70 public String getId() { 71 return id; 72 } 73 setId(String value)74 public void setId(String value) { 75 this.id = value; 76 } 77 /** 78 * reader should be on <handler-chains> element 79 */ parseHandlerConfigFile(Class annotatedClass, XMLStreamReader reader)80 public static HandlerChainsModel parseHandlerConfigFile(Class annotatedClass, XMLStreamReader reader) { 81 ensureProperName(reader,QNAME_HANDLER_CHAINS); 82 HandlerChainsModel handlerModel = new HandlerChainsModel(annotatedClass); 83 List<HandlerChainType> hChains = handlerModel.getHandlerChain(); 84 XMLStreamReaderUtil.nextElementContent(reader); 85 86 while (reader.getName().equals(QNAME_HANDLER_CHAIN)) { 87 HandlerChainType hChain = new HandlerChainType(); 88 XMLStreamReaderUtil.nextElementContent(reader); 89 90 if (reader.getName().equals(QNAME_CHAIN_PORT_PATTERN)) { 91 QName portNamePattern = XMLStreamReaderUtil.getElementQName(reader); 92 hChain.setPortNamePattern(portNamePattern); 93 XMLStreamReaderUtil.nextElementContent(reader); 94 } else if (reader.getName().equals(QNAME_CHAIN_PROTOCOL_BINDING)) { 95 String bindingList = XMLStreamReaderUtil.getElementText(reader); 96 StringTokenizer stk = new StringTokenizer(bindingList); 97 while(stk.hasMoreTokens()) { 98 String token = stk.nextToken(); 99 // This will convert tokens into Binding URI 100 hChain.addProtocolBinding(token); 101 } 102 XMLStreamReaderUtil.nextElementContent(reader); 103 } else if (reader.getName().equals(QNAME_CHAIN_SERVICE_PATTERN)) { 104 QName serviceNamepattern = XMLStreamReaderUtil.getElementQName(reader); 105 hChain.setServiceNamePattern(serviceNamepattern); 106 XMLStreamReaderUtil.nextElementContent(reader); 107 } 108 List<HandlerType> handlers = hChain.getHandlers(); 109 // process all <handler> elements 110 while (reader.getName().equals(QNAME_HANDLER)) { 111 HandlerType handler = new HandlerType(); 112 113 XMLStreamReaderUtil.nextContent(reader); 114 if (reader.getName().equals(QNAME_HANDLER_NAME)) { 115 String handlerName = 116 XMLStreamReaderUtil.getElementText(reader).trim(); 117 handler.setHandlerName(handlerName); 118 XMLStreamReaderUtil.nextContent(reader); 119 } 120 121 // handler class 122 ensureProperName(reader, QNAME_HANDLER_CLASS); 123 String handlerClass = 124 XMLStreamReaderUtil.getElementText(reader).trim(); 125 handler.setHandlerClass(handlerClass); 126 XMLStreamReaderUtil.nextContent(reader); 127 128 // init params (ignored) 129 while (reader.getName().equals(QNAME_HANDLER_PARAM)) { 130 skipInitParamElement(reader); 131 } 132 133 // headers (ignored) 134 while (reader.getName().equals(QNAME_HANDLER_HEADER)) { 135 skipTextElement(reader); 136 } 137 138 // roles (not stored per handler) 139 while (reader.getName().equals(QNAME_HANDLER_ROLE)) { 140 List<String> soapRoles = handler.getSoapRoles(); 141 soapRoles.add(XMLStreamReaderUtil.getElementText(reader)); 142 XMLStreamReaderUtil.nextContent(reader); 143 } 144 145 handlers.add(handler); 146 147 // move past </handler> 148 ensureProperName(reader, QNAME_HANDLER); 149 XMLStreamReaderUtil.nextContent(reader); 150 } 151 152 // move past </handler-chain> 153 ensureProperName(reader, QNAME_HANDLER_CHAIN); 154 hChains.add(hChain); 155 XMLStreamReaderUtil.nextContent(reader); 156 } 157 158 return handlerModel; 159 } 160 161 /** 162 * <p>This method is called internally by HandlerAnnotationProcessor, 163 * and by 164 * {@link com.sun.xml.internal.ws.transport.http.DeploymentDescriptorParser} 165 * directly when it reaches the handler chains element in the 166 * descriptor file it is parsing. 167 * @param reader should be on <handler-chains> element 168 * @return A HandlerAnnotationInfo object that stores the 169 * handlers and roles. 170 */ 171 172 173 parseHandlerFile(XMLStreamReader reader, ClassLoader classLoader, QName serviceName, QName portName, WSBinding wsbinding)174 public static HandlerAnnotationInfo parseHandlerFile(XMLStreamReader reader, 175 ClassLoader classLoader, QName serviceName, QName portName, 176 WSBinding wsbinding) { 177 ensureProperName(reader,QNAME_HANDLER_CHAINS); 178 String bindingId = wsbinding.getBindingId().toString(); 179 HandlerAnnotationInfo info = new HandlerAnnotationInfo(); 180 181 XMLStreamReaderUtil.nextElementContent(reader); 182 183 List<Handler> handlerChain = new ArrayList<Handler>(); 184 Set<String> roles = new HashSet<String>(); 185 186 while (reader.getName().equals(QNAME_HANDLER_CHAIN)) { 187 188 XMLStreamReaderUtil.nextElementContent(reader); 189 190 if (reader.getName().equals(QNAME_CHAIN_PORT_PATTERN)) { 191 if (portName == null) { 192 logger.warning("handler chain sepcified for port " + 193 "but port QName passed to parser is null"); 194 } 195 boolean parseChain = JAXWSUtils.matchQNames(portName, 196 XMLStreamReaderUtil.getElementQName(reader)); 197 if (!parseChain) { 198 skipChain(reader); 199 continue; 200 } 201 XMLStreamReaderUtil.nextElementContent(reader); 202 } else if (reader.getName().equals(QNAME_CHAIN_PROTOCOL_BINDING)) { 203 if (bindingId == null) { 204 logger.warning("handler chain sepcified for bindingId " + 205 "but bindingId passed to parser is null"); 206 } 207 String bindingConstraint = XMLStreamReaderUtil.getElementText(reader); 208 boolean skipThisChain = true; 209 StringTokenizer stk = new StringTokenizer(bindingConstraint); 210 List<String> bindingList = new ArrayList<String>(); 211 while(stk.hasMoreTokens()) { 212 String tokenOrURI = stk.nextToken(); 213 /* 214 Convert short-form tokens to API's binding ids 215 Unknown token, Put it as it is 216 */ 217 tokenOrURI = DeploymentDescriptorParser.getBindingIdForToken(tokenOrURI); 218 String binding = BindingID.parse(tokenOrURI).toString(); 219 bindingList.add(binding); 220 } 221 if(bindingList.contains(bindingId)){ 222 skipThisChain = false; 223 } 224 225 if (skipThisChain) { 226 skipChain(reader); 227 continue; 228 } 229 XMLStreamReaderUtil.nextElementContent(reader); 230 } else if (reader.getName().equals(QNAME_CHAIN_SERVICE_PATTERN)) { 231 if (serviceName == null) { 232 logger.warning("handler chain sepcified for service " + 233 "but service QName passed to parser is null"); 234 } 235 boolean parseChain = JAXWSUtils.matchQNames( 236 serviceName, 237 XMLStreamReaderUtil.getElementQName(reader)); 238 if (!parseChain) { 239 skipChain(reader); 240 continue; 241 } 242 XMLStreamReaderUtil.nextElementContent(reader); 243 } 244 245 // process all <handler> elements 246 while (reader.getName().equals(QNAME_HANDLER)) { 247 Handler handler; 248 249 XMLStreamReaderUtil.nextContent(reader); 250 if (reader.getName().equals(QNAME_HANDLER_NAME)) { 251 skipTextElement(reader); 252 } 253 254 // handler class 255 ensureProperName(reader, QNAME_HANDLER_CLASS); 256 try { 257 handler = (Handler) loadClass(classLoader, 258 XMLStreamReaderUtil.getElementText(reader).trim()).newInstance(); 259 } catch (InstantiationException ie){ 260 throw new RuntimeException(ie); 261 } catch (IllegalAccessException e) { 262 throw new RuntimeException(e); 263 } 264 XMLStreamReaderUtil.nextContent(reader); 265 266 // init params (ignored) 267 while (reader.getName().equals(QNAME_HANDLER_PARAM)) { 268 skipInitParamElement(reader); 269 } 270 271 // headers (ignored) 272 while (reader.getName().equals(QNAME_HANDLER_HEADER)) { 273 skipTextElement(reader); 274 } 275 276 // roles (not stored per handler) 277 while (reader.getName().equals(QNAME_HANDLER_ROLE)) { 278 roles.add(XMLStreamReaderUtil.getElementText(reader)); 279 XMLStreamReaderUtil.nextContent(reader); 280 } 281 282 // call @PostConstruct method on handler if present 283 for (Method method : handler.getClass().getMethods()) { 284 if (method.getAnnotation(PostConstruct.class) == null) { 285 continue; 286 } 287 try { 288 method.invoke(handler, new Object [0]); 289 break; 290 } catch (Exception e) { 291 throw new RuntimeException(e); 292 } 293 } 294 295 handlerChain.add(handler); 296 297 // move past </handler> 298 ensureProperName(reader, QNAME_HANDLER); 299 XMLStreamReaderUtil.nextContent(reader); 300 } 301 302 // move past </handler-chain> 303 ensureProperName(reader, QNAME_HANDLER_CHAIN); 304 XMLStreamReaderUtil.nextContent(reader); 305 } 306 307 info.setHandlers(handlerChain); 308 info.setRoles(roles); 309 return info; 310 } 311 getHandlersForPortInfo(PortInfo info)312 public HandlerAnnotationInfo getHandlersForPortInfo(PortInfo info){ 313 314 HandlerAnnotationInfo handlerInfo = new HandlerAnnotationInfo(); 315 List<Handler> handlerClassList = new ArrayList<Handler>(); 316 Set<String> roles = new HashSet<String>(); 317 318 for(HandlerChainType hchain : handlerChains) { 319 boolean hchainMatched = false; 320 if((!hchain.isConstraintSet()) || 321 JAXWSUtils.matchQNames(info.getServiceName(), hchain.getServiceNamePattern()) || 322 JAXWSUtils.matchQNames(info.getPortName(), hchain.getPortNamePattern()) || 323 hchain.getProtocolBindings().contains(info.getBindingID()) ){ 324 hchainMatched = true; 325 326 } 327 if(hchainMatched) { 328 for(HandlerType handler : hchain.getHandlers()) { 329 try { 330 Handler handlerClass = (Handler) loadClass(annotatedClass.getClassLoader(), 331 handler.getHandlerClass()).newInstance(); 332 callHandlerPostConstruct(handlerClass); 333 handlerClassList.add(handlerClass); 334 } catch (InstantiationException ie){ 335 throw new RuntimeException(ie); 336 } catch (IllegalAccessException e) { 337 throw new RuntimeException(e); 338 } 339 340 roles.addAll(handler.getSoapRoles()); 341 } 342 343 } 344 } 345 346 handlerInfo.setHandlers(handlerClassList); 347 handlerInfo.setRoles(roles); 348 return handlerInfo; 349 350 } 351 loadClass(ClassLoader loader, String name)352 private static Class loadClass(ClassLoader loader, String name) { 353 try { 354 return Class.forName(name, true, loader); 355 } catch (ClassNotFoundException e) { 356 throw new UtilException( 357 "util.handler.class.not.found", 358 name); 359 } 360 } 361 callHandlerPostConstruct(Object handlerClass)362 private static void callHandlerPostConstruct(Object handlerClass) { 363 // call @PostConstruct method on handler if present 364 for (Method method : handlerClass.getClass().getMethods()) { 365 if (method.getAnnotation(PostConstruct.class) == null) { 366 continue; 367 } 368 try { 369 method.invoke(handlerClass, new Object [0]); 370 break; 371 } catch (Exception e) { 372 throw new RuntimeException(e); 373 } 374 } 375 } 376 skipChain(XMLStreamReader reader)377 private static void skipChain(XMLStreamReader reader) { 378 while (XMLStreamReaderUtil.nextContent(reader) != 379 XMLStreamConstants.END_ELEMENT || 380 !reader.getName().equals(QNAME_HANDLER_CHAIN)) {} 381 XMLStreamReaderUtil.nextElementContent(reader); 382 } 383 skipTextElement(XMLStreamReader reader)384 private static void skipTextElement(XMLStreamReader reader) { 385 XMLStreamReaderUtil.nextContent(reader); 386 XMLStreamReaderUtil.nextElementContent(reader); 387 XMLStreamReaderUtil.nextElementContent(reader); 388 } 389 skipInitParamElement(XMLStreamReader reader)390 private static void skipInitParamElement(XMLStreamReader reader) { 391 int state; 392 do { 393 state = XMLStreamReaderUtil.nextContent(reader); 394 } while (state != XMLStreamReader.END_ELEMENT || 395 !reader.getName().equals(QNAME_HANDLER_PARAM)); 396 XMLStreamReaderUtil.nextElementContent(reader); 397 } 398 ensureProperName(XMLStreamReader reader, QName expectedName)399 private static void ensureProperName(XMLStreamReader reader, 400 QName expectedName) { 401 402 if (!reader.getName().equals(expectedName)) { 403 failWithLocalName("util.parser.wrong.element", reader, 404 expectedName.getLocalPart()); 405 } 406 } 407 ensureProperName(XMLStreamReader reader, String expectedName)408 static void ensureProperName(XMLStreamReader reader, String expectedName) { 409 if (!reader.getLocalName().equals(expectedName)) { 410 failWithLocalName("util.parser.wrong.element", reader, 411 expectedName); 412 } 413 } 414 failWithLocalName(String key, XMLStreamReader reader, String arg)415 private static void failWithLocalName(String key, 416 XMLStreamReader reader, String arg) { 417 throw new UtilException(key, 418 Integer.toString(reader.getLocation().getLineNumber()), 419 reader.getLocalName(), 420 arg ); 421 } 422 423 public static final String PROTOCOL_SOAP11_TOKEN = "##SOAP11_HTTP"; 424 public static final String PROTOCOL_SOAP12_TOKEN = "##SOAP12_HTTP"; 425 public static final String PROTOCOL_XML_TOKEN = "##XML_HTTP"; 426 427 public static final String NS_109 = 428 "http://java.sun.com/xml/ns/javaee"; 429 public static final QName QNAME_CHAIN_PORT_PATTERN = 430 new QName(NS_109, "port-name-pattern"); 431 public static final QName QNAME_CHAIN_PROTOCOL_BINDING = 432 new QName(NS_109, "protocol-bindings"); 433 public static final QName QNAME_CHAIN_SERVICE_PATTERN = 434 new QName(NS_109, "service-name-pattern"); 435 public static final QName QNAME_HANDLER_CHAIN = 436 new QName(NS_109, "handler-chain"); 437 public static final QName QNAME_HANDLER_CHAINS = 438 new QName(NS_109, "handler-chains"); 439 public static final QName QNAME_HANDLER = 440 new QName(NS_109, "handler"); 441 public static final QName QNAME_HANDLER_NAME = 442 new QName(NS_109, "handler-name"); 443 public static final QName QNAME_HANDLER_CLASS = 444 new QName(NS_109, "handler-class"); 445 public static final QName QNAME_HANDLER_PARAM = 446 new QName(NS_109, "init-param"); 447 public static final QName QNAME_HANDLER_PARAM_NAME = 448 new QName(NS_109, "param-name"); 449 public static final QName QNAME_HANDLER_PARAM_VALUE = 450 new QName(NS_109, "param-value"); 451 public static final QName QNAME_HANDLER_HEADER = 452 new QName(NS_109, "soap-header"); 453 public static final QName QNAME_HANDLER_ROLE = 454 new QName(NS_109, "soap-role"); 455 456 static class HandlerChainType { 457 //constraints 458 QName serviceNamePattern; 459 QName portNamePattern; 460 List<String> protocolBindings; 461 462 // This flag is set if one of the above constraint is set on handler chain 463 boolean constraintSet = false; 464 465 List<HandlerType> handlers; 466 String id; 467 468 469 /** Creates a new instance of HandlerChain */ HandlerChainType()470 public HandlerChainType() { 471 protocolBindings = new ArrayList<String>(); 472 } 473 setServiceNamePattern(QName value)474 public void setServiceNamePattern(QName value) { 475 this.serviceNamePattern = value; 476 constraintSet = true; 477 } 478 getServiceNamePattern()479 public QName getServiceNamePattern() { 480 return serviceNamePattern; 481 } 482 setPortNamePattern(QName value)483 public void setPortNamePattern(QName value) { 484 this.portNamePattern = value; 485 constraintSet = true; 486 } 487 getPortNamePattern()488 public QName getPortNamePattern() { 489 return portNamePattern; 490 } 491 getProtocolBindings()492 public List<java.lang.String> getProtocolBindings() { 493 return this.protocolBindings; 494 } 495 addProtocolBinding(String tokenOrURI)496 public void addProtocolBinding(String tokenOrURI){ 497 /* 498 Convert short-form tokens to API's binding ids 499 Unknown token, Put it as it is 500 */ 501 tokenOrURI = DeploymentDescriptorParser.getBindingIdForToken(tokenOrURI); 502 String binding = BindingID.parse(tokenOrURI).toString(); 503 protocolBindings.add(binding); 504 constraintSet = true; 505 } 506 isConstraintSet()507 public boolean isConstraintSet() { 508 return constraintSet || !protocolBindings.isEmpty(); 509 } getId()510 public java.lang.String getId() { 511 return id; 512 } 513 setId(java.lang.String value)514 public void setId(java.lang.String value) { 515 this.id = value; 516 } 517 getHandlers()518 public List<HandlerType> getHandlers() { 519 if (handlers == null) { 520 handlers = new ArrayList<HandlerType>(); 521 } 522 return this.handlers; 523 } 524 } 525 526 static class HandlerType { 527 String handlerName; 528 String handlerClass; 529 List<String> soapRoles; 530 531 java.lang.String id; 532 533 /** Creates a new instance of HandlerComponent */ HandlerType()534 public HandlerType() { 535 } 536 getHandlerName()537 public String getHandlerName() { 538 return handlerName; 539 } 540 setHandlerName(String value)541 public void setHandlerName(String value) { 542 this.handlerName = value; 543 } 544 getHandlerClass()545 public String getHandlerClass() { 546 return handlerClass; 547 } 548 setHandlerClass(String value)549 public void setHandlerClass(String value) { 550 this.handlerClass = value; 551 } 552 getId()553 public java.lang.String getId() { 554 return id; 555 } 556 setId(java.lang.String value)557 public void setId(java.lang.String value) { 558 this.id = value; 559 } 560 getSoapRoles()561 public List<String> getSoapRoles() { 562 if (soapRoles == null) { 563 soapRoles = new ArrayList<String>(); 564 } 565 return this.soapRoles; 566 } 567 } 568 } 569