src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/HttpAdapter.java

Fri, 04 Oct 2013 16:21:34 +0100

author
mkos
date
Fri, 04 Oct 2013 16:21:34 +0100
changeset 408
b0610cd08440
parent 384
8f2986ff0235
child 637
9c07ef4934dd
permissions
-rw-r--r--

8025054: Update JAX-WS RI integration to 2.2.9-b130926.1035
Reviewed-by: chegar

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

mercurial