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.transport.http;
27  
28  import com.sun.xml.internal.ws.transport.http.DeploymentDescriptorParser.AdapterFactory;
29  import com.sun.xml.internal.ws.api.server.WSEndpoint;
30  import com.sun.xml.internal.ws.api.server.PortAddressResolver;
31  import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
32  import com.sun.istack.internal.NotNull;
33  
34  import javax.xml.namespace.QName;
35  import java.util.List;
36  import java.util.ArrayList;
37  import java.util.Map;
38  import java.util.HashMap;
39  import java.util.AbstractList;
40  import 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   */
57  public 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 }