1/* 2 * Copyright (c) 1997, 2013, 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 26package com.sun.xml.internal.ws.transport.http; 27 28import com.sun.xml.internal.ws.transport.http.DeploymentDescriptorParser.AdapterFactory; 29import com.sun.xml.internal.ws.api.server.WSEndpoint; 30import com.sun.xml.internal.ws.api.server.PortAddressResolver; 31import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; 32import com.sun.istack.internal.NotNull; 33 34import javax.xml.namespace.QName; 35import java.util.List; 36import java.util.ArrayList; 37import java.util.Map; 38import java.util.HashMap; 39import java.util.AbstractList; 40import java.util.Map.Entry; 41 42/** 43 * List of {@link HttpAdapter}s created together. 44 * 45 * <p> 46 * Some cases WAR file may contain multiple endpoints for ports in a WSDL. 47 * If the runtime knows these ports, their port addresses can be patched. 48 * This class keeps a list of {@link HttpAdapter}s and use that information to patch 49 * multiple port addresses. 50 * 51 * <p> 52 * Concrete implementations of this class need to override {@link #createHttpAdapter} 53 * method to create implementations of {@link HttpAdapter}. 54 * 55 * @author Jitendra Kotamraju 56 */ 57public abstract class HttpAdapterList<T extends HttpAdapter> extends AbstractList<T> implements AdapterFactory<T> { 58 private final List<T> adapters = new ArrayList<T>(); 59 private final Map<PortInfo, String> addressMap = new HashMap<PortInfo, String>(); 60 61 // TODO: documented because it's used by AS 62 @Override 63 public T createAdapter(String name, String urlPattern, WSEndpoint<?> endpoint) { 64 T t = createHttpAdapter(name, urlPattern, endpoint); 65 adapters.add(t); 66 WSDLPort port = endpoint.getPort(); 67 if (port != null) { 68 PortInfo portInfo = new PortInfo(port.getOwner().getName(),port.getName().getLocalPart(), endpoint.getImplementationClass()); 69 addressMap.put(portInfo, getValidPath(urlPattern)); 70 } 71 return t; 72 } 73 74 /** 75 * Implementations need to override this one to create a concrete class 76 * of HttpAdapter 77 */ 78 protected abstract T createHttpAdapter(String name, String urlPattern, WSEndpoint<?> endpoint); 79 80 /** 81 * @return urlPattern without "/*" 82 */ 83 private String getValidPath(@NotNull String urlPattern) { 84 if (urlPattern.endsWith("/*")) { 85 return urlPattern.substring(0, urlPattern.length() - 2); 86 } else { 87 return urlPattern; 88 } 89 } 90 91 /** 92 * Creates a PortAddressResolver that maps portname to its address 93 * 94 * @param endpointImpl application endpoint Class that eventually serves the request. 95 */ 96 public PortAddressResolver createPortAddressResolver(final String baseAddress, final Class<?> endpointImpl) { 97 return new PortAddressResolver() { 98 @Override 99 public String getAddressFor(@NotNull QName serviceName, @NotNull String portName) { 100 String urlPattern = addressMap.get(new PortInfo(serviceName,portName, endpointImpl)); 101 if (urlPattern == null) { 102 //if a WSDL defines more ports, urlpattern is null (portName does not match endpointImpl) 103 //so fallback to the default behaviour where only serviceName/portName is checked 104 for (Entry<PortInfo, String> e : addressMap.entrySet()) { 105 if (serviceName.equals(e.getKey().serviceName) && portName.equals(e.getKey().portName)) { 106 urlPattern = e.getValue(); 107 break; 108 } 109 } 110 } 111 return (urlPattern == null) ? null : baseAddress+urlPattern; 112 } 113 }; 114 } 115 116 117 @Override 118 public T get(int index) { 119 return adapters.get(index); 120 } 121 122 @Override 123 public int size() { 124 return adapters.size(); 125 } 126 127 private static class PortInfo { 128 private final QName serviceName; 129 private final String portName; 130 private final Class<?> implClass; 131 132 PortInfo(@NotNull QName serviceName, @NotNull String portName, Class<?> implClass) { 133 this.serviceName = serviceName; 134 this.portName = portName; 135 this.implClass = implClass; 136 } 137 138 @Override 139 public boolean equals(Object portInfo) { 140 if (portInfo instanceof PortInfo) { 141 PortInfo that = (PortInfo)portInfo; 142 if (this.implClass == null) { 143 return this.serviceName.equals(that.serviceName) && this.portName.equals(that.portName) && that.implClass == null; 144 } 145 return this.serviceName.equals(that.serviceName) && this.portName.equals(that.portName) && this.implClass.equals(that.implClass); 146 } 147 return false; 148 } 149 150 @Override 151 public int hashCode() { 152 int retVal = serviceName.hashCode()+portName.hashCode(); 153 return implClass != null ? retVal + implClass.hashCode() : retVal; 154 } 155 } 156} 157