Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
ohair@286 | 1 | /* |
ohair@286 | 2 | * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
ohair@286 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
ohair@286 | 4 | * |
ohair@286 | 5 | * This code is free software; you can redistribute it and/or modify it |
ohair@286 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ohair@286 | 7 | * published by the Free Software Foundation. Oracle designates this |
ohair@286 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@286 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
ohair@286 | 10 | * |
ohair@286 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
ohair@286 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
ohair@286 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
ohair@286 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
ohair@286 | 15 | * accompanied this code). |
ohair@286 | 16 | * |
ohair@286 | 17 | * You should have received a copy of the GNU General Public License version |
ohair@286 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
ohair@286 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
ohair@286 | 20 | * |
ohair@286 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@286 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@286 | 23 | * questions. |
ohair@286 | 24 | */ |
ohair@286 | 25 | |
ohair@286 | 26 | package com.sun.xml.internal.ws.transport.http; |
ohair@286 | 27 | |
ohair@286 | 28 | |
ohair@286 | 29 | import com.sun.istack.internal.NotNull; |
ohair@286 | 30 | import com.sun.istack.internal.Nullable; |
ohair@286 | 31 | import com.sun.xml.internal.ws.api.addressing.NonAnonymousResponseProcessor; |
ohair@286 | 32 | import com.sun.xml.internal.ws.api.Component; |
ohair@286 | 33 | import com.sun.xml.internal.ws.api.PropertySet; |
ohair@286 | 34 | import com.sun.xml.internal.ws.api.ha.HaInfo; |
ohair@286 | 35 | import com.sun.xml.internal.ws.api.ha.StickyFeature; |
ohair@286 | 36 | import com.sun.xml.internal.ws.api.message.ExceptionHasMessage; |
ohair@286 | 37 | import com.sun.xml.internal.ws.api.message.Message; |
ohair@286 | 38 | import com.sun.xml.internal.ws.api.message.Packet; |
ohair@286 | 39 | import com.sun.xml.internal.ws.api.pipe.Codec; |
ohair@286 | 40 | import com.sun.xml.internal.ws.api.pipe.ContentType; |
ohair@286 | 41 | import com.sun.xml.internal.ws.api.server.AbstractServerAsyncTransport; |
ohair@286 | 42 | import com.sun.xml.internal.ws.api.server.Adapter; |
ohair@286 | 43 | import com.sun.xml.internal.ws.api.server.BoundEndpoint; |
ohair@286 | 44 | import com.sun.xml.internal.ws.api.server.DocumentAddressResolver; |
ohair@286 | 45 | import com.sun.xml.internal.ws.api.server.Module; |
ohair@286 | 46 | import com.sun.xml.internal.ws.api.server.PortAddressResolver; |
ohair@286 | 47 | import com.sun.xml.internal.ws.api.server.SDDocument; |
ohair@286 | 48 | import com.sun.xml.internal.ws.api.server.ServiceDefinition; |
ohair@286 | 49 | import com.sun.xml.internal.ws.api.server.TransportBackChannel; |
ohair@286 | 50 | import com.sun.xml.internal.ws.api.server.WSEndpoint; |
ohair@286 | 51 | import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate; |
ohair@286 | 52 | import com.sun.xml.internal.ws.resources.WsservletMessages; |
ohair@286 | 53 | import com.sun.xml.internal.ws.server.UnsupportedMediaException; |
ohair@286 | 54 | import com.sun.xml.internal.ws.util.ByteArrayBuffer; |
ohair@286 | 55 | import com.sun.xml.internal.ws.util.Pool; |
ohair@286 | 56 | |
ohair@286 | 57 | import javax.xml.ws.Binding; |
ohair@286 | 58 | import javax.xml.ws.WebServiceException; |
ohair@286 | 59 | import javax.xml.ws.WebServiceFeature; |
ohair@286 | 60 | import javax.xml.ws.http.HTTPBinding; |
ohair@286 | 61 | |
ohair@286 | 62 | import java.io.ByteArrayOutputStream; |
ohair@286 | 63 | import java.io.IOException; |
ohair@286 | 64 | import java.io.InputStream; |
ohair@286 | 65 | import java.io.OutputStream; |
ohair@286 | 66 | import java.io.OutputStreamWriter; |
ohair@286 | 67 | import java.io.PrintWriter; |
ohair@286 | 68 | import java.net.HttpURLConnection; |
ohair@286 | 69 | import java.util.*; |
ohair@286 | 70 | import java.util.Map.Entry; |
ohair@286 | 71 | import java.util.logging.Level; |
ohair@286 | 72 | import java.util.logging.Logger; |
ohair@286 | 73 | |
ohair@286 | 74 | /** |
ohair@286 | 75 | * {@link Adapter} that receives messages in HTTP. |
ohair@286 | 76 | * |
ohair@286 | 77 | * <p> |
ohair@286 | 78 | * This object also assigns unique query string (such as "xsd=1") to |
ohair@286 | 79 | * each {@link SDDocument} so that they can be served by HTTP GET requests. |
ohair@286 | 80 | * |
ohair@286 | 81 | * @author Kohsuke Kawaguchi |
ohair@286 | 82 | * @author Jitendra Kotamraju |
ohair@286 | 83 | */ |
ohair@286 | 84 | public class HttpAdapter extends Adapter<HttpAdapter.HttpToolkit> { |
ohair@286 | 85 | |
ohair@286 | 86 | /** |
ohair@286 | 87 | * {@link SDDocument}s keyed by the query string like "?abc". |
ohair@286 | 88 | * Used for serving documents via HTTP GET. |
ohair@286 | 89 | * |
ohair@286 | 90 | * Empty if the endpoint doesn't have {@link ServiceDefinition}. |
ohair@286 | 91 | * Read-only. |
ohair@286 | 92 | */ |
ohair@286 | 93 | protected Map<String,SDDocument> wsdls; |
ohair@286 | 94 | |
ohair@286 | 95 | /** |
ohair@286 | 96 | * Reverse map of {@link #wsdls}. Read-only. |
ohair@286 | 97 | */ |
ohair@286 | 98 | private Map<SDDocument,String> revWsdls; |
ohair@286 | 99 | |
ohair@286 | 100 | /** |
ohair@286 | 101 | * A reference to the service definition from which the map of wsdls/revWsdls |
ohair@286 | 102 | * was created. This allows us to establish if the service definition documents |
ohair@286 | 103 | * have changed in the meantime. |
ohair@286 | 104 | */ |
ohair@286 | 105 | private ServiceDefinition serviceDefinition = null; |
ohair@286 | 106 | |
ohair@286 | 107 | public final HttpAdapterList<? extends HttpAdapter> owner; |
ohair@286 | 108 | |
ohair@286 | 109 | /** |
ohair@286 | 110 | * Servlet URL pattern with which this {@link HttpAdapter} is associated. |
ohair@286 | 111 | */ |
ohair@286 | 112 | public final String urlPattern; |
ohair@286 | 113 | |
ohair@286 | 114 | protected boolean stickyCookie; |
ohair@286 | 115 | |
ohair@286 | 116 | protected boolean disableJreplicaCookie = false; |
ohair@286 | 117 | |
ohair@286 | 118 | /** |
ohair@286 | 119 | * Creates a lone {@link HttpAdapter} that does not know of any other |
ohair@286 | 120 | * {@link HttpAdapter}s. |
ohair@286 | 121 | * |
ohair@286 | 122 | * This is convenient for creating an {@link HttpAdapter} for an environment |
ohair@286 | 123 | * where they don't know each other (such as JavaSE deployment.) |
ohair@286 | 124 | * |
ohair@286 | 125 | * @param endpoint web service endpoint |
ohair@286 | 126 | * @return singe adapter to process HTTP messages |
ohair@286 | 127 | */ |
ohair@286 | 128 | public static HttpAdapter createAlone(WSEndpoint endpoint) { |
ohair@286 | 129 | return new DummyList().createAdapter("","",endpoint); |
ohair@286 | 130 | } |
ohair@286 | 131 | |
ohair@286 | 132 | /** |
ohair@286 | 133 | * @deprecated |
ohair@286 | 134 | * remove as soon as we can update the test util. |
ohair@286 | 135 | * @param endpoint web service endpoint |
ohair@286 | 136 | * @param owner list of related adapters |
ohair@286 | 137 | */ |
ohair@286 | 138 | protected HttpAdapter(WSEndpoint endpoint, HttpAdapterList<? extends HttpAdapter> owner) { |
ohair@286 | 139 | this(endpoint,owner,null); |
ohair@286 | 140 | } |
ohair@286 | 141 | |
ohair@286 | 142 | protected HttpAdapter(WSEndpoint endpoint, HttpAdapterList<? extends HttpAdapter> owner, String urlPattern) { |
ohair@286 | 143 | super(endpoint); |
ohair@286 | 144 | this.owner = owner; |
ohair@286 | 145 | this.urlPattern = urlPattern; |
ohair@286 | 146 | |
ohair@286 | 147 | initWSDLMap(endpoint.getServiceDefinition()); |
ohair@286 | 148 | } |
ohair@286 | 149 | |
ohair@286 | 150 | /** |
ohair@286 | 151 | * Return the last known service definition of the endpoint. |
ohair@286 | 152 | * |
ohair@286 | 153 | * @return The service definition of the endpoint |
ohair@286 | 154 | */ |
ohair@286 | 155 | public ServiceDefinition getServiceDefinition() { |
ohair@286 | 156 | return this.serviceDefinition; |
ohair@286 | 157 | } |
ohair@286 | 158 | |
ohair@286 | 159 | /** |
ohair@286 | 160 | * Fill in WSDL map. |
ohair@286 | 161 | * |
ohair@286 | 162 | * @param sdef service definition |
ohair@286 | 163 | */ |
ohair@286 | 164 | public void initWSDLMap(ServiceDefinition sdef) { |
ohair@286 | 165 | this.serviceDefinition = sdef; |
ohair@286 | 166 | if(sdef==null) { |
ohair@286 | 167 | wsdls = Collections.emptyMap(); |
ohair@286 | 168 | revWsdls = Collections.emptyMap(); |
ohair@286 | 169 | } else { |
ohair@286 | 170 | wsdls = new HashMap<String, SDDocument>(); // wsdl=1 --> Doc |
ohair@286 | 171 | // Sort WSDL, Schema documents based on SystemId so that the same |
ohair@286 | 172 | // document gets wsdl=x mapping |
ohair@286 | 173 | Map<String, SDDocument> systemIds = new TreeMap<String, SDDocument>(); |
ohair@286 | 174 | for (SDDocument sdd : sdef) { |
ohair@286 | 175 | if (sdd == sdef.getPrimary()) { // No sorting for Primary WSDL |
ohair@286 | 176 | wsdls.put("wsdl", sdd); |
ohair@286 | 177 | wsdls.put("WSDL", sdd); |
ohair@286 | 178 | } else { |
ohair@286 | 179 | systemIds.put(sdd.getURL().toString(), sdd); |
ohair@286 | 180 | } |
ohair@286 | 181 | } |
ohair@286 | 182 | |
ohair@286 | 183 | int wsdlnum = 1; |
ohair@286 | 184 | int xsdnum = 1; |
ohair@286 | 185 | for (Map.Entry<String, SDDocument> e : systemIds.entrySet()) { |
ohair@286 | 186 | SDDocument sdd = e.getValue(); |
ohair@286 | 187 | if (sdd.isWSDL()) { |
ohair@286 | 188 | wsdls.put("wsdl="+(wsdlnum++),sdd); |
ohair@286 | 189 | } |
ohair@286 | 190 | if (sdd.isSchema()) { |
ohair@286 | 191 | wsdls.put("xsd="+(xsdnum++),sdd); |
ohair@286 | 192 | } |
ohair@286 | 193 | } |
ohair@286 | 194 | |
ohair@286 | 195 | revWsdls = new HashMap<SDDocument,String>(); // Doc --> wsdl=1 |
ohair@286 | 196 | for (Entry<String,SDDocument> e : wsdls.entrySet()) { |
ohair@286 | 197 | if (!e.getKey().equals("WSDL")) { // map Doc --> wsdl, not WSDL |
ohair@286 | 198 | revWsdls.put(e.getValue(),e.getKey()); |
ohair@286 | 199 | } |
ohair@286 | 200 | } |
ohair@286 | 201 | } |
ohair@286 | 202 | } |
ohair@286 | 203 | |
ohair@286 | 204 | /** |
ohair@286 | 205 | * Returns the "/abc/def/ghi" portion if |
ohair@286 | 206 | * the URL pattern is "/abc/def/ghi/*". |
ohair@286 | 207 | */ |
ohair@286 | 208 | public String getValidPath() { |
ohair@286 | 209 | if (urlPattern.endsWith("/*")) { |
ohair@286 | 210 | return urlPattern.substring(0, urlPattern.length() - 2); |
ohair@286 | 211 | } else { |
ohair@286 | 212 | return urlPattern; |
ohair@286 | 213 | } |
ohair@286 | 214 | } |
ohair@286 | 215 | |
ohair@286 | 216 | protected HttpToolkit createToolkit() { |
ohair@286 | 217 | return new HttpToolkit(); |
ohair@286 | 218 | } |
ohair@286 | 219 | |
ohair@286 | 220 | /** |
ohair@286 | 221 | * Receives the incoming HTTP connection and dispatches |
ohair@286 | 222 | * it to JAX-WS. This method returns when JAX-WS completes |
ohair@286 | 223 | * processing the request and the whole reply is written |
ohair@286 | 224 | * to {@link WSHTTPConnection}. |
ohair@286 | 225 | * |
ohair@286 | 226 | * <p> |
ohair@286 | 227 | * This method is invoked by the lower-level HTTP stack, |
ohair@286 | 228 | * and "connection" here is an HTTP connection. |
ohair@286 | 229 | * |
ohair@286 | 230 | * <p> |
ohair@286 | 231 | * To populate a request {@link Packet} with more info, |
ohair@286 | 232 | * define {@link PropertySet.Property properties} on |
ohair@286 | 233 | * {@link WSHTTPConnection}. |
ohair@286 | 234 | * |
ohair@286 | 235 | * @param connection to receive/send HTTP messages for web service endpoints |
ohair@286 | 236 | * @throws IOException when I/O errors happen |
ohair@286 | 237 | */ |
ohair@286 | 238 | public void handle(@NotNull WSHTTPConnection connection) throws IOException { |
ohair@286 | 239 | if (handleGet(connection)) { |
ohair@286 | 240 | return; |
ohair@286 | 241 | } |
ohair@286 | 242 | |
ohair@286 | 243 | // Make sure the Toolkit is recycled by the same pool instance from which it was taken |
ohair@286 | 244 | final Pool<HttpToolkit> currentPool = getPool(); |
ohair@286 | 245 | // normal request handling |
ohair@286 | 246 | final HttpToolkit tk = currentPool.take(); |
ohair@286 | 247 | try { |
ohair@286 | 248 | tk.handle(connection); |
ohair@286 | 249 | } finally { |
ohair@286 | 250 | currentPool.recycle(tk); |
ohair@286 | 251 | } |
ohair@286 | 252 | } |
ohair@286 | 253 | |
ohair@286 | 254 | public boolean handleGet(@NotNull WSHTTPConnection connection) throws IOException { |
ohair@286 | 255 | if (connection.getRequestMethod().equals("GET")) { |
ohair@286 | 256 | // metadata query. let the interceptor run |
ohair@286 | 257 | for (Component c : endpoint.getComponents()) { |
ohair@286 | 258 | HttpMetadataPublisher spi = c.getSPI(HttpMetadataPublisher.class); |
ohair@286 | 259 | if (spi != null && spi.handleMetadataRequest(this, connection)) |
ohair@286 | 260 | return true; // handled |
ohair@286 | 261 | } |
ohair@286 | 262 | |
ohair@286 | 263 | if (isMetadataQuery(connection.getQueryString())) { |
ohair@286 | 264 | // Sends published WSDL and schema documents as the default action. |
ohair@286 | 265 | publishWSDL(connection); |
ohair@286 | 266 | return true; |
ohair@286 | 267 | } |
ohair@286 | 268 | |
ohair@286 | 269 | Binding binding = getEndpoint().getBinding(); |
ohair@286 | 270 | if (!(binding instanceof HTTPBinding)) { |
ohair@286 | 271 | // Writes HTML page with all the endpoint descriptions |
ohair@286 | 272 | writeWebServicesHtmlPage(connection); |
ohair@286 | 273 | return true; |
ohair@286 | 274 | } |
ohair@286 | 275 | } else if (connection.getRequestMethod().equals("HEAD")) { |
ohair@286 | 276 | connection.getInput().close(); |
ohair@286 | 277 | Binding binding = getEndpoint().getBinding(); |
ohair@286 | 278 | if (isMetadataQuery(connection.getQueryString())) { |
ohair@286 | 279 | SDDocument doc = wsdls.get(connection.getQueryString()); |
ohair@286 | 280 | connection.setStatus(doc != null |
ohair@286 | 281 | ? HttpURLConnection.HTTP_OK |
ohair@286 | 282 | : HttpURLConnection.HTTP_NOT_FOUND); |
ohair@286 | 283 | connection.getOutput().close(); |
ohair@286 | 284 | connection.close(); |
ohair@286 | 285 | return true; |
ohair@286 | 286 | } else if (!(binding instanceof HTTPBinding)) { |
ohair@286 | 287 | connection.setStatus(HttpURLConnection.HTTP_NOT_FOUND); |
ohair@286 | 288 | connection.getOutput().close(); |
ohair@286 | 289 | connection.close(); |
ohair@286 | 290 | return true; |
ohair@286 | 291 | } |
ohair@286 | 292 | // Let the endpoint handle for HTTPBinding |
ohair@286 | 293 | } |
ohair@286 | 294 | |
ohair@286 | 295 | return false; |
ohair@286 | 296 | |
ohair@286 | 297 | } |
ohair@286 | 298 | /* |
ohair@286 | 299 | * |
ohair@286 | 300 | * @param con |
ohair@286 | 301 | * @param codec |
ohair@286 | 302 | * @return |
ohair@286 | 303 | * @throws IOException |
ohair@286 | 304 | * ExceptionHasMessage exception that contains particular fault message |
ohair@286 | 305 | * UnsupportedMediaException to indicate to send 415 error code |
ohair@286 | 306 | */ |
ohair@286 | 307 | private Packet decodePacket(@NotNull WSHTTPConnection con, @NotNull Codec codec) throws IOException { |
ohair@286 | 308 | String ct = con.getRequestHeader("Content-Type"); |
ohair@286 | 309 | InputStream in = con.getInput(); |
ohair@286 | 310 | Packet packet = new Packet(); |
ohair@286 | 311 | packet.soapAction = fixQuotesAroundSoapAction(con.getRequestHeader("SOAPAction")); |
ohair@286 | 312 | packet.wasTransportSecure = con.isSecure(); |
ohair@286 | 313 | packet.acceptableMimeTypes = con.getRequestHeader("Accept"); |
ohair@286 | 314 | packet.addSatellite(con); |
ohair@286 | 315 | addSatellites(packet); |
ohair@286 | 316 | packet.isAdapterDeliversNonAnonymousResponse = true; |
ohair@286 | 317 | packet.component = this; |
ohair@286 | 318 | packet.transportBackChannel = new Oneway(con); |
ohair@286 | 319 | packet.webServiceContextDelegate = con.getWebServiceContextDelegate(); |
ohair@286 | 320 | |
ohair@286 | 321 | if (dump || LOGGER.isLoggable(Level.FINER)) { |
ohair@286 | 322 | ByteArrayBuffer buf = new ByteArrayBuffer(); |
ohair@286 | 323 | buf.write(in); |
ohair@286 | 324 | in.close(); |
ohair@286 | 325 | dump(buf, "HTTP request", con.getRequestHeaders()); |
ohair@286 | 326 | in = buf.newInputStream(); |
ohair@286 | 327 | } |
ohair@286 | 328 | codec.decode(in, ct, packet); |
ohair@286 | 329 | return packet; |
ohair@286 | 330 | } |
ohair@286 | 331 | |
ohair@286 | 332 | protected void addSatellites(Packet packet) { |
ohair@286 | 333 | } |
ohair@286 | 334 | |
ohair@286 | 335 | /** |
ohair@286 | 336 | * Some stacks may send non WS-I BP 1.2 conformant SoapAction. |
ohair@286 | 337 | * Make sure SOAPAction is quoted as {@link Packet#soapAction} expectsa quoted soapAction value. |
ohair@286 | 338 | * |
ohair@286 | 339 | * @param soapAction SoapAction HTTP Header |
ohair@286 | 340 | * @return quoted SOAPAction value |
ohair@286 | 341 | */ |
ohair@286 | 342 | private String fixQuotesAroundSoapAction(String soapAction) { |
ohair@286 | 343 | if(soapAction != null && (!soapAction.startsWith("\"") || !soapAction.endsWith("\"")) ) { |
ohair@286 | 344 | LOGGER.info("Received WS-I BP non-conformant Unquoted SoapAction HTTP header: "+ soapAction); |
ohair@286 | 345 | String fixedSoapAction = soapAction; |
ohair@286 | 346 | if(!soapAction.startsWith("\"")) |
ohair@286 | 347 | fixedSoapAction = "\"" + fixedSoapAction; |
ohair@286 | 348 | if(!soapAction.endsWith("\"")) |
ohair@286 | 349 | fixedSoapAction = fixedSoapAction + "\""; |
ohair@286 | 350 | return fixedSoapAction; |
ohair@286 | 351 | } |
ohair@286 | 352 | return soapAction; |
ohair@286 | 353 | } |
ohair@286 | 354 | |
ohair@286 | 355 | protected NonAnonymousResponseProcessor getNonAnonymousResponseProcessor() { |
ohair@286 | 356 | return NonAnonymousResponseProcessor.getDefault(); |
ohair@286 | 357 | } |
ohair@286 | 358 | |
ohair@286 | 359 | private void encodePacket(@NotNull Packet packet, @NotNull WSHTTPConnection con, @NotNull Codec codec) throws IOException { |
ohair@286 | 360 | if (packet.endpointAddress != null) { |
ohair@286 | 361 | // Message is targeted to non-anonymous response endpoint. |
ohair@286 | 362 | // After call to non-anonymous processor, typically, packet.getMessage() will be null |
ohair@286 | 363 | // however, processors could use this pattern to modify the response sent on the back-channel, |
ohair@286 | 364 | // e.g. send custom HTTP headers with the HTTP 202 |
ohair@286 | 365 | packet = getNonAnonymousResponseProcessor().process(packet); |
ohair@286 | 366 | } |
ohair@286 | 367 | |
ohair@286 | 368 | if (con.isClosed()) { |
ohair@286 | 369 | return; // Connection is already closed |
ohair@286 | 370 | } |
ohair@286 | 371 | Message responseMessage = packet.getMessage(); |
ohair@286 | 372 | addStickyCookie(con); |
ohair@286 | 373 | addReplicaCookie(con, packet); |
ohair@286 | 374 | if (responseMessage == null) { |
ohair@286 | 375 | if (!con.isClosed()) { |
ohair@286 | 376 | // set the response code if not already set |
ohair@286 | 377 | // for example, 415 may have been set earlier for Unsupported Content-Type |
ohair@286 | 378 | if (con.getStatus() == 0) |
ohair@286 | 379 | con.setStatus(WSHTTPConnection.ONEWAY); |
ohair@286 | 380 | // close the response channel now |
ohair@286 | 381 | try { |
ohair@286 | 382 | con.getOutput().close(); // no payload |
ohair@286 | 383 | } catch (IOException e) { |
ohair@286 | 384 | throw new WebServiceException(e); |
ohair@286 | 385 | } |
ohair@286 | 386 | } |
ohair@286 | 387 | } else { |
ohair@286 | 388 | if (con.getStatus() == 0) { |
ohair@286 | 389 | // if the appliation didn't set the status code, |
ohair@286 | 390 | // set the default one. |
ohair@286 | 391 | con.setStatus(responseMessage.isFault() |
ohair@286 | 392 | ? HttpURLConnection.HTTP_INTERNAL_ERROR |
ohair@286 | 393 | : HttpURLConnection.HTTP_OK); |
ohair@286 | 394 | } |
ohair@286 | 395 | |
ohair@286 | 396 | ContentType contentType = codec.getStaticContentType(packet); |
ohair@286 | 397 | if (contentType != null) { |
ohair@286 | 398 | con.setContentTypeResponseHeader(contentType.getContentType()); |
ohair@286 | 399 | OutputStream os = con.getProtocol().contains("1.1") ? con.getOutput() : new Http10OutputStream(con); |
ohair@286 | 400 | if (dump || LOGGER.isLoggable(Level.FINER)) { |
ohair@286 | 401 | ByteArrayBuffer buf = new ByteArrayBuffer(); |
ohair@286 | 402 | codec.encode(packet, buf); |
ohair@286 | 403 | dump(buf, "HTTP response " + con.getStatus(), con.getResponseHeaders()); |
ohair@286 | 404 | buf.writeTo(os); |
ohair@286 | 405 | } else { |
ohair@286 | 406 | codec.encode(packet, os); |
ohair@286 | 407 | } |
ohair@286 | 408 | os.close(); |
ohair@286 | 409 | } else { |
ohair@286 | 410 | |
ohair@286 | 411 | ByteArrayBuffer buf = new ByteArrayBuffer(); |
ohair@286 | 412 | contentType = codec.encode(packet, buf); |
ohair@286 | 413 | con.setContentTypeResponseHeader(contentType.getContentType()); |
ohair@286 | 414 | if (dump || LOGGER.isLoggable(Level.FINER)) { |
ohair@286 | 415 | dump(buf, "HTTP response " + con.getStatus(), con.getResponseHeaders()); |
ohair@286 | 416 | } |
ohair@286 | 417 | OutputStream os = con.getOutput(); |
ohair@286 | 418 | buf.writeTo(os); |
ohair@286 | 419 | os.close(); |
ohair@286 | 420 | } |
ohair@286 | 421 | } |
ohair@286 | 422 | } |
ohair@286 | 423 | |
ohair@286 | 424 | /* |
ohair@286 | 425 | * GlassFish Load-balancer plugin always add a header proxy-jroute on |
ohair@286 | 426 | * request being send from load-balancer plugin to server |
ohair@286 | 427 | * |
ohair@286 | 428 | * JROUTE cookie need to be stamped in two cases |
ohair@286 | 429 | * 1 : At the time of session creation. In this case, request will not have |
ohair@286 | 430 | * any JROUTE cookie. |
ohair@286 | 431 | * 2 : At the time of fail-over. In this case, value of proxy-jroute |
ohair@286 | 432 | * header(will point to current instance) and JROUTE cookie(will point to |
ohair@286 | 433 | * previous failed instance) will be different. This logic can be used |
ohair@286 | 434 | * to determine fail-over scenario. |
ohair@286 | 435 | */ |
ohair@286 | 436 | private void addStickyCookie(WSHTTPConnection con) { |
ohair@286 | 437 | if (stickyCookie) { |
ohair@286 | 438 | String proxyJroute = con.getRequestHeader("proxy-jroute"); |
ohair@286 | 439 | if (proxyJroute == null) { |
ohair@286 | 440 | // Load-balancer plugin is not front-ending this instance |
ohair@286 | 441 | return; |
ohair@286 | 442 | } |
ohair@286 | 443 | |
ohair@286 | 444 | String jrouteId = con.getCookie("JROUTE"); |
ohair@286 | 445 | if (jrouteId == null || !jrouteId.equals(proxyJroute)) { |
ohair@286 | 446 | // Initial request or failover |
ohair@286 | 447 | con.setCookie("JROUTE", proxyJroute); |
ohair@286 | 448 | } |
ohair@286 | 449 | } |
ohair@286 | 450 | } |
ohair@286 | 451 | |
ohair@286 | 452 | private void addReplicaCookie(WSHTTPConnection con, Packet packet) { |
ohair@286 | 453 | if (stickyCookie) { |
ohair@286 | 454 | HaInfo haInfo = null; |
ohair@286 | 455 | if (packet.supports(Packet.HA_INFO)) { |
ohair@286 | 456 | haInfo = (HaInfo)packet.get(Packet.HA_INFO); |
ohair@286 | 457 | } |
ohair@286 | 458 | if (haInfo != null) { |
ohair@286 | 459 | con.setCookie("METRO_KEY", haInfo.getKey()); |
ohair@286 | 460 | if (!disableJreplicaCookie) { |
ohair@286 | 461 | con.setCookie("JREPLICA", haInfo.getReplicaInstance()); |
ohair@286 | 462 | } |
ohair@286 | 463 | } |
ohair@286 | 464 | } |
ohair@286 | 465 | } |
ohair@286 | 466 | |
ohair@286 | 467 | public void invokeAsync(final WSHTTPConnection con) throws IOException { |
ohair@286 | 468 | invokeAsync(con, NO_OP_COMPLETION_CALLBACK); |
ohair@286 | 469 | } |
ohair@286 | 470 | |
ohair@286 | 471 | public void invokeAsync(final WSHTTPConnection con, final CompletionCallback callback) throws IOException { |
ohair@286 | 472 | |
ohair@286 | 473 | if (handleGet(con)) { |
ohair@286 | 474 | callback.onCompletion(); |
ohair@286 | 475 | return; |
ohair@286 | 476 | } |
ohair@286 | 477 | final Pool<HttpToolkit> currentPool = getPool(); |
ohair@286 | 478 | final HttpToolkit tk = currentPool.take(); |
ohair@286 | 479 | final Packet request; |
ohair@286 | 480 | |
ohair@286 | 481 | try { |
ohair@286 | 482 | |
ohair@286 | 483 | request = decodePacket(con, tk.codec); |
ohair@286 | 484 | } catch (ExceptionHasMessage e) { |
ohair@286 | 485 | LOGGER.log(Level.SEVERE, e.getMessage(), e); |
ohair@286 | 486 | Packet response = new Packet(); |
ohair@286 | 487 | response.setMessage(e.getFaultMessage()); |
ohair@286 | 488 | encodePacket(response, con, tk.codec); |
ohair@286 | 489 | currentPool.recycle(tk); |
ohair@286 | 490 | con.close(); |
ohair@286 | 491 | callback.onCompletion(); |
ohair@286 | 492 | return; |
ohair@286 | 493 | } catch (UnsupportedMediaException e) { |
ohair@286 | 494 | LOGGER.log(Level.SEVERE, e.getMessage(), e); |
ohair@286 | 495 | Packet response = new Packet(); |
ohair@286 | 496 | con.setStatus(WSHTTPConnection.UNSUPPORTED_MEDIA); |
ohair@286 | 497 | encodePacket(response, con, tk.codec); |
ohair@286 | 498 | currentPool.recycle(tk); |
ohair@286 | 499 | con.close(); |
ohair@286 | 500 | callback.onCompletion(); |
ohair@286 | 501 | return; |
ohair@286 | 502 | } |
ohair@286 | 503 | |
ohair@286 | 504 | endpoint.process(request, new WSEndpoint.CompletionCallback() { |
ohair@286 | 505 | public void onCompletion(@NotNull Packet response) { |
ohair@286 | 506 | try { |
ohair@286 | 507 | try { |
ohair@286 | 508 | encodePacket(response, con, tk.codec); |
ohair@286 | 509 | } catch (IOException ioe) { |
ohair@286 | 510 | LOGGER.log(Level.SEVERE, ioe.getMessage(), ioe); |
ohair@286 | 511 | } |
ohair@286 | 512 | currentPool.recycle(tk); |
ohair@286 | 513 | } finally { |
ohair@286 | 514 | con.close(); |
ohair@286 | 515 | callback.onCompletion(); |
ohair@286 | 516 | |
ohair@286 | 517 | } |
ohair@286 | 518 | } |
ohair@286 | 519 | },null); |
ohair@286 | 520 | |
ohair@286 | 521 | } |
ohair@286 | 522 | |
ohair@286 | 523 | public static final CompletionCallback NO_OP_COMPLETION_CALLBACK = new CompletionCallback() { |
ohair@286 | 524 | |
ohair@286 | 525 | public void onCompletion() { |
ohair@286 | 526 | //NO-OP |
ohair@286 | 527 | } |
ohair@286 | 528 | }; |
ohair@286 | 529 | |
ohair@286 | 530 | public interface CompletionCallback{ |
ohair@286 | 531 | void onCompletion(); |
ohair@286 | 532 | } |
ohair@286 | 533 | |
ohair@286 | 534 | final class AsyncTransport extends AbstractServerAsyncTransport<WSHTTPConnection> { |
ohair@286 | 535 | |
ohair@286 | 536 | public AsyncTransport() { |
ohair@286 | 537 | super(endpoint); |
ohair@286 | 538 | } |
ohair@286 | 539 | |
ohair@286 | 540 | public void handleAsync(WSHTTPConnection con) throws IOException { |
ohair@286 | 541 | super.handle(con); |
ohair@286 | 542 | } |
ohair@286 | 543 | |
ohair@286 | 544 | protected void encodePacket(WSHTTPConnection con, @NotNull Packet packet, @NotNull Codec codec) throws IOException { |
ohair@286 | 545 | HttpAdapter.this.encodePacket(packet, con, codec); |
ohair@286 | 546 | } |
ohair@286 | 547 | |
ohair@286 | 548 | protected @Nullable String getAcceptableMimeTypes(WSHTTPConnection con) { |
ohair@286 | 549 | return null; |
ohair@286 | 550 | } |
ohair@286 | 551 | |
ohair@286 | 552 | protected @Nullable TransportBackChannel getTransportBackChannel(WSHTTPConnection con) { |
ohair@286 | 553 | return new Oneway(con); |
ohair@286 | 554 | } |
ohair@286 | 555 | |
ohair@286 | 556 | protected @NotNull |
ohair@286 | 557 | PropertySet getPropertySet(WSHTTPConnection con) { |
ohair@286 | 558 | return con; |
ohair@286 | 559 | } |
ohair@286 | 560 | |
ohair@286 | 561 | protected @NotNull WebServiceContextDelegate getWebServiceContextDelegate(WSHTTPConnection con) { |
ohair@286 | 562 | return con.getWebServiceContextDelegate(); |
ohair@286 | 563 | } |
ohair@286 | 564 | } |
ohair@286 | 565 | |
ohair@286 | 566 | final class Oneway implements TransportBackChannel { |
ohair@286 | 567 | WSHTTPConnection con; |
ohair@286 | 568 | boolean closed; |
ohair@286 | 569 | |
ohair@286 | 570 | Oneway(WSHTTPConnection con) { |
ohair@286 | 571 | this.con = con; |
ohair@286 | 572 | } |
ohair@286 | 573 | public void close() { |
ohair@286 | 574 | if (!closed) { |
ohair@286 | 575 | closed = true; |
ohair@286 | 576 | // close the response channel now |
ohair@286 | 577 | if (con.getStatus() == 0) { |
ohair@286 | 578 | // if the appliation didn't set the status code, |
ohair@286 | 579 | // set the default one. |
ohair@286 | 580 | con.setStatus(WSHTTPConnection.ONEWAY); |
ohair@286 | 581 | } |
ohair@286 | 582 | |
ohair@286 | 583 | OutputStream output = null; |
ohair@286 | 584 | try { |
ohair@286 | 585 | output = con.getOutput(); |
ohair@286 | 586 | } catch (IOException e) { |
ohair@286 | 587 | // no-op |
ohair@286 | 588 | } |
ohair@286 | 589 | |
ohair@286 | 590 | if (output != null) { |
ohair@286 | 591 | try { |
ohair@286 | 592 | output.close(); // no payload |
ohair@286 | 593 | } catch (IOException e) { |
ohair@286 | 594 | throw new WebServiceException(e); |
ohair@286 | 595 | } |
ohair@286 | 596 | } |
ohair@286 | 597 | con.close(); |
ohair@286 | 598 | } |
ohair@286 | 599 | } |
ohair@286 | 600 | } |
ohair@286 | 601 | |
ohair@286 | 602 | final class HttpToolkit extends Adapter.Toolkit { |
ohair@286 | 603 | public void handle(WSHTTPConnection con) throws IOException { |
ohair@286 | 604 | try { |
ohair@286 | 605 | boolean invoke = false; |
ohair@286 | 606 | Packet packet; |
ohair@286 | 607 | try { |
ohair@286 | 608 | packet = decodePacket(con, codec); |
ohair@286 | 609 | invoke = true; |
ohair@286 | 610 | } catch(Exception e) { |
ohair@286 | 611 | packet = new Packet(); |
ohair@286 | 612 | if (e instanceof ExceptionHasMessage) { |
ohair@286 | 613 | LOGGER.log(Level.SEVERE, e.getMessage(), e); |
ohair@286 | 614 | packet.setMessage(((ExceptionHasMessage)e).getFaultMessage()); |
ohair@286 | 615 | } else if (e instanceof UnsupportedMediaException) { |
ohair@286 | 616 | LOGGER.log(Level.SEVERE, e.getMessage(), e); |
ohair@286 | 617 | con.setStatus(WSHTTPConnection.UNSUPPORTED_MEDIA); |
ohair@286 | 618 | } else { |
ohair@286 | 619 | LOGGER.log(Level.SEVERE, e.getMessage(), e); |
ohair@286 | 620 | con.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR); |
ohair@286 | 621 | } |
ohair@286 | 622 | } |
ohair@286 | 623 | if (invoke) { |
ohair@286 | 624 | try { |
ohair@286 | 625 | packet = head.process(packet, con.getWebServiceContextDelegate(), |
ohair@286 | 626 | packet.transportBackChannel); |
ohair@286 | 627 | } catch(Exception e) { |
ohair@286 | 628 | LOGGER.log(Level.SEVERE, e.getMessage(), e); |
ohair@286 | 629 | if (!con.isClosed()) { |
ohair@286 | 630 | writeInternalServerError(con); |
ohair@286 | 631 | } |
ohair@286 | 632 | return; |
ohair@286 | 633 | } |
ohair@286 | 634 | } |
ohair@286 | 635 | encodePacket(packet, con, codec); |
ohair@286 | 636 | } finally { |
ohair@286 | 637 | if (!con.isClosed()) { |
ohair@286 | 638 | con.close(); |
ohair@286 | 639 | } |
ohair@286 | 640 | } |
ohair@286 | 641 | } |
ohair@286 | 642 | } |
ohair@286 | 643 | |
ohair@286 | 644 | /** |
ohair@286 | 645 | * Returns true if the given query string is for metadata request. |
ohair@286 | 646 | * |
ohair@286 | 647 | * @param query |
ohair@286 | 648 | * String like "xsd=1" or "perhaps=some&unrelated=query". |
ohair@286 | 649 | * Can be null. |
ohair@286 | 650 | * @return true for metadata requests |
ohair@286 | 651 | * false for web service requests |
ohair@286 | 652 | */ |
ohair@286 | 653 | private boolean isMetadataQuery(String query) { |
ohair@286 | 654 | // we intentionally return true even if documents don't exist, |
ohair@286 | 655 | // so that they get 404. |
ohair@286 | 656 | return query != null && (query.equals("WSDL") || query.startsWith("wsdl") || query.startsWith("xsd=")); |
ohair@286 | 657 | } |
ohair@286 | 658 | |
ohair@286 | 659 | /** |
ohair@286 | 660 | * Sends out the WSDL (and other referenced documents) |
ohair@286 | 661 | * in response to the GET requests to URLs like "?wsdl" or "?xsd=2". |
ohair@286 | 662 | * |
ohair@286 | 663 | * @param con |
ohair@286 | 664 | * The connection to which the data will be sent. |
ohair@286 | 665 | * |
ohair@286 | 666 | * @throws IOException when I/O errors happen |
ohair@286 | 667 | */ |
ohair@286 | 668 | public void publishWSDL(@NotNull WSHTTPConnection con) throws IOException { |
ohair@286 | 669 | con.getInput().close(); |
ohair@286 | 670 | |
ohair@286 | 671 | SDDocument doc = wsdls.get(con.getQueryString()); |
ohair@286 | 672 | if (doc == null) { |
ohair@286 | 673 | writeNotFoundErrorPage(con,"Invalid Request"); |
ohair@286 | 674 | return; |
ohair@286 | 675 | } |
ohair@286 | 676 | |
ohair@286 | 677 | con.setStatus(HttpURLConnection.HTTP_OK); |
ohair@286 | 678 | con.setContentTypeResponseHeader("text/xml;charset=utf-8"); |
ohair@286 | 679 | |
ohair@286 | 680 | OutputStream os = con.getProtocol().contains("1.1") ? con.getOutput() : new Http10OutputStream(con); |
ohair@286 | 681 | |
ohair@286 | 682 | PortAddressResolver portAddressResolver = getPortAddressResolver(con.getBaseAddress()); |
ohair@286 | 683 | DocumentAddressResolver resolver = getDocumentAddressResolver(portAddressResolver); |
ohair@286 | 684 | |
ohair@286 | 685 | doc.writeTo(portAddressResolver, resolver, os); |
ohair@286 | 686 | os.close(); |
ohair@286 | 687 | } |
ohair@286 | 688 | |
ohair@286 | 689 | public PortAddressResolver getPortAddressResolver(String baseAddress) { |
ohair@286 | 690 | return owner.createPortAddressResolver(baseAddress); |
ohair@286 | 691 | } |
ohair@286 | 692 | |
ohair@286 | 693 | public DocumentAddressResolver getDocumentAddressResolver( |
ohair@286 | 694 | PortAddressResolver portAddressResolver) { |
ohair@286 | 695 | final String address = portAddressResolver.getAddressFor(endpoint.getServiceName(), endpoint.getPortName().getLocalPart()); |
ohair@286 | 696 | assert address != null; |
ohair@286 | 697 | return new DocumentAddressResolver() { |
ohair@286 | 698 | public String getRelativeAddressFor(@NotNull SDDocument current, @NotNull SDDocument referenced) { |
ohair@286 | 699 | // the map on endpoint should account for all SDDocument |
ohair@286 | 700 | assert revWsdls.containsKey(referenced); |
ohair@286 | 701 | return address+'?'+ revWsdls.get(referenced); |
ohair@286 | 702 | } |
ohair@286 | 703 | }; |
ohair@286 | 704 | } |
ohair@286 | 705 | |
ohair@286 | 706 | /** |
ohair@286 | 707 | * HTTP/1.0 connections require Content-Length. So just buffer to find out |
ohair@286 | 708 | * the length. |
ohair@286 | 709 | */ |
ohair@286 | 710 | private final static class Http10OutputStream extends ByteArrayBuffer { |
ohair@286 | 711 | private final WSHTTPConnection con; |
ohair@286 | 712 | |
ohair@286 | 713 | Http10OutputStream(WSHTTPConnection con) { |
ohair@286 | 714 | this.con = con; |
ohair@286 | 715 | } |
ohair@286 | 716 | |
ohair@286 | 717 | @Override |
ohair@286 | 718 | public void close() throws IOException { |
ohair@286 | 719 | super.close(); |
ohair@286 | 720 | con.setContentLengthResponseHeader(size()); |
ohair@286 | 721 | OutputStream os = con.getOutput(); |
ohair@286 | 722 | writeTo(os); |
ohair@286 | 723 | os.close(); |
ohair@286 | 724 | } |
ohair@286 | 725 | } |
ohair@286 | 726 | |
ohair@286 | 727 | private void writeNotFoundErrorPage(WSHTTPConnection con, String message) throws IOException { |
ohair@286 | 728 | con.setStatus(HttpURLConnection.HTTP_NOT_FOUND); |
ohair@286 | 729 | con.setContentTypeResponseHeader("text/html; charset=utf-8"); |
ohair@286 | 730 | |
ohair@286 | 731 | PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutput(),"UTF-8")); |
ohair@286 | 732 | out.println("<html>"); |
ohair@286 | 733 | out.println("<head><title>"); |
ohair@286 | 734 | out.println(WsservletMessages.SERVLET_HTML_TITLE()); |
ohair@286 | 735 | out.println("</title></head>"); |
ohair@286 | 736 | out.println("<body>"); |
ohair@286 | 737 | out.println(WsservletMessages.SERVLET_HTML_NOT_FOUND(message)); |
ohair@286 | 738 | out.println("</body>"); |
ohair@286 | 739 | out.println("</html>"); |
ohair@286 | 740 | out.close(); |
ohair@286 | 741 | } |
ohair@286 | 742 | |
ohair@286 | 743 | private void writeInternalServerError(WSHTTPConnection con) throws IOException { |
ohair@286 | 744 | con.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR); |
ohair@286 | 745 | con.getOutput().close(); // Sets the status code |
ohair@286 | 746 | } |
ohair@286 | 747 | |
ohair@286 | 748 | private static final class DummyList extends HttpAdapterList<HttpAdapter> { |
ohair@286 | 749 | @Override |
ohair@286 | 750 | protected HttpAdapter createHttpAdapter(String name, String urlPattern, WSEndpoint<?> endpoint) { |
ohair@286 | 751 | return new HttpAdapter(endpoint,this,urlPattern); |
ohair@286 | 752 | } |
ohair@286 | 753 | } |
ohair@286 | 754 | |
ohair@286 | 755 | private void dump(ByteArrayBuffer buf, String caption, Map<String, List<String>> headers) throws IOException { |
ohair@286 | 756 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
ohair@286 | 757 | PrintWriter pw = new PrintWriter(baos, true); |
ohair@286 | 758 | pw.println("---["+caption +"]---"); |
ohair@286 | 759 | if (headers != null) { |
ohair@286 | 760 | for (Entry<String, List<String>> header : headers.entrySet()) { |
ohair@286 | 761 | if (header.getValue().isEmpty()) { |
ohair@286 | 762 | // I don't think this is legal, but let's just dump it, |
ohair@286 | 763 | // as the point of the dump is to uncover problems. |
ohair@286 | 764 | pw.println(header.getValue()); |
ohair@286 | 765 | } else { |
ohair@286 | 766 | for (String value : header.getValue()) { |
ohair@286 | 767 | pw.println(header.getKey() + ": " + value); |
ohair@286 | 768 | } |
ohair@286 | 769 | } |
ohair@286 | 770 | } |
ohair@286 | 771 | } |
ohair@286 | 772 | buf.writeTo(baos); |
ohair@286 | 773 | pw.println("--------------------"); |
ohair@286 | 774 | |
ohair@286 | 775 | String msg = baos.toString(); |
ohair@286 | 776 | if (dump) { |
ohair@286 | 777 | System.out.println(msg); |
ohair@286 | 778 | } |
ohair@286 | 779 | if (LOGGER.isLoggable(Level.FINER)) { |
ohair@286 | 780 | LOGGER.log(Level.FINER, msg); |
ohair@286 | 781 | } |
ohair@286 | 782 | } |
ohair@286 | 783 | |
ohair@286 | 784 | /* |
ohair@286 | 785 | * Generates the listing of all services. |
ohair@286 | 786 | */ |
ohair@286 | 787 | private void writeWebServicesHtmlPage(WSHTTPConnection con) throws IOException { |
ohair@286 | 788 | if (!publishStatusPage) return; |
ohair@286 | 789 | |
ohair@286 | 790 | // TODO: resurrect the ability to localize according to the current request. |
ohair@286 | 791 | |
ohair@286 | 792 | con.getInput().close(); |
ohair@286 | 793 | |
ohair@286 | 794 | // standard browsable page |
ohair@286 | 795 | con.setStatus(WSHTTPConnection.OK); |
ohair@286 | 796 | con.setContentTypeResponseHeader("text/html; charset=utf-8"); |
ohair@286 | 797 | |
ohair@286 | 798 | PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutput(),"UTF-8")); |
ohair@286 | 799 | out.println("<html>"); |
ohair@286 | 800 | out.println("<head><title>"); |
ohair@286 | 801 | // out.println("Web Services"); |
ohair@286 | 802 | out.println(WsservletMessages.SERVLET_HTML_TITLE()); |
ohair@286 | 803 | out.println("</title></head>"); |
ohair@286 | 804 | out.println("<body>"); |
ohair@286 | 805 | // out.println("<h1>Web Services</h1>"); |
ohair@286 | 806 | out.println(WsservletMessages.SERVLET_HTML_TITLE_2()); |
ohair@286 | 807 | |
ohair@286 | 808 | // what endpoints do we have in this system? |
ohair@286 | 809 | Module module = getEndpoint().getContainer().getSPI(Module.class); |
ohair@286 | 810 | List<BoundEndpoint> endpoints = Collections.emptyList(); |
ohair@286 | 811 | if(module!=null) { |
ohair@286 | 812 | endpoints = module.getBoundEndpoints(); |
ohair@286 | 813 | } |
ohair@286 | 814 | |
ohair@286 | 815 | if (endpoints.isEmpty()) { |
ohair@286 | 816 | // out.println("<p>No JAX-WS context information available.</p>"); |
ohair@286 | 817 | out.println(WsservletMessages.SERVLET_HTML_NO_INFO_AVAILABLE()); |
ohair@286 | 818 | } else { |
ohair@286 | 819 | out.println("<table width='100%' border='1'>"); |
ohair@286 | 820 | out.println("<tr>"); |
ohair@286 | 821 | out.println("<td>"); |
ohair@286 | 822 | // out.println("Endpoint"); |
ohair@286 | 823 | out.println(WsservletMessages.SERVLET_HTML_COLUMN_HEADER_PORT_NAME()); |
ohair@286 | 824 | out.println("</td>"); |
ohair@286 | 825 | |
ohair@286 | 826 | out.println("<td>"); |
ohair@286 | 827 | // out.println("Information"); |
ohair@286 | 828 | out.println(WsservletMessages.SERVLET_HTML_COLUMN_HEADER_INFORMATION()); |
ohair@286 | 829 | out.println("</td>"); |
ohair@286 | 830 | out.println("</tr>"); |
ohair@286 | 831 | |
ohair@286 | 832 | for (BoundEndpoint a : endpoints) { |
ohair@286 | 833 | String endpointAddress = a.getAddress(con.getBaseAddress()).toString(); |
ohair@286 | 834 | out.println("<tr>"); |
ohair@286 | 835 | |
ohair@286 | 836 | out.println("<td>"); |
ohair@286 | 837 | out.println(WsservletMessages.SERVLET_HTML_ENDPOINT_TABLE( |
ohair@286 | 838 | a.getEndpoint().getServiceName(), |
ohair@286 | 839 | a.getEndpoint().getPortName() |
ohair@286 | 840 | )); |
ohair@286 | 841 | out.println("</td>"); |
ohair@286 | 842 | |
ohair@286 | 843 | out.println("<td>"); |
ohair@286 | 844 | out.println(WsservletMessages.SERVLET_HTML_INFORMATION_TABLE( |
ohair@286 | 845 | endpointAddress, |
ohair@286 | 846 | a.getEndpoint().getImplementationClass().getName() |
ohair@286 | 847 | )); |
ohair@286 | 848 | out.println("</td>"); |
ohair@286 | 849 | |
ohair@286 | 850 | out.println("</tr>"); |
ohair@286 | 851 | } |
ohair@286 | 852 | out.println("</table>"); |
ohair@286 | 853 | } |
ohair@286 | 854 | out.println("</body>"); |
ohair@286 | 855 | out.println("</html>"); |
ohair@286 | 856 | out.close(); |
ohair@286 | 857 | } |
ohair@286 | 858 | |
ohair@286 | 859 | /** |
ohair@286 | 860 | * Dumps what goes across HTTP transport. |
ohair@286 | 861 | */ |
ohair@286 | 862 | public static boolean dump = false; |
ohair@286 | 863 | |
ohair@286 | 864 | public static boolean publishStatusPage = true; |
ohair@286 | 865 | |
ohair@286 | 866 | static { |
ohair@286 | 867 | try { |
ohair@286 | 868 | dump = Boolean.getBoolean(HttpAdapter.class.getName()+".dump"); |
ohair@286 | 869 | } catch( Throwable t ) { |
ohair@286 | 870 | // OK to ignore this |
ohair@286 | 871 | } |
ohair@286 | 872 | try { |
ohair@286 | 873 | publishStatusPage = System.getProperty(HttpAdapter.class.getName()+".publishStatusPage").equals("true"); |
ohair@286 | 874 | } catch( Throwable t ) { |
ohair@286 | 875 | // OK to ignore this |
ohair@286 | 876 | } |
ohair@286 | 877 | } |
ohair@286 | 878 | |
ohair@286 | 879 | private static final Logger LOGGER = Logger.getLogger(HttpAdapter.class.getName()); |
ohair@286 | 880 | } |