feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
81
jdkSrc/jdk8/com/sun/xml/internal/ws/client/AsyncInvoker.java
Normal file
81
jdkSrc/jdk8/com/sun/xml/internal/ws/client/AsyncInvoker.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Fiber.CompletionCallback;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* Invokes {@link Tube}line asynchronously for the client's async API(for e.g.: Dispatch#invokeAsync}
|
||||
* The concrete classes need to call {@link Stub#processAsync(AsyncResponseImpl, Packet, RequestContext, Fiber.CompletionCallback) } in
|
||||
* run() method.
|
||||
*
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
public abstract class AsyncInvoker implements Runnable {
|
||||
/**
|
||||
* Because of the object instantiation order,
|
||||
* we can't take this as a constructor parameter.
|
||||
*/
|
||||
protected AsyncResponseImpl responseImpl;
|
||||
protected boolean nonNullAsyncHandlerGiven;
|
||||
|
||||
public void setReceiver(AsyncResponseImpl responseImpl) {
|
||||
this.responseImpl = responseImpl;
|
||||
}
|
||||
|
||||
public AsyncResponseImpl getResponseImpl() {
|
||||
return responseImpl;
|
||||
}
|
||||
|
||||
public void setResponseImpl(AsyncResponseImpl responseImpl) {
|
||||
this.responseImpl = responseImpl;
|
||||
}
|
||||
|
||||
public boolean isNonNullAsyncHandlerGiven() {
|
||||
return nonNullAsyncHandlerGiven;
|
||||
}
|
||||
|
||||
public void setNonNullAsyncHandlerGiven(boolean nonNullAsyncHandlerGiven) {
|
||||
this.nonNullAsyncHandlerGiven = nonNullAsyncHandlerGiven;
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
do_run();
|
||||
}catch(WebServiceException e) {
|
||||
throw e;
|
||||
}catch(Throwable t) {
|
||||
//Wrap it in WebServiceException
|
||||
throw new WebServiceException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void do_run();
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.ws.api.Cancelable;
|
||||
import com.sun.xml.internal.ws.util.CompletedFuture;
|
||||
|
||||
import javax.xml.ws.AsyncHandler;
|
||||
import javax.xml.ws.Response;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
/**
|
||||
* {@link Response} implementation. When Runnbale is executed, it just hands the
|
||||
* request to Fiber and returns. When the Fiber finishes the execution, it sets
|
||||
* response in the {@link FutureTask}
|
||||
*
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
public final class AsyncResponseImpl<T> extends FutureTask<T> implements Response<T>, ResponseContextReceiver {
|
||||
|
||||
/**
|
||||
* Optional {@link AsyncHandler} that gets invoked
|
||||
* at the completion of the task.
|
||||
*/
|
||||
private final AsyncHandler<T> handler;
|
||||
private ResponseContext responseContext;
|
||||
private final Runnable callable;
|
||||
private Cancelable cancelable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param runnable
|
||||
* This {@link Runnable} is executed asynchronously.
|
||||
* @param handler
|
||||
* Optional {@link AsyncHandler} to invoke at the end
|
||||
* of the processing. Can be null.
|
||||
*/
|
||||
public AsyncResponseImpl(Runnable runnable, @Nullable AsyncHandler<T> handler) {
|
||||
super(runnable, null);
|
||||
this.callable = runnable;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// override so that AsyncInvoker calls set()
|
||||
// when Fiber calls the callback
|
||||
try {
|
||||
callable.run();
|
||||
} catch (WebServiceException e) {
|
||||
//it could be a WebServiceException or a ProtocolException or any RuntimeException
|
||||
// resulting due to some internal bug.
|
||||
set(null, e);
|
||||
} catch (Throwable e) {
|
||||
//its some other exception resulting from user error, wrap it in
|
||||
// WebServiceException
|
||||
set(null, new WebServiceException(e));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ResponseContext getContext() {
|
||||
return responseContext;
|
||||
}
|
||||
|
||||
public void setResponseContext(ResponseContext rc) {
|
||||
responseContext = rc;
|
||||
}
|
||||
|
||||
public void set(final T v, final Throwable t) {
|
||||
// call the handler before we mark the future as 'done'
|
||||
if (handler!=null) {
|
||||
try {
|
||||
/**
|
||||
* {@link Response} object passed into the callback.
|
||||
* We need a separate {@link java.util.concurrent.Future} because we don't want {@link ResponseImpl}
|
||||
* to be marked as 'done' before the callback finishes execution.
|
||||
* (That would provide implicit synchronization between the application code
|
||||
* in the main thread and the callback code, and is compatible with the JAX-RI 2.0 FCS.
|
||||
*/
|
||||
class CallbackFuture<T> extends CompletedFuture<T> implements Response<T> {
|
||||
public CallbackFuture(T v, Throwable t) {
|
||||
super(v, t);
|
||||
}
|
||||
|
||||
public Map<String, Object> getContext() {
|
||||
return AsyncResponseImpl.this.getContext();
|
||||
}
|
||||
}
|
||||
handler.handleResponse(new CallbackFuture<T>(v, t));
|
||||
} catch (Throwable e) {
|
||||
super.setException(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (t != null) {
|
||||
super.setException(t);
|
||||
} else {
|
||||
super.set(v);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCancelable(Cancelable cancelable) {
|
||||
this.cancelable = cancelable;
|
||||
}
|
||||
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
if (cancelable != null)
|
||||
cancelable.cancel(mayInterruptIfRunning);
|
||||
return super.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.developer.JAXWSProperties;
|
||||
|
||||
public interface BindingProviderProperties extends JAXWSProperties{
|
||||
|
||||
//legacy properties
|
||||
@Deprecated
|
||||
public static final String HOSTNAME_VERIFICATION_PROPERTY =
|
||||
"com.sun.xml.internal.ws.client.http.HostnameVerificationProperty";
|
||||
public static final String HTTP_COOKIE_JAR =
|
||||
"com.sun.xml.internal.ws.client.http.CookieJar";
|
||||
|
||||
public static final String REDIRECT_REQUEST_PROPERTY =
|
||||
"com.sun.xml.internal.ws.client.http.RedirectRequestProperty";
|
||||
public static final String ONE_WAY_OPERATION =
|
||||
"com.sun.xml.internal.ws.server.OneWayOperation";
|
||||
|
||||
|
||||
//JAXWS 2.0
|
||||
public static final String JAXWS_HANDLER_CONFIG =
|
||||
"com.sun.xml.internal.ws.handler.config";
|
||||
public static final String JAXWS_CLIENT_HANDLE_PROPERTY =
|
||||
"com.sun.xml.internal.ws.client.handle";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.api.ResourceLoader;
|
||||
import com.sun.xml.internal.ws.api.server.Container;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
final class ClientContainer extends Container {
|
||||
|
||||
private final ResourceLoader loader = new ResourceLoader() {
|
||||
public URL getResource(String resource) throws MalformedURLException {
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
if (cl == null) {
|
||||
cl = this.getClass().getClassLoader();
|
||||
}
|
||||
return cl.getResource("META-INF/"+resource);
|
||||
}
|
||||
};
|
||||
|
||||
public <T> T getSPI(Class<T> spiType) {
|
||||
T t = super.getSPI(spiType);
|
||||
if (t != null)
|
||||
return t;
|
||||
if (spiType == ResourceLoader.class) {
|
||||
return spiType.cast(loader);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.api.WSBinding;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
|
||||
import com.sun.xml.internal.ws.api.pipe.NextAction;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.pipe.TubeCloner;
|
||||
import com.sun.xml.internal.ws.api.pipe.helper.AbstractTubeImpl;
|
||||
import com.sun.xml.internal.ws.api.server.SDDocument;
|
||||
import com.sun.xml.internal.ws.util.MetadataUtil;
|
||||
import com.sun.xml.internal.ws.util.pipe.AbstractSchemaValidationTube;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.Validator;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* {@link Tube} that does the schema validation on the client side.
|
||||
*
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
public class ClientSchemaValidationTube extends AbstractSchemaValidationTube {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ClientSchemaValidationTube.class.getName());
|
||||
|
||||
private final Schema schema;
|
||||
private final Validator validator;
|
||||
private final boolean noValidation;
|
||||
private final WSDLPort port;
|
||||
|
||||
public ClientSchemaValidationTube(WSBinding binding, WSDLPort port, Tube next) {
|
||||
super(binding, next);
|
||||
this.port = port;
|
||||
if (port != null) {
|
||||
String primaryWsdl = port.getOwner().getParent().getLocation().getSystemId();
|
||||
MetadataResolverImpl mdresolver = new MetadataResolverImpl();
|
||||
Map<String, SDDocument> docs = MetadataUtil.getMetadataClosure(primaryWsdl, mdresolver, true);
|
||||
mdresolver = new MetadataResolverImpl(docs.values());
|
||||
Source[] sources = getSchemaSources(docs.values(), mdresolver);
|
||||
for(Source source : sources) {
|
||||
LOGGER.fine("Constructing client validation schema from = "+source.getSystemId());
|
||||
//printDOM((DOMSource)source);
|
||||
}
|
||||
if (sources.length != 0) {
|
||||
noValidation = false;
|
||||
sf.setResourceResolver(mdresolver);
|
||||
try {
|
||||
schema = sf.newSchema(sources);
|
||||
} catch(SAXException e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
validator = schema.newValidator();
|
||||
return;
|
||||
}
|
||||
}
|
||||
noValidation = true;
|
||||
schema = null;
|
||||
validator = null;
|
||||
}
|
||||
|
||||
protected Validator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
protected boolean isNoValidation() {
|
||||
return noValidation;
|
||||
}
|
||||
|
||||
protected ClientSchemaValidationTube(ClientSchemaValidationTube that, TubeCloner cloner) {
|
||||
super(that,cloner);
|
||||
this.port = that.port;
|
||||
this.schema = that.schema;
|
||||
this.validator = schema.newValidator();
|
||||
this.noValidation = that.noValidation;
|
||||
}
|
||||
|
||||
public AbstractTubeImpl copy(TubeCloner cloner) {
|
||||
return new ClientSchemaValidationTube(this,cloner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NextAction processRequest(Packet request) {
|
||||
if (isNoValidation() || !feature.isOutbound() || !request.getMessage().hasPayload() || request.getMessage().isFault()) {
|
||||
return super.processRequest(request);
|
||||
}
|
||||
try {
|
||||
doProcess(request);
|
||||
} catch(SAXException se) {
|
||||
throw new WebServiceException(se);
|
||||
}
|
||||
return super.processRequest(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NextAction processResponse(Packet response) {
|
||||
if (isNoValidation() || !feature.isInbound() || response.getMessage() == null || !response.getMessage().hasPayload() || response.getMessage().isFault()) {
|
||||
return super.processResponse(response);
|
||||
}
|
||||
try {
|
||||
doProcess(response);
|
||||
} catch(SAXException se) {
|
||||
throw new WebServiceException(se);
|
||||
}
|
||||
return super.processResponse(response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.localization.Localizable;
|
||||
import com.sun.xml.internal.ws.util.exception.JAXWSExceptionBase;
|
||||
|
||||
|
||||
/**
|
||||
* @author WS Development Team
|
||||
*/
|
||||
public class ClientTransportException extends JAXWSExceptionBase {
|
||||
public ClientTransportException(Localizable msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public ClientTransportException(Localizable msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
public ClientTransportException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public String getDefaultResourceBundleName() {
|
||||
return "com.sun.xml.internal.ws.resources.client";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
/**
|
||||
* Content negotiation enum.
|
||||
* <p>
|
||||
* A value of {@link #none} means no content negotation at level of the
|
||||
* client transport will be performed to negotiate the encoding of XML infoset.
|
||||
* The default encoding will always be used.
|
||||
* <p>
|
||||
* A value of {@link #pessimistic} means the client transport will assume
|
||||
* the default encoding of XML infoset for an outbound message unless informed
|
||||
* otherwise by a previously received inbound message.
|
||||
* (The client transport initially and pessimistically assumes that a service
|
||||
* does not support anything other than the default encoding of XML infoset.)
|
||||
* <p>
|
||||
* A value of {@link #optimistic} means the client transport will assume
|
||||
* a non-default encoding of XML infoset for an outbound message.
|
||||
* (The client transport optimistically assumes that a service
|
||||
* supports the non-default encoding of XML infoset.)
|
||||
*
|
||||
* @author Paul.Sandoz@Sun.Com
|
||||
*/
|
||||
public enum ContentNegotiation {
|
||||
none,
|
||||
pessimistic,
|
||||
optimistic;
|
||||
|
||||
/**
|
||||
* Property name for content negotiation on {@link RequestContext}.
|
||||
*/
|
||||
public static final String PROPERTY = "com.sun.xml.internal.ws.client.ContentNegotiation";
|
||||
|
||||
/**
|
||||
* Obtain the content negotiation value from a system property.
|
||||
* <p>
|
||||
* This method will never throw a runtime exception.
|
||||
*
|
||||
* @return the content negotiation value.
|
||||
*/
|
||||
public static ContentNegotiation obtainFromSystemProperty() {
|
||||
try {
|
||||
String value = System.getProperty(PROPERTY);
|
||||
|
||||
if (value == null) {
|
||||
return none;
|
||||
}
|
||||
|
||||
return valueOf(value);
|
||||
} catch (Exception e) {
|
||||
// Default to none for any unrecognized value or any other
|
||||
// runtime exception thrown
|
||||
return none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.api.handler.MessageHandler;
|
||||
import com.sun.xml.internal.ws.handler.HandlerException;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.handler.Handler;
|
||||
import javax.xml.ws.handler.LogicalHandler;
|
||||
import javax.xml.ws.handler.soap.SOAPHandler;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class holds the handler information and roles on the Binding (mutable info in the binding).
|
||||
*
|
||||
* HandlerConfiguration is immutable, and a new object is created when the BindingImpl is created or User calls
|
||||
* Binding.setHandlerChain() or SOAPBinding.setRoles().
|
||||
*
|
||||
* During invocation in Stub.process(), snapshot of the handler configuration is set in Packet.handlerConfig. The
|
||||
* information in the HandlerConfiguration is used by MUPipe and HandlerTube implementations.
|
||||
*
|
||||
* @author Rama Pulavarthi
|
||||
*/
|
||||
public class HandlerConfiguration {
|
||||
private final Set<String> roles;
|
||||
/**
|
||||
* This chain may contain both soap and logical handlers.
|
||||
*/
|
||||
private final List<Handler> handlerChain;
|
||||
private final List<LogicalHandler> logicalHandlers;
|
||||
private final List<SOAPHandler> soapHandlers;
|
||||
private final List<MessageHandler> messageHandlers;
|
||||
private final Set<QName> handlerKnownHeaders;
|
||||
|
||||
/**
|
||||
* @param roles This contains the roles assumed by the Binding implementation.
|
||||
* @param handlerChain This contains the handler chain set on the Binding
|
||||
*/
|
||||
public HandlerConfiguration(Set<String> roles, List<Handler> handlerChain) {
|
||||
this.roles = roles;
|
||||
this.handlerChain = handlerChain;
|
||||
logicalHandlers = new ArrayList<LogicalHandler>();
|
||||
soapHandlers = new ArrayList<SOAPHandler>();
|
||||
messageHandlers = new ArrayList<MessageHandler>();
|
||||
Set<QName> modHandlerKnownHeaders = new HashSet<QName>();
|
||||
|
||||
for (Handler handler : handlerChain) {
|
||||
if (handler instanceof LogicalHandler) {
|
||||
logicalHandlers.add((LogicalHandler) handler);
|
||||
} else if (handler instanceof SOAPHandler) {
|
||||
soapHandlers.add((SOAPHandler) handler);
|
||||
Set<QName> headers = ((SOAPHandler<?>) handler).getHeaders();
|
||||
if (headers != null) {
|
||||
modHandlerKnownHeaders.addAll(headers);
|
||||
}
|
||||
} else if (handler instanceof MessageHandler) {
|
||||
messageHandlers.add((MessageHandler) handler);
|
||||
Set<QName> headers = ((MessageHandler<?>) handler).getHeaders();
|
||||
if (headers != null) {
|
||||
modHandlerKnownHeaders.addAll(headers);
|
||||
}
|
||||
}else {
|
||||
throw new HandlerException("handler.not.valid.type",
|
||||
handler.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
handlerKnownHeaders = Collections.unmodifiableSet(modHandlerKnownHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when roles as reset on binding using SOAPBinding#setRoles(), to save reparsing the handlers again.
|
||||
* @param roles
|
||||
* @param oldConfig
|
||||
*/
|
||||
public HandlerConfiguration(Set<String> roles, HandlerConfiguration oldConfig) {
|
||||
this.roles = roles;
|
||||
this.handlerChain = oldConfig.handlerChain;
|
||||
this.logicalHandlers = oldConfig.logicalHandlers;
|
||||
this.soapHandlers = oldConfig.soapHandlers;
|
||||
this.messageHandlers = oldConfig.messageHandlers;
|
||||
this.handlerKnownHeaders = oldConfig.handlerKnownHeaders;
|
||||
}
|
||||
|
||||
public Set<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return return a copy of handler chain
|
||||
*/
|
||||
public List<Handler> getHandlerChain() {
|
||||
if(handlerChain == null)
|
||||
return Collections.emptyList();
|
||||
return new ArrayList<Handler>(handlerChain);
|
||||
|
||||
}
|
||||
|
||||
public List<LogicalHandler> getLogicalHandlers() {
|
||||
return logicalHandlers;
|
||||
}
|
||||
|
||||
public List<SOAPHandler> getSoapHandlers() {
|
||||
return soapHandlers;
|
||||
}
|
||||
|
||||
public List<MessageHandler> getMessageHandlers() {
|
||||
return messageHandlers;
|
||||
}
|
||||
|
||||
public Set<QName> getHandlerKnownHeaders() {
|
||||
return handlerKnownHeaders;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.handler.HandlerChainsModel;
|
||||
import com.sun.xml.internal.ws.util.HandlerAnnotationInfo;
|
||||
import com.sun.xml.internal.ws.util.HandlerAnnotationProcessor;
|
||||
|
||||
import javax.jws.HandlerChain;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.handler.Handler;
|
||||
import javax.xml.ws.handler.HandlerResolver;
|
||||
import javax.xml.ws.handler.PortInfo;
|
||||
import javax.xml.ws.soap.SOAPBinding;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Used by {@link WSServiceDelegate} to configure {@link BindingImpl}
|
||||
* with handlers. The two mechanisms encapsulated by this abstraction
|
||||
* is {@link HandlerChain} annotaion and {@link HandlerResolver}
|
||||
* interface.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class HandlerConfigurator {
|
||||
/**
|
||||
* Configures the given {@link BindingImpl} object by adding handlers to it.
|
||||
*/
|
||||
abstract void configureHandlers(@NotNull WSPortInfo port, @NotNull BindingImpl binding);
|
||||
|
||||
/**
|
||||
* Returns a {@link HandlerResolver}, if this object encapsulates any {@link HandlerResolver}.
|
||||
* Otherwise null.
|
||||
*/
|
||||
abstract HandlerResolver getResolver();
|
||||
|
||||
|
||||
/**
|
||||
* Configures handlers by calling {@link HandlerResolver}.
|
||||
* <p>
|
||||
* When a null {@link HandlerResolver} is set by the user to
|
||||
* {@link Service#setHandlerResolver(HandlerResolver)}, we'll use this object
|
||||
* with null {@link #resolver}.
|
||||
*/
|
||||
static final class HandlerResolverImpl extends HandlerConfigurator {
|
||||
private final @Nullable HandlerResolver resolver;
|
||||
|
||||
public HandlerResolverImpl(HandlerResolver resolver) {
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
void configureHandlers(@NotNull WSPortInfo port, @NotNull BindingImpl binding) {
|
||||
if (resolver!=null) {
|
||||
binding.setHandlerChain(resolver.getHandlerChain(port));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
HandlerResolver getResolver() {
|
||||
return resolver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures handlers from {@link HandlerChain} annotation.
|
||||
*
|
||||
* <p>
|
||||
* This class is a simple
|
||||
* map of PortInfo objects to handler chains. It is used by a
|
||||
* {@link WSServiceDelegate} object, and can
|
||||
* be replaced by user code with a different class implementing
|
||||
* HandlerResolver. This class is only used on the client side, and
|
||||
* it includes a lot of logging to help when there are issues since
|
||||
* it deals with port names, service names, and bindings. All three
|
||||
* must match when getting a handler chain from the map.
|
||||
*
|
||||
* <p>It is created by the {@link WSServiceDelegate}
|
||||
* class , which uses {@link HandlerAnnotationProcessor} to create
|
||||
* a handler chain and then it sets the chains on this class and they
|
||||
* are put into the map. The ServiceContext uses the map to set handler
|
||||
* chains on bindings when they are created.
|
||||
*/
|
||||
static final class AnnotationConfigurator extends HandlerConfigurator {
|
||||
private final HandlerChainsModel handlerModel;
|
||||
private final Map<WSPortInfo,HandlerAnnotationInfo> chainMap = new HashMap<WSPortInfo,HandlerAnnotationInfo>();
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".handler");
|
||||
|
||||
AnnotationConfigurator(WSServiceDelegate delegate) {
|
||||
handlerModel = HandlerAnnotationProcessor.buildHandlerChainsModel(delegate.getServiceClass());
|
||||
assert handlerModel!=null; // this class is suppeod to be called only when there's @HandlerCHain
|
||||
}
|
||||
|
||||
|
||||
void configureHandlers(WSPortInfo port, BindingImpl binding) {
|
||||
//Check in cache first
|
||||
HandlerAnnotationInfo chain = chainMap.get(port);
|
||||
|
||||
if(chain==null) {
|
||||
logGetChain(port);
|
||||
// Put it in cache
|
||||
chain = handlerModel.getHandlersForPortInfo(port);
|
||||
chainMap.put(port,chain);
|
||||
}
|
||||
|
||||
if (binding instanceof SOAPBinding) {
|
||||
((SOAPBinding) binding).setRoles(chain.getRoles());
|
||||
}
|
||||
|
||||
logSetChain(port,chain);
|
||||
binding.setHandlerChain(chain.getHandlers());
|
||||
}
|
||||
|
||||
HandlerResolver getResolver() {
|
||||
return new HandlerResolver() {
|
||||
public List<Handler> getHandlerChain(PortInfo portInfo) {
|
||||
return new ArrayList<Handler>(
|
||||
handlerModel.getHandlersForPortInfo(portInfo).getHandlers());
|
||||
}
|
||||
};
|
||||
}
|
||||
// logged at finer level
|
||||
private void logSetChain(WSPortInfo info, HandlerAnnotationInfo chain) {
|
||||
logger.finer("Setting chain of length " + chain.getHandlers().size() +
|
||||
" for port info");
|
||||
logPortInfo(info, Level.FINER);
|
||||
}
|
||||
|
||||
// logged at fine level
|
||||
private void logGetChain(WSPortInfo info) {
|
||||
logger.fine("No handler chain found for port info:");
|
||||
logPortInfo(info, Level.FINE);
|
||||
logger.fine("Existing handler chains:");
|
||||
if (chainMap.isEmpty()) {
|
||||
logger.fine("none");
|
||||
} else {
|
||||
for (WSPortInfo key : chainMap.keySet()) {
|
||||
logger.fine(chainMap.get(key).getHandlers().size() +
|
||||
" handlers for port info ");
|
||||
logPortInfo(key, Level.FINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logPortInfo(WSPortInfo info, Level level) {
|
||||
logger.log(level, "binding: " + info.getBindingID() +
|
||||
"\nservice: " + info.getServiceName() +
|
||||
"\nport: " + info.getPortName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLService;
|
||||
import com.sun.xml.internal.ws.api.server.Container;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.org.glassfish.gmbal.AMXMetadata;
|
||||
import com.sun.org.glassfish.gmbal.Description;
|
||||
import com.sun.org.glassfish.gmbal.ManagedAttribute;
|
||||
import com.sun.org.glassfish.gmbal.ManagedObject;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author Harold Carr
|
||||
*/
|
||||
@ManagedObject
|
||||
@Description("Metro Web Service client")
|
||||
@AMXMetadata(type="WSClient")
|
||||
public final class MonitorRootClient extends com.sun.xml.internal.ws.server.MonitorBase {
|
||||
|
||||
private final Stub stub;
|
||||
|
||||
MonitorRootClient(final Stub stub) {
|
||||
this.stub = stub;
|
||||
}
|
||||
|
||||
/*
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".client.stub");
|
||||
*/
|
||||
|
||||
//
|
||||
// From WSServiceDelegate
|
||||
//
|
||||
|
||||
@ManagedAttribute
|
||||
private Container getContainer() { return stub.owner.getContainer(); }
|
||||
|
||||
@ManagedAttribute
|
||||
private Map<QName, PortInfo> qnameToPortInfoMap() { return stub.owner.getQNameToPortInfoMap(); }
|
||||
|
||||
@ManagedAttribute
|
||||
private QName serviceName() { return stub.owner.getServiceName(); }
|
||||
|
||||
@ManagedAttribute
|
||||
private Class serviceClass() { return stub.owner.getServiceClass(); }
|
||||
|
||||
@ManagedAttribute
|
||||
private URL wsdlDocumentLocation() { return stub.owner.getWSDLDocumentLocation(); }
|
||||
|
||||
@ManagedAttribute
|
||||
private WSDLService wsdlService() { return stub.owner.getWsdlService(); }
|
||||
|
||||
|
||||
|
||||
}
|
||||
213
jdkSrc/jdk8/com/sun/xml/internal/ws/client/PortInfo.java
Normal file
213
jdkSrc/jdk8/com/sun/xml/internal/ws/client/PortInfo.java
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.ws.api.BindingID;
|
||||
import com.sun.xml.internal.ws.api.EndpointAddress;
|
||||
import com.sun.xml.internal.ws.api.WSService;
|
||||
import com.sun.xml.internal.ws.api.policy.PolicyResolverFactory;
|
||||
import com.sun.xml.internal.ws.api.policy.PolicyResolver;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
|
||||
import com.sun.xml.internal.ws.policy.PolicyMap;
|
||||
import com.sun.xml.internal.ws.policy.jaxws.PolicyUtil;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.WebServiceFeature;
|
||||
|
||||
/**
|
||||
* Information about a port.
|
||||
* <p/>
|
||||
* This object is owned by {@link WSServiceDelegate} to keep track of a port,
|
||||
* since a port maybe added dynamically.
|
||||
*
|
||||
* @author JAXWS Development Team
|
||||
*/
|
||||
public class PortInfo implements WSPortInfo {
|
||||
private final @NotNull WSServiceDelegate owner;
|
||||
|
||||
public final @NotNull QName portName;
|
||||
public final @NotNull EndpointAddress targetEndpoint;
|
||||
public final @NotNull BindingID bindingId;
|
||||
|
||||
public final @NotNull PolicyMap policyMap;
|
||||
/**
|
||||
* If a port is known statically to a WSDL, {@link PortInfo} may
|
||||
* have the corresponding WSDL model. This would occur when the
|
||||
* service was created with the WSDL location and the port is defined
|
||||
* in the WSDL.
|
||||
* <p/>
|
||||
* If this is a {@link SEIPortInfo}, then this is always non-null.
|
||||
*/
|
||||
public final @Nullable WSDLPort portModel;
|
||||
|
||||
public PortInfo(WSServiceDelegate owner, EndpointAddress targetEndpoint, QName name, BindingID bindingId) {
|
||||
this.owner = owner;
|
||||
this.targetEndpoint = targetEndpoint;
|
||||
this.portName = name;
|
||||
this.bindingId = bindingId;
|
||||
this.portModel = getPortModel(owner, name);
|
||||
this.policyMap = createPolicyMap();
|
||||
|
||||
}
|
||||
|
||||
public PortInfo(@NotNull WSServiceDelegate owner, @NotNull WSDLPort port) {
|
||||
this.owner = owner;
|
||||
this.targetEndpoint = port.getAddress();
|
||||
this.portName = port.getName();
|
||||
this.bindingId = port.getBinding().getBindingId();
|
||||
this.portModel = port;
|
||||
this.policyMap = createPolicyMap();
|
||||
}
|
||||
|
||||
public PolicyMap getPolicyMap() {
|
||||
return policyMap;
|
||||
}
|
||||
|
||||
public PolicyMap createPolicyMap() {
|
||||
PolicyMap map;
|
||||
if(portModel != null) {
|
||||
map = portModel.getOwner().getParent().getPolicyMap();
|
||||
} else {
|
||||
map = PolicyResolverFactory.create().resolve(new PolicyResolver.ClientContext(null,owner.getContainer()));
|
||||
}
|
||||
//still map is null, create a empty map
|
||||
if(map == null)
|
||||
map = PolicyMap.createPolicyMap(null);
|
||||
return map;
|
||||
}
|
||||
/**
|
||||
* Creates {@link BindingImpl} for this {@link PortInfo}.
|
||||
*
|
||||
* @param webServiceFeatures
|
||||
* User-specified features.
|
||||
* @param portInterface
|
||||
* Null if this is for dispatch. Otherwise the interface the proxy is going to implement
|
||||
* @return
|
||||
* The initialized BindingImpl
|
||||
*/
|
||||
public BindingImpl createBinding(WebServiceFeature[] webServiceFeatures, Class<?> portInterface) {
|
||||
return createBinding(new WebServiceFeatureList(webServiceFeatures), portInterface, null);
|
||||
}
|
||||
|
||||
public BindingImpl createBinding(WebServiceFeatureList webServiceFeatures, Class<?> portInterface,
|
||||
BindingImpl existingBinding) {
|
||||
if (existingBinding != null) {
|
||||
webServiceFeatures.addAll(existingBinding.getFeatures());
|
||||
}
|
||||
|
||||
Iterable<WebServiceFeature> configFeatures;
|
||||
//TODO incase of Dispatch, provide a way to User for complete control of the message processing by giving
|
||||
// ability to turn off the WSDL/Policy based features and its associated tubes.
|
||||
|
||||
//Even in case of Dispatch, merge all features configured via WSDL/Policy or deployment configuration
|
||||
if (portModel != null) {
|
||||
// could have merged features from this.policyMap, but some features are set in WSDLModel which are not there in PolicyMap
|
||||
// for ex: <wsaw:UsingAddressing> wsdl extn., and since the policyMap features are merged into WSDLModel anyway during postFinished(),
|
||||
// So, using here WsdlModel for merging is right.
|
||||
|
||||
// merge features from WSDL
|
||||
configFeatures = portModel.getFeatures();
|
||||
} else {
|
||||
configFeatures = PolicyUtil.getPortScopedFeatures(policyMap, owner.getServiceName(),portName);
|
||||
}
|
||||
webServiceFeatures.mergeFeatures(configFeatures, false);
|
||||
|
||||
// merge features from interceptor
|
||||
webServiceFeatures.mergeFeatures(owner.serviceInterceptor.preCreateBinding(this, portInterface, webServiceFeatures), false);
|
||||
|
||||
BindingImpl bindingImpl = BindingImpl.create(bindingId, webServiceFeatures.toArray());
|
||||
owner.getHandlerConfigurator().configureHandlers(this,bindingImpl);
|
||||
return bindingImpl;
|
||||
}
|
||||
|
||||
//This method is used for Dispatch client only
|
||||
private WSDLPort getPortModel(WSServiceDelegate owner, QName portName) {
|
||||
|
||||
if (owner.getWsdlService() != null){
|
||||
Iterable<? extends WSDLPort> ports = owner.getWsdlService().getPorts();
|
||||
for (WSDLPort port : ports){
|
||||
if (port.getName().equals(portName))
|
||||
return port;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// implementation of API PortInfo interface
|
||||
//
|
||||
|
||||
@Nullable
|
||||
public WSDLPort getPort() {
|
||||
return portModel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WSService getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BindingID getBindingId() {
|
||||
return bindingId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public EndpointAddress getEndpointAddress() {
|
||||
return targetEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Only meant to be used via {@link javax.xml.ws.handler.PortInfo}.
|
||||
* Use {@link WSServiceDelegate#getServiceName()}.
|
||||
*/
|
||||
public QName getServiceName() {
|
||||
return owner.getServiceName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Only meant to be used via {@link javax.xml.ws.handler.PortInfo}.
|
||||
* Use {@link #portName}.
|
||||
*/
|
||||
public QName getPortName() {
|
||||
return portName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Only meant to be used via {@link javax.xml.ws.handler.PortInfo}.
|
||||
* Use {@link #bindingId}.
|
||||
*/
|
||||
public String getBindingID() {
|
||||
return bindingId.toString();
|
||||
}
|
||||
}
|
||||
382
jdkSrc/jdk8/com/sun/xml/internal/ws/client/RequestContext.java
Normal file
382
jdkSrc/jdk8/com/sun/xml/internal/ws/client/RequestContext.java
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.oracle.webservices.internal.api.message.BaseDistributedPropertySet;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.ws.api.EndpointAddress;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.transport.Headers;
|
||||
|
||||
import javax.xml.ws.BindingProvider;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
import static javax.xml.ws.BindingProvider.*;
|
||||
import static javax.xml.ws.handler.MessageContext.HTTP_REQUEST_HEADERS;
|
||||
|
||||
/**
|
||||
* Request context implementation.
|
||||
*
|
||||
* <h2>Why a custom map?</h2>
|
||||
* <p>
|
||||
* The JAX-WS spec exposes properties as a {@link Map}, but if we just use
|
||||
* an ordinary {@link HashMap} for this, it doesn't work as fast as we'd like
|
||||
* it to be. Hence we have this class.
|
||||
*
|
||||
* <p>
|
||||
* We expect the user to set a few properties and then use that same
|
||||
* setting to make a bunch of invocations. So we'd like to take some hit
|
||||
* when the user actually sets a property to do some computation,
|
||||
* then use that computed value during a method invocation again and again.
|
||||
*
|
||||
* <p>
|
||||
* For this goal, we use {@link com.sun.xml.internal.ws.api.PropertySet} and implement some properties
|
||||
* as virtual properties backed by methods. This allows us to do the computation
|
||||
* in the setter, and store it in a field.
|
||||
*
|
||||
* <p>
|
||||
* These fields are used by {@link Stub#process} to populate a {@link Packet}.
|
||||
*
|
||||
* <h2>How it works?</h2>
|
||||
* <p>
|
||||
* For better performance, we wan't use strongly typed field as much as possible
|
||||
* to avoid reflection and unnecessary collection iterations;
|
||||
*
|
||||
* Using {@link com.oracle.webservices.internal.api.message.BasePropertySet.MapView} implementation allows client to use {@link Map} interface
|
||||
* in a way that all the strongly typed properties are reflected to the fields
|
||||
* right away. Any additional (extending) properties can be added by client as well;
|
||||
* those would be processed using iterating the {@link MapView} and their processing,
|
||||
* of course, would be slower.
|
||||
* <p>
|
||||
* The previous implementation with fallback mode has been removed to simplify
|
||||
* the code and remove the bugs.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
@SuppressWarnings({"SuspiciousMethodCalls"})
|
||||
public final class RequestContext extends BaseDistributedPropertySet {
|
||||
private static final Logger LOGGER = Logger.getLogger(RequestContext.class.getName());
|
||||
|
||||
/**
|
||||
* The default value to be use for {@link #contentNegotiation} obtained
|
||||
* from a system property.
|
||||
* <p>
|
||||
* This enables content negotiation to be easily switched on by setting
|
||||
* a system property on the command line for testing purposes tests.
|
||||
*/
|
||||
private static ContentNegotiation defaultContentNegotiation =
|
||||
ContentNegotiation.obtainFromSystemProperty();
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public void addSatellite(@NotNull com.sun.xml.internal.ws.api.PropertySet satellite) {
|
||||
super.addSatellite(satellite);
|
||||
}
|
||||
|
||||
/**
|
||||
* The endpoint address to which this message is sent to.
|
||||
*
|
||||
* <p>
|
||||
* This is the actual data store for {@link BindingProvider#ENDPOINT_ADDRESS_PROPERTY}.
|
||||
*/
|
||||
private @NotNull EndpointAddress endpointAddress;
|
||||
|
||||
/**
|
||||
* Creates {@link BindingProvider#ENDPOINT_ADDRESS_PROPERTY} view
|
||||
* on top of {@link #endpointAddress}.
|
||||
*
|
||||
* @deprecated
|
||||
* always access {@link #endpointAddress}.
|
||||
*/
|
||||
@Property(ENDPOINT_ADDRESS_PROPERTY)
|
||||
public String getEndPointAddressString() {
|
||||
return endpointAddress != null ? endpointAddress.toString() : null;
|
||||
}
|
||||
|
||||
public void setEndPointAddressString(String s) {
|
||||
if (s == null) {
|
||||
throw new IllegalArgumentException();
|
||||
} else {
|
||||
this.endpointAddress = EndpointAddress.create(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEndpointAddress(@NotNull EndpointAddress epa) {
|
||||
this.endpointAddress = epa;
|
||||
}
|
||||
|
||||
public @NotNull EndpointAddress getEndpointAddress() {
|
||||
return endpointAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of {@link ContentNegotiation#PROPERTY}
|
||||
* property.
|
||||
*/
|
||||
public ContentNegotiation contentNegotiation = defaultContentNegotiation;
|
||||
|
||||
@Property(ContentNegotiation.PROPERTY)
|
||||
public String getContentNegotiationString() {
|
||||
return contentNegotiation.toString();
|
||||
}
|
||||
|
||||
public void setContentNegotiationString(String s) {
|
||||
if (s == null) {
|
||||
contentNegotiation = ContentNegotiation.none;
|
||||
} else {
|
||||
try {
|
||||
contentNegotiation = ContentNegotiation.valueOf(s);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// If the value is not recognized default to none
|
||||
contentNegotiation = ContentNegotiation.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of the SOAPAction header associated with the message.
|
||||
*
|
||||
* <p>
|
||||
* For outgoing messages, the transport may sends out this value.
|
||||
* If this field is null, the transport may choose to send <tt>""</tt>
|
||||
* (quoted empty string.)
|
||||
*
|
||||
* For incoming messages, the transport will set this field.
|
||||
* If the incoming message did not contain the SOAPAction header,
|
||||
* the transport sets this field to null.
|
||||
*
|
||||
* <p>
|
||||
* If the value is non-null, it must be always in the quoted form.
|
||||
* The value can be null.
|
||||
*
|
||||
* <p>
|
||||
* Note that the way the transport sends this value out depends on
|
||||
* transport and SOAP version.
|
||||
*
|
||||
* For HTTP transport and SOAP 1.1, BP requires that SOAPAction
|
||||
* header is present (See {@BP R2744} and {@BP R2745}.) For SOAP 1.2,
|
||||
* this is moved to the parameter of the "application/soap+xml".
|
||||
*/
|
||||
|
||||
private String soapAction;
|
||||
|
||||
@Property(SOAPACTION_URI_PROPERTY)
|
||||
public String getSoapAction() {
|
||||
return soapAction;
|
||||
}
|
||||
|
||||
public void setSoapAction(String sAction) {
|
||||
soapAction = sAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* This controls whether BindingProvider.SOAPACTION_URI_PROPERTY is used.
|
||||
* See BindingProvider.SOAPACTION_USE_PROPERTY for details.
|
||||
*
|
||||
* This only control whether value of BindingProvider.SOAPACTION_URI_PROPERTY is used or not and not
|
||||
* if it can be sent if it can be obtained by other means such as WSDL binding
|
||||
*/
|
||||
private Boolean soapActionUse;
|
||||
|
||||
@Property(SOAPACTION_USE_PROPERTY)
|
||||
public Boolean getSoapActionUse() {
|
||||
return soapActionUse;
|
||||
}
|
||||
|
||||
public void setSoapActionUse(Boolean sActionUse) {
|
||||
soapActionUse = sActionUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty {@link RequestContext}.
|
||||
*/
|
||||
RequestContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
private RequestContext(RequestContext that) {
|
||||
for (Map.Entry<String, Object> entry : that.asMapLocal().entrySet()) {
|
||||
if (!propMap.containsKey(entry.getKey())) {
|
||||
asMap().put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
endpointAddress = that.endpointAddress;
|
||||
soapAction = that.soapAction;
|
||||
soapActionUse = that.soapActionUse;
|
||||
contentNegotiation = that.contentNegotiation;
|
||||
that.copySatelliteInto(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The efficient get method that reads from {@link RequestContext}.
|
||||
*/
|
||||
@Override
|
||||
public Object get(Object key) {
|
||||
if(supports(key)) {
|
||||
return super.get(key);
|
||||
} else {
|
||||
// use mapView to get extending property
|
||||
return asMap().get(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The efficient put method that updates {@link RequestContext}.
|
||||
*/
|
||||
@Override
|
||||
public Object put(String key, Object value) {
|
||||
|
||||
if(supports(key)) {
|
||||
return super.put(key,value);
|
||||
} else {
|
||||
// use mapView to put extending property (if the map allows that)
|
||||
return asMap().put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill a {@link Packet} with values of this {@link RequestContext}.
|
||||
*
|
||||
* @param packet to be filled with context values
|
||||
* @param isAddressingEnabled flag if addressing enabled (to provide warning if necessary)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void fill(Packet packet, boolean isAddressingEnabled) {
|
||||
|
||||
// handling as many properties as possible (all in propMap.keySet())
|
||||
// to avoid slow Packet.put()
|
||||
if (endpointAddress != null) {
|
||||
packet.endpointAddress = endpointAddress;
|
||||
}
|
||||
packet.contentNegotiation = contentNegotiation;
|
||||
fillSOAPAction(packet, isAddressingEnabled);
|
||||
mergeRequestHeaders(packet);
|
||||
|
||||
Set<String> handlerScopeNames = new HashSet<String>();
|
||||
|
||||
copySatelliteInto(packet);
|
||||
|
||||
// extending properties ...
|
||||
for (String key : asMapLocal().keySet()) {
|
||||
|
||||
//if it is not standard property it defaults to Scope.HANDLER
|
||||
if (!supportsLocal(key)) {
|
||||
handlerScopeNames.add(key);
|
||||
}
|
||||
|
||||
// to avoid slow Packet.put(), handle as small number of props as possible
|
||||
// => only properties not from RequestContext object
|
||||
if (!propMap.containsKey(key)) {
|
||||
Object value = asMapLocal().get(key);
|
||||
if (packet.supports(key)) {
|
||||
// very slow operation - try to avoid it!
|
||||
packet.put(key, value);
|
||||
} else {
|
||||
packet.invocationProperties.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!handlerScopeNames.isEmpty()) {
|
||||
packet.getHandlerScopePropertyNames(false).addAll(handlerScopeNames);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void mergeRequestHeaders(Packet packet) {
|
||||
//for bug 12883765
|
||||
//retrieve headers which is set in soap message
|
||||
Headers packetHeaders = (Headers) packet.invocationProperties.get(HTTP_REQUEST_HEADERS);
|
||||
//retrieve headers from request context
|
||||
Map<String, List<String>> myHeaders = (Map<String, List<String>>) asMap().get(HTTP_REQUEST_HEADERS);
|
||||
if ((packetHeaders != null) && (myHeaders != null)) {
|
||||
//update the headers set in soap message with those in request context
|
||||
for (Entry<String, List<String>> entry : myHeaders.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key != null && key.trim().length() != 0) {
|
||||
List<String> listFromPacket = packetHeaders.get(key);
|
||||
//if the two headers contain the same key, combine the value
|
||||
if (listFromPacket != null) {
|
||||
listFromPacket.addAll(entry.getValue());
|
||||
} else {
|
||||
//add the headers in request context to those set in soap message
|
||||
packetHeaders.put(key, myHeaders.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
// update headers in request context with those set in soap message since it may contain other properties..
|
||||
asMap().put(HTTP_REQUEST_HEADERS, packetHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillSOAPAction(Packet packet, boolean isAddressingEnabled) {
|
||||
final boolean p = packet.packetTakesPriorityOverRequestContext;
|
||||
final String localSoapAction = p ? packet.soapAction : soapAction;
|
||||
final Boolean localSoapActionUse = p ? (Boolean) packet.invocationProperties.get(BindingProvider.SOAPACTION_USE_PROPERTY)
|
||||
: soapActionUse;
|
||||
|
||||
//JAX-WS-596: Check the semantics of SOAPACTION_USE_PROPERTY before using the SOAPACTION_URI_PROPERTY for
|
||||
// SoapAction as specified in the javadoc of BindingProvider. The spec seems to be little contradicting with
|
||||
// javadoc and says that the use property effects the sending of SOAPAction property.
|
||||
// Since the user has the capability to set the value as "" if needed, implement the javadoc behavior.
|
||||
if ((localSoapActionUse != null && localSoapActionUse) || (localSoapActionUse == null && isAddressingEnabled)) {
|
||||
if (localSoapAction != null) {
|
||||
packet.soapAction = localSoapAction;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!isAddressingEnabled && (localSoapActionUse == null || !localSoapActionUse)) && localSoapAction != null) {
|
||||
LOGGER.warning("BindingProvider.SOAPACTION_URI_PROPERTY is set in the RequestContext but is ineffective," +
|
||||
" Either set BindingProvider.SOAPACTION_USE_PROPERTY to true or enable AddressingFeature");
|
||||
}
|
||||
}
|
||||
|
||||
public RequestContext copy() {
|
||||
return new RequestContext(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyMap getPropertyMap() {
|
||||
return propMap;
|
||||
}
|
||||
|
||||
private static final PropertyMap propMap = parse(RequestContext.class);
|
||||
|
||||
@Override
|
||||
protected boolean mapAllowsAdditionalProperties() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
163
jdkSrc/jdk8/com/sun/xml/internal/ws/client/ResponseContext.java
Normal file
163
jdkSrc/jdk8/com/sun/xml/internal/ws/client/ResponseContext.java
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.message.AttachmentSet;
|
||||
import com.sun.xml.internal.ws.api.message.Attachment;
|
||||
|
||||
import javax.xml.ws.handler.MessageContext;
|
||||
import javax.activation.DataHandler;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Implements "response context" on top of {@link Packet}.
|
||||
*
|
||||
* <p>
|
||||
* This class creates a read-only {@link Map} view that
|
||||
* gets exposed to client applications after an invocation
|
||||
* is complete.
|
||||
*
|
||||
* <p>
|
||||
* The design goal of this class is to make it efficient
|
||||
* to create a new {@link ResponseContext}, at the expense
|
||||
* of making some {@link Map} operations slower. This is
|
||||
* justified because the response context is mostly just
|
||||
* used to query a few known values, and operations like
|
||||
* enumeration isn't likely.
|
||||
*
|
||||
* <p>
|
||||
* Some of the {@link Map} methods requre this class to
|
||||
* build the complete {@link Set} of properties, but we
|
||||
* try to avoid that as much as possible.
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* TODO: are we exposing all strongly-typed fields, or
|
||||
* do they have appliation/handler scope notion?
|
||||
* </pre>
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
@SuppressWarnings({"SuspiciousMethodCalls"}) // IDE doesn't like me calling Map methods with key typed as Object
|
||||
public class ResponseContext extends AbstractMap<String,Object> {
|
||||
private final Packet packet;
|
||||
|
||||
/**
|
||||
* Lazily computed.
|
||||
*/
|
||||
private Set<Map.Entry<String,Object>> entrySet;
|
||||
|
||||
/**
|
||||
* @param packet
|
||||
* The {@link Packet} to wrap.
|
||||
*/
|
||||
public ResponseContext(Packet packet) {
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
if(packet.supports(key))
|
||||
return packet.containsKey(key); // strongly typed
|
||||
|
||||
if(packet.invocationProperties.containsKey(key))
|
||||
// if handler-scope, hide it
|
||||
return !packet.getHandlerScopePropertyNames(true).contains(key);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object get(Object key) {
|
||||
if(packet.supports(key))
|
||||
return packet.get(key); // strongly typed
|
||||
|
||||
if(packet.getHandlerScopePropertyNames(true).contains(key))
|
||||
return null; // no such application-scope property
|
||||
|
||||
Object value = packet.invocationProperties.get(key);
|
||||
|
||||
//add the attachments from the Message to the corresponding attachment property
|
||||
if(key.equals(MessageContext.INBOUND_MESSAGE_ATTACHMENTS)){
|
||||
Map<String, DataHandler> atts = (Map<String, DataHandler>) value;
|
||||
if(atts == null)
|
||||
atts = new HashMap<String, DataHandler>();
|
||||
AttachmentSet attSet = packet.getMessage().getAttachments();
|
||||
for(Attachment att : attSet){
|
||||
atts.put(att.getContentId(), att.asDataHandler());
|
||||
}
|
||||
return atts;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object put(String key, Object value) {
|
||||
// response context is read-only
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object remove(Object key) {
|
||||
// response context is read-only
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends String, ? extends Object> t) {
|
||||
// response context is read-only
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
// response context is read-only
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Set<Entry<String, Object>> entrySet() {
|
||||
if(entrySet==null) {
|
||||
// this is where the worst case happens. we have to clone the whole properties
|
||||
// to get this view.
|
||||
|
||||
// use TreeSet so that toString() sort them nicely. It's easier for apps.
|
||||
Map<String,Object> r = new HashMap<String,Object>();
|
||||
|
||||
// export application-scope properties
|
||||
r.putAll(packet.invocationProperties);
|
||||
|
||||
// hide handler-scope properties
|
||||
r.keySet().removeAll(packet.getHandlerScopePropertyNames(true));
|
||||
|
||||
// and all strongly typed ones
|
||||
r.putAll(packet.createMapView());
|
||||
|
||||
entrySet = Collections.unmodifiableSet(r.entrySet());
|
||||
}
|
||||
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
/**
|
||||
* Receives {@link ResponseContext} at the end of
|
||||
* the message invocation.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public interface ResponseContextReceiver {
|
||||
/**
|
||||
* Called upon the completion of the invocation
|
||||
* to set a {@link ResponseContext}.
|
||||
*
|
||||
* <p>
|
||||
* This method is invoked even when the invocation fails.
|
||||
*/
|
||||
void setResponseContext(ResponseContext rc);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.ws.util.JAXWSUtils;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebEndpoint;
|
||||
import javax.xml.ws.WebServiceClient;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Represents parsed {@link WebServiceClient} and {@link WebEndpoint}
|
||||
* annotations on a {@link Service}-derived class.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class SCAnnotations {
|
||||
SCAnnotations(final Class<?> sc) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
WebServiceClient wsc =sc.getAnnotation(WebServiceClient.class);
|
||||
if(wsc==null) {
|
||||
throw new WebServiceException("Service Interface Annotations required, exiting...");
|
||||
}
|
||||
|
||||
String tns = wsc.targetNamespace();
|
||||
try {
|
||||
JAXWSUtils.getFileOrURL(wsc.wsdlLocation());
|
||||
} catch (IOException e) {
|
||||
// TODO: report a reasonable error message
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
|
||||
for (Method method : sc.getDeclaredMethods()) {
|
||||
WebEndpoint webEndpoint = method.getAnnotation(WebEndpoint.class);
|
||||
if (webEndpoint != null) {
|
||||
String endpointName = webEndpoint.name();
|
||||
QName portQName = new QName(tns, endpointName);
|
||||
portQNames.add(portQName);
|
||||
}
|
||||
Class<?> seiClazz = method.getReturnType();
|
||||
if (seiClazz!=void.class) {
|
||||
classes.add(seiClazz);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final ArrayList<QName> portQNames = new ArrayList<QName>();
|
||||
final ArrayList<Class> classes = new ArrayList<Class>();
|
||||
}
|
||||
84
jdkSrc/jdk8/com/sun/xml/internal/ws/client/SEIPortInfo.java
Normal file
84
jdkSrc/jdk8/com/sun/xml/internal/ws/client/SEIPortInfo.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.ws.api.model.SEIModel;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.binding.SOAPBindingImpl;
|
||||
import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
|
||||
import com.sun.xml.internal.ws.model.SOAPSEIModel;
|
||||
|
||||
import javax.xml.ws.WebServiceFeature;
|
||||
|
||||
/**
|
||||
* {@link PortInfo} that has {@link SEIModel}.
|
||||
*
|
||||
* This object is created statically when {@link WSServiceDelegate} is created
|
||||
* with an service interface.
|
||||
*
|
||||
* NOTE: Made this class public so that Dispatch instances derived from a
|
||||
* 'parent' SEI-based port instance (generally for sending protocol
|
||||
* messages or request retries) can still know what the parent's SEI was.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class SEIPortInfo extends PortInfo {
|
||||
|
||||
public final Class sei;
|
||||
|
||||
/**
|
||||
* Model of {@link #sei}.
|
||||
*/
|
||||
public final SOAPSEIModel model;
|
||||
|
||||
public SEIPortInfo(WSServiceDelegate owner, Class sei, SOAPSEIModel model, @NotNull WSDLPort portModel) {
|
||||
super(owner, portModel);
|
||||
this.sei = sei;
|
||||
this.model = model;
|
||||
assert sei != null && model != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingImpl createBinding(WebServiceFeature[] webServiceFeatures, Class<?> portInterface) {
|
||||
BindingImpl binding = super.createBinding(webServiceFeatures, portInterface);
|
||||
return setKnownHeaders(binding);
|
||||
}
|
||||
|
||||
public BindingImpl createBinding(WebServiceFeatureList webServiceFeatures, Class<?> portInterface) {
|
||||
// not to pass in (BindingImpl) model.getWSBinding()
|
||||
BindingImpl binding = super.createBinding(webServiceFeatures, portInterface, null);
|
||||
return setKnownHeaders(binding);
|
||||
}
|
||||
|
||||
private BindingImpl setKnownHeaders(BindingImpl binding) {
|
||||
if (binding instanceof SOAPBindingImpl) {
|
||||
((SOAPBindingImpl) binding).setPortKnownHeaders(model.getKnownHeaders());
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.localization.Localizable;
|
||||
import com.sun.xml.internal.ws.util.exception.JAXWSExceptionBase;
|
||||
|
||||
|
||||
/**
|
||||
* @author WS Development Team
|
||||
*/
|
||||
public class SenderException extends JAXWSExceptionBase {
|
||||
public SenderException(String key, Object... args) {
|
||||
super(key, args);
|
||||
}
|
||||
|
||||
public SenderException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public SenderException(Localizable arg) {
|
||||
super("sender.nestedError", arg);
|
||||
}
|
||||
|
||||
public String getDefaultResourceBundleName() {
|
||||
return "com.sun.xml.internal.ws.resources.sender";
|
||||
}
|
||||
}
|
||||
753
jdkSrc/jdk8/com/sun/xml/internal/ws/client/Stub.java
Normal file
753
jdkSrc/jdk8/com/sun/xml/internal/ws/client/Stub.java
Normal file
@@ -0,0 +1,753 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
|
||||
import com.sun.xml.internal.ws.addressing.WSEPRExtension;
|
||||
import com.sun.xml.internal.ws.api.BindingID;
|
||||
import com.sun.xml.internal.ws.api.Component;
|
||||
import com.sun.xml.internal.ws.api.ComponentFeature;
|
||||
import com.sun.xml.internal.ws.api.ComponentFeature.Target;
|
||||
import com.sun.xml.internal.ws.api.ComponentRegistry;
|
||||
import com.sun.xml.internal.ws.api.ComponentsFeature;
|
||||
import com.sun.xml.internal.ws.api.EndpointAddress;
|
||||
import com.sun.xml.internal.ws.api.WSBinding;
|
||||
import com.sun.xml.internal.ws.api.WSService;
|
||||
import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.api.message.AddressingUtils;
|
||||
import com.sun.xml.internal.ws.api.message.Header;
|
||||
import com.sun.xml.internal.ws.api.message.HeaderList;
|
||||
import com.sun.xml.internal.ws.api.message.MessageHeaders;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.model.SEIModel;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
|
||||
import com.sun.xml.internal.ws.api.pipe.ClientTubeAssemblerContext;
|
||||
import com.sun.xml.internal.ws.api.pipe.Engine;
|
||||
import com.sun.xml.internal.ws.api.pipe.Fiber;
|
||||
import com.sun.xml.internal.ws.api.pipe.FiberContextSwitchInterceptorFactory;
|
||||
import com.sun.xml.internal.ws.api.pipe.SyncStartForAsyncFeature;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.pipe.TubelineAssembler;
|
||||
import com.sun.xml.internal.ws.api.pipe.TubelineAssemblerFactory;
|
||||
import com.sun.xml.internal.ws.api.server.Container;
|
||||
import com.sun.xml.internal.ws.api.server.ContainerResolver;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.developer.JAXWSProperties;
|
||||
import com.sun.xml.internal.ws.developer.WSBindingProvider;
|
||||
import com.sun.xml.internal.ws.model.wsdl.WSDLDirectProperties;
|
||||
import com.sun.xml.internal.ws.model.wsdl.WSDLPortProperties;
|
||||
import com.sun.xml.internal.ws.model.wsdl.WSDLProperties;
|
||||
import com.sun.xml.internal.ws.resources.ClientMessages;
|
||||
import com.sun.xml.internal.ws.util.Pool;
|
||||
import com.sun.xml.internal.ws.util.Pool.TubePool;
|
||||
import com.sun.xml.internal.ws.util.RuntimeVersion;
|
||||
import com.sun.xml.internal.ws.wsdl.OperationDispatcher;
|
||||
import com.sun.org.glassfish.gmbal.ManagedObjectManager;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.ws.BindingProvider;
|
||||
import javax.xml.ws.EndpointReference;
|
||||
import javax.xml.ws.RespectBindingFeature;
|
||||
import javax.xml.ws.Response;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import javax.xml.ws.http.HTTPBinding;
|
||||
import javax.xml.ws.wsaddressing.W3CEndpointReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
/**
|
||||
* Base class for stubs, which accept method invocations from
|
||||
* client applications and pass the message to a {@link Tube}
|
||||
* for processing.
|
||||
*
|
||||
* <p>
|
||||
* This class implements the management of pipe instances,
|
||||
* and most of the {@link BindingProvider} methods.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class Stub implements WSBindingProvider, ResponseContextReceiver, ComponentRegistry {
|
||||
/**
|
||||
* Internal flag indicating async dispatch should be used even when the
|
||||
* SyncStartForAsyncInvokeFeature is present on the binding associated
|
||||
* with a stub. There is no type associated with this property on the
|
||||
* request context. Its presence is what triggers the 'prevent' behavior.
|
||||
*/
|
||||
public static final String PREVENT_SYNC_START_FOR_ASYNC_INVOKE = "com.sun.xml.internal.ws.client.StubRequestSyncStartForAsyncInvoke";
|
||||
|
||||
/**
|
||||
* Reuse pipelines as it's expensive to create.
|
||||
* <p>
|
||||
* Set to null when {@link #close() closed}.
|
||||
*/
|
||||
private Pool<Tube> tubes;
|
||||
|
||||
private final Engine engine;
|
||||
|
||||
/**
|
||||
* The {@link WSServiceDelegate} object that owns us.
|
||||
*/
|
||||
protected final WSServiceDelegate owner;
|
||||
|
||||
/**
|
||||
* Non-null if this stub is configured to talk to an EPR.
|
||||
* <p>
|
||||
* When this field is non-null, its reference parameters are sent as out-bound headers.
|
||||
* This field can be null even when addressing is enabled, but if the addressing is
|
||||
* not enabled, this field must be null.
|
||||
* <p>
|
||||
* Unlike endpoint address, we are not letting users to change the EPR,
|
||||
* as it contains references to services and so on that we don't want to change.
|
||||
*/
|
||||
protected
|
||||
@Nullable
|
||||
WSEndpointReference endpointReference;
|
||||
|
||||
protected final BindingImpl binding;
|
||||
|
||||
protected final WSPortInfo portInfo;
|
||||
|
||||
/**
|
||||
* represents AddressingVersion on binding if enabled, otherwise null;
|
||||
*/
|
||||
protected AddressingVersion addrVersion;
|
||||
|
||||
public RequestContext requestContext = new RequestContext();
|
||||
|
||||
private final RequestContext cleanRequestContext;
|
||||
|
||||
/**
|
||||
* {@link ResponseContext} from the last synchronous operation.
|
||||
*/
|
||||
private ResponseContext responseContext;
|
||||
@Nullable
|
||||
protected final WSDLPort wsdlPort;
|
||||
|
||||
protected QName portname;
|
||||
|
||||
/**
|
||||
* {@link Header}s to be added to outbound {@link Packet}.
|
||||
* The contents is determined by the user.
|
||||
*/
|
||||
@Nullable
|
||||
private volatile Header[] userOutboundHeaders;
|
||||
|
||||
private final
|
||||
@NotNull
|
||||
WSDLProperties wsdlProperties;
|
||||
protected OperationDispatcher operationDispatcher = null;
|
||||
private final
|
||||
@NotNull
|
||||
ManagedObjectManager managedObjectManager;
|
||||
private boolean managedObjectManagerClosed = false;
|
||||
|
||||
private final Set<Component> components = new CopyOnWriteArraySet<Component>();
|
||||
|
||||
/**
|
||||
* @param master The created stub will send messages to this pipe.
|
||||
* @param binding As a {@link BindingProvider}, this object will
|
||||
* return this binding from {@link BindingProvider#getBinding()}.
|
||||
* @param defaultEndPointAddress The destination of the message. The actual destination
|
||||
* could be overridden by {@link RequestContext}.
|
||||
* @param epr To create a stub that sends out reference parameters
|
||||
* of a specific EPR, give that instance. Otherwise null.
|
||||
* Its address field will not be used, and that should be given
|
||||
* separately as the <tt>defaultEndPointAddress</tt>.
|
||||
*/
|
||||
@Deprecated
|
||||
protected Stub(WSServiceDelegate owner, Tube master, BindingImpl binding, WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) {
|
||||
this(owner, master, null, null, binding, wsdlPort, defaultEndPointAddress, epr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param portname The name of this port
|
||||
* @param master The created stub will send messages to this pipe.
|
||||
* @param binding As a {@link BindingProvider}, this object will
|
||||
* return this binding from {@link BindingProvider#getBinding()}.
|
||||
* @param defaultEndPointAddress The destination of the message. The actual destination
|
||||
* could be overridden by {@link RequestContext}.
|
||||
* @param epr To create a stub that sends out reference parameters
|
||||
* of a specific EPR, give that instance. Otherwise null.
|
||||
* Its address field will not be used, and that should be given
|
||||
* separately as the <tt>defaultEndPointAddress</tt>.
|
||||
*/
|
||||
@Deprecated
|
||||
protected Stub(QName portname, WSServiceDelegate owner, Tube master, BindingImpl binding, WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) {
|
||||
this(owner, master, null, portname, binding, wsdlPort, defaultEndPointAddress, epr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param portInfo PortInfo for this stub
|
||||
* @param binding As a {@link BindingProvider}, this object will
|
||||
* return this binding from {@link BindingProvider#getBinding()}.
|
||||
* @param master The created stub will send messages to this pipe.
|
||||
* @param defaultEndPointAddress The destination of the message. The actual destination
|
||||
* could be overridden by {@link RequestContext}.
|
||||
* @param epr To create a stub that sends out reference parameters
|
||||
* of a specific EPR, give that instance. Otherwise null.
|
||||
* Its address field will not be used, and that should be given
|
||||
* separately as the <tt>defaultEndPointAddress</tt>.
|
||||
*/
|
||||
protected Stub(WSPortInfo portInfo, BindingImpl binding, Tube master,EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) {
|
||||
this((WSServiceDelegate) portInfo.getOwner(), master, portInfo, null, binding,portInfo.getPort(), defaultEndPointAddress, epr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param portInfo PortInfo for this stub
|
||||
* @param binding As a {@link BindingProvider}, this object will
|
||||
* return this binding from {@link BindingProvider#getBinding()}.
|
||||
* @param defaultEndPointAddress The destination of the message. The actual destination
|
||||
* could be overridden by {@link RequestContext}.
|
||||
* @param epr To create a stub that sends out reference parameters
|
||||
* of a specific EPR, give that instance. Otherwise null.
|
||||
* Its address field will not be used, and that should be given
|
||||
* separately as the <tt>defaultEndPointAddress</tt>.
|
||||
*/
|
||||
protected Stub(WSPortInfo portInfo, BindingImpl binding, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) {
|
||||
this(portInfo,binding,null, defaultEndPointAddress,epr);
|
||||
|
||||
}
|
||||
|
||||
private Stub(WSServiceDelegate owner, @Nullable Tube master, @Nullable WSPortInfo portInfo, QName portname, BindingImpl binding, @Nullable WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) {
|
||||
Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
|
||||
try {
|
||||
this.owner = owner;
|
||||
this.portInfo = portInfo;
|
||||
this.wsdlPort = wsdlPort != null ? wsdlPort : (portInfo != null ? portInfo.getPort() : null);
|
||||
this.portname = portname;
|
||||
if (portname == null) {
|
||||
if (portInfo != null) {
|
||||
this.portname = portInfo.getPortName();
|
||||
} else if (wsdlPort != null) {
|
||||
this.portname = wsdlPort.getName();
|
||||
}
|
||||
}
|
||||
this.binding = binding;
|
||||
|
||||
ComponentFeature cf = binding.getFeature(ComponentFeature.class);
|
||||
if (cf != null && Target.STUB.equals(cf.getTarget())) {
|
||||
components.add(cf.getComponent());
|
||||
}
|
||||
ComponentsFeature csf = binding.getFeature(ComponentsFeature.class);
|
||||
if (csf != null) {
|
||||
for (ComponentFeature cfi : csf.getComponentFeatures()) {
|
||||
if (Target.STUB.equals(cfi.getTarget()))
|
||||
components.add(cfi.getComponent());
|
||||
}
|
||||
}
|
||||
|
||||
// if there is an EPR, EPR's address should be used for invocation instead of default address
|
||||
if (epr != null) {
|
||||
this.requestContext.setEndPointAddressString(epr.getAddress());
|
||||
} else {
|
||||
this.requestContext.setEndpointAddress(defaultEndPointAddress);
|
||||
}
|
||||
this.engine = new Engine(getStringId(), owner.getContainer(), owner.getExecutor());
|
||||
this.endpointReference = epr;
|
||||
wsdlProperties = (wsdlPort == null) ? new WSDLDirectProperties(owner.getServiceName(), portname) : new WSDLPortProperties(wsdlPort);
|
||||
|
||||
this.cleanRequestContext = this.requestContext.copy();
|
||||
|
||||
// ManagedObjectManager MUST be created before the pipeline
|
||||
// is constructed.
|
||||
|
||||
managedObjectManager = new MonitorRootClient(this).createManagedObjectManager(this);
|
||||
|
||||
if (master != null) {
|
||||
this.tubes = new TubePool(master);
|
||||
} else {
|
||||
this.tubes = new TubePool(createPipeline(portInfo, binding));
|
||||
}
|
||||
|
||||
addrVersion = binding.getAddressingVersion();
|
||||
|
||||
// This needs to happen after createPipeline.
|
||||
// TBD: Check if it needs to happen outside the Stub constructor.
|
||||
managedObjectManager.resumeJMXRegistration();
|
||||
} finally {
|
||||
ContainerResolver.getDefault().exitContainer(old);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pipeline for the given port name.
|
||||
*/
|
||||
private Tube createPipeline(WSPortInfo portInfo, WSBinding binding) {
|
||||
//Check all required WSDL extensions are understood
|
||||
checkAllWSDLExtensionsUnderstood(portInfo, binding);
|
||||
SEIModel seiModel = null;
|
||||
Class sei = null;
|
||||
if (portInfo instanceof SEIPortInfo) {
|
||||
SEIPortInfo sp = (SEIPortInfo) portInfo;
|
||||
seiModel = sp.model;
|
||||
sei = sp.sei;
|
||||
}
|
||||
BindingID bindingId = portInfo.getBindingId();
|
||||
|
||||
TubelineAssembler assembler = TubelineAssemblerFactory.create(
|
||||
Thread.currentThread().getContextClassLoader(), bindingId, owner.getContainer());
|
||||
if (assembler == null) {
|
||||
throw new WebServiceException("Unable to process bindingID=" + bindingId); // TODO: i18n
|
||||
}
|
||||
return assembler.createClient(
|
||||
new ClientTubeAssemblerContext(
|
||||
portInfo.getEndpointAddress(),
|
||||
portInfo.getPort(),
|
||||
this, binding, owner.getContainer(), ((BindingImpl) binding).createCodec(), seiModel, sei));
|
||||
}
|
||||
|
||||
public WSDLPort getWSDLPort() {
|
||||
return wsdlPort;
|
||||
}
|
||||
|
||||
public WSService getService() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public Pool<Tube> getTubes() {
|
||||
return tubes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks only if RespectBindingFeature is enabled
|
||||
* checks if all required wsdl extensions in the
|
||||
* corresponding wsdl:Port are understood when RespectBindingFeature is enabled.
|
||||
* @throws WebServiceException
|
||||
* when any wsdl extension that has wsdl:required=true is not understood
|
||||
*/
|
||||
private static void checkAllWSDLExtensionsUnderstood(WSPortInfo port, WSBinding binding) {
|
||||
if (port.getPort() != null && binding.isFeatureEnabled(RespectBindingFeature.class)) {
|
||||
port.getPort().areRequiredExtensionsUnderstood();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSPortInfo getPortInfo() {
|
||||
return portInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nullable when there is no associated WSDL Model
|
||||
* @return
|
||||
*/
|
||||
public
|
||||
@Nullable
|
||||
OperationDispatcher getOperationDispatcher() {
|
||||
if (operationDispatcher == null && wsdlPort != null) {
|
||||
operationDispatcher = new OperationDispatcher(wsdlPort, binding, null);
|
||||
}
|
||||
return operationDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the port name that this stub is configured to talk to.
|
||||
* <p>
|
||||
* When {@link #wsdlPort} is non-null, the port name is always
|
||||
* the same as {@link WSDLPort#getName()}, but this method
|
||||
* returns a port name even if no WSDL is available for this stub.
|
||||
*/
|
||||
protected abstract
|
||||
@NotNull
|
||||
QName getPortName();
|
||||
|
||||
/**
|
||||
* Gets the service name that this stub is configured to talk to.
|
||||
* <p>
|
||||
* When {@link #wsdlPort} is non-null, the service name is always
|
||||
* the same as the one that's inferred from {@link WSDLPort#getOwner()},
|
||||
* but this method returns a port name even if no WSDL is available for
|
||||
* this stub.
|
||||
*/
|
||||
protected final
|
||||
@NotNull
|
||||
QName getServiceName() {
|
||||
return owner.getServiceName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Executor} to be used for asynchronous method invocations.
|
||||
* <p>
|
||||
* Note that the value this method returns may different from invocations
|
||||
* to invocations. The caller must not cache.
|
||||
*
|
||||
* @return always non-null.
|
||||
*/
|
||||
public final Executor getExecutor() {
|
||||
return owner.getExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes a message to a pipe for processing.
|
||||
* <p>
|
||||
* Unlike {@link Tube} instances,
|
||||
* this method is thread-safe and can be invoked from
|
||||
* multiple threads concurrently.
|
||||
*
|
||||
* @param packet The message to be sent to the server
|
||||
* @param requestContext The {@link RequestContext} when this invocation is originally scheduled.
|
||||
* This must be the same object as {@link #requestContext} for synchronous
|
||||
* invocations, but for asynchronous invocations, it needs to be a snapshot
|
||||
* captured at the point of invocation, to correctly satisfy the spec requirement.
|
||||
* @param receiver Receives the {@link ResponseContext}. Since the spec requires
|
||||
* that the asynchronous invocations must not update response context,
|
||||
* depending on the mode of invocation they have to go to different places.
|
||||
* So we take a setter that abstracts that away.
|
||||
*/
|
||||
protected final Packet process(Packet packet, RequestContext requestContext, ResponseContextReceiver receiver) {
|
||||
packet.isSynchronousMEP = true;
|
||||
packet.component = this;
|
||||
configureRequestPacket(packet, requestContext);
|
||||
Pool<Tube> pool = tubes;
|
||||
if (pool == null) {
|
||||
throw new WebServiceException("close method has already been invoked"); // TODO: i18n
|
||||
}
|
||||
|
||||
Fiber fiber = engine.createFiber();
|
||||
configureFiber(fiber);
|
||||
|
||||
// then send it away!
|
||||
Tube tube = pool.take();
|
||||
|
||||
try {
|
||||
return fiber.runSync(tube, packet);
|
||||
} finally {
|
||||
// this allows us to capture the packet even when the call failed with an exception.
|
||||
// when the call fails with an exception it's no longer a 'reply' but it may provide some information
|
||||
// about what went wrong.
|
||||
|
||||
// note that Packet can still be updated after
|
||||
// ResponseContext is created.
|
||||
Packet reply = (fiber.getPacket() == null) ? packet : fiber.getPacket();
|
||||
receiver.setResponseContext(new ResponseContext(reply));
|
||||
|
||||
pool.recycle(tube);
|
||||
}
|
||||
}
|
||||
|
||||
private void configureRequestPacket(Packet packet, RequestContext requestContext) {
|
||||
// fill in Packet
|
||||
packet.proxy = this;
|
||||
packet.handlerConfig = binding.getHandlerConfig();
|
||||
|
||||
// to make it multi-thread safe we need to first get a stable snapshot
|
||||
Header[] hl = userOutboundHeaders;
|
||||
if (hl != null) {
|
||||
MessageHeaders mh = packet.getMessage().getHeaders();
|
||||
for (Header h : hl) {
|
||||
mh.add(h);
|
||||
}
|
||||
}
|
||||
|
||||
requestContext.fill(packet, (binding.getAddressingVersion() != null));
|
||||
packet.addSatellite(wsdlProperties);
|
||||
|
||||
if (addrVersion != null) {
|
||||
// populate request WS-Addressing headers
|
||||
MessageHeaders headerList = packet.getMessage().getHeaders();
|
||||
AddressingUtils.fillRequestAddressingHeaders(headerList, wsdlPort, binding, packet);
|
||||
|
||||
|
||||
// Spec is not clear on if ReferenceParameters are to be added when addressing is not enabled,
|
||||
// but the EPR has ReferenceParameters.
|
||||
// Current approach: Add ReferenceParameters only if addressing enabled.
|
||||
if (endpointReference != null) {
|
||||
endpointReference.addReferenceParametersToList(packet.getMessage().getHeaders());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes a message through a {@link Tube}line for processing. The processing happens
|
||||
* asynchronously and when the response is available, Fiber.CompletionCallback is
|
||||
* called. The processing could happen on multiple threads.
|
||||
*
|
||||
* <p>
|
||||
* Unlike {@link Tube} instances,
|
||||
* this method is thread-safe and can be invoked from
|
||||
* multiple threads concurrently.
|
||||
*
|
||||
* @param receiver The {@link Response} implementation
|
||||
* @param request The message to be sent to the server
|
||||
* @param requestContext The {@link RequestContext} when this invocation is originally scheduled.
|
||||
* This must be the same object as {@link #requestContext} for synchronous
|
||||
* invocations, but for asynchronous invocations, it needs to be a snapshot
|
||||
* captured at the point of invocation, to correctly satisfy the spec requirement.
|
||||
* @param completionCallback Once the processing is done, the callback is invoked.
|
||||
*/
|
||||
protected final void processAsync(AsyncResponseImpl<?> receiver, Packet request, RequestContext requestContext, final Fiber.CompletionCallback completionCallback) {
|
||||
// fill in Packet
|
||||
request.component = this;
|
||||
configureRequestPacket(request, requestContext);
|
||||
|
||||
final Pool<Tube> pool = tubes;
|
||||
if (pool == null) {
|
||||
throw new WebServiceException("close method has already been invoked"); // TODO: i18n
|
||||
}
|
||||
|
||||
final Fiber fiber = engine.createFiber();
|
||||
configureFiber(fiber);
|
||||
|
||||
receiver.setCancelable(fiber);
|
||||
|
||||
// check race condition on cancel
|
||||
if (receiver.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FiberContextSwitchInterceptorFactory fcsif = owner.getSPI(FiberContextSwitchInterceptorFactory.class);
|
||||
if (fcsif != null) {
|
||||
fiber.addInterceptor(fcsif.create());
|
||||
}
|
||||
|
||||
// then send it away!
|
||||
final Tube tube = pool.take();
|
||||
|
||||
Fiber.CompletionCallback fiberCallback = new Fiber.CompletionCallback() {
|
||||
@Override
|
||||
public void onCompletion(@NotNull Packet response) {
|
||||
pool.recycle(tube);
|
||||
completionCallback.onCompletion(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompletion(@NotNull Throwable error) {
|
||||
// let's not reuse tubes as they might be in a wrong state, so not
|
||||
// calling pool.recycle()
|
||||
completionCallback.onCompletion(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Check for SyncStartForAsyncInvokeFeature
|
||||
|
||||
fiber.start(tube, request, fiberCallback,
|
||||
getBinding().isFeatureEnabled(SyncStartForAsyncFeature.class) &&
|
||||
!requestContext.containsKey(PREVENT_SYNC_START_FOR_ASYNC_INVOKE));
|
||||
}
|
||||
|
||||
protected void configureFiber(Fiber fiber) {
|
||||
// no-op in the base class, but can be used by derived classes to configure the Fiber prior
|
||||
// to invocation
|
||||
}
|
||||
|
||||
private static final Logger monitoringLogger = Logger.getLogger(com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".monitoring");
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
TubePool tp = (TubePool) tubes;
|
||||
if (tp != null) {
|
||||
// multi-thread safety of 'close' needs to be considered more carefully.
|
||||
// some calls might be pending while this method is invoked. Should we
|
||||
// block until they are complete, or should we abort them (but how?)
|
||||
Tube p = tp.takeMaster();
|
||||
p.preDestroy();
|
||||
tubes = null;
|
||||
}
|
||||
if (!managedObjectManagerClosed) {
|
||||
try {
|
||||
final ObjectName name = managedObjectManager.getObjectName(managedObjectManager.getRoot());
|
||||
// The name is null when the MOM is a NOOP.
|
||||
if (name != null) {
|
||||
monitoringLogger.log(Level.INFO, "Closing Metro monitoring root: {0}", name);
|
||||
}
|
||||
managedObjectManager.close();
|
||||
} catch (java.io.IOException e) {
|
||||
monitoringLogger.log(Level.WARNING, "Ignoring error when closing Managed Object Manager", e);
|
||||
}
|
||||
managedObjectManagerClosed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final WSBinding getBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String, Object> getRequestContext() {
|
||||
return requestContext.asMap();
|
||||
}
|
||||
|
||||
public void resetRequestContext() {
|
||||
requestContext = cleanRequestContext.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResponseContext getResponseContext() {
|
||||
return responseContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResponseContext(ResponseContext rc) {
|
||||
this.responseContext = rc;
|
||||
}
|
||||
|
||||
private String getStringId() {
|
||||
return RuntimeVersion.VERSION + ": Stub for " + getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getStringId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final WSEndpointReference getWSEndpointReference() {
|
||||
if (binding.getBindingID().equals(HTTPBinding.HTTP_BINDING)) {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
ClientMessages.UNSUPPORTED_OPERATION("BindingProvider.getEndpointReference(Class<T> class)", "XML/HTTP Binding", "SOAP11 or SOAP12 Binding")
|
||||
);
|
||||
}
|
||||
|
||||
if (endpointReference != null) {
|
||||
return endpointReference;
|
||||
}
|
||||
|
||||
String eprAddress = requestContext.getEndpointAddress().toString();
|
||||
QName portTypeName = null;
|
||||
String wsdlAddress = null;
|
||||
List<WSEndpointReference.EPRExtension> wsdlEPRExtensions = new ArrayList<WSEndpointReference.EPRExtension>();
|
||||
if (wsdlPort != null) {
|
||||
portTypeName = wsdlPort.getBinding().getPortTypeName();
|
||||
wsdlAddress = eprAddress + "?wsdl";
|
||||
|
||||
//gather EPRExtensions specified in WSDL.
|
||||
try {
|
||||
WSEndpointReference wsdlEpr = wsdlPort.getEPR();
|
||||
if (wsdlEpr != null) {
|
||||
for (WSEndpointReference.EPRExtension extnEl : wsdlEpr.getEPRExtensions()) {
|
||||
wsdlEPRExtensions.add(new WSEPRExtension(
|
||||
XMLStreamBuffer.createNewBufferFromXMLStreamReader(extnEl.readAsXMLStreamReader()), extnEl.getQName()));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (XMLStreamException ex) {
|
||||
throw new WebServiceException(ex);
|
||||
}
|
||||
}
|
||||
AddressingVersion av = AddressingVersion.W3C;
|
||||
this.endpointReference = new WSEndpointReference(
|
||||
av, eprAddress, getServiceName(), getPortName(), portTypeName, null, wsdlAddress, null, wsdlEPRExtensions, null);
|
||||
|
||||
return this.endpointReference;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final W3CEndpointReference getEndpointReference() {
|
||||
if (binding.getBindingID().equals(HTTPBinding.HTTP_BINDING)) {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
ClientMessages.UNSUPPORTED_OPERATION("BindingProvider.getEndpointReference()", "XML/HTTP Binding", "SOAP11 or SOAP12 Binding"));
|
||||
}
|
||||
return getEndpointReference(W3CEndpointReference.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T extends EndpointReference> T getEndpointReference(Class<T> clazz) {
|
||||
return getWSEndpointReference().toSpec(clazz);
|
||||
}
|
||||
|
||||
public
|
||||
@NotNull
|
||||
@Override
|
||||
ManagedObjectManager getManagedObjectManager() {
|
||||
return managedObjectManager;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// WSBindingProvider methods
|
||||
//
|
||||
//
|
||||
@Override
|
||||
public final void setOutboundHeaders(List<Header> headers) {
|
||||
if (headers == null) {
|
||||
this.userOutboundHeaders = null;
|
||||
} else {
|
||||
for (Header h : headers) {
|
||||
if (h == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
userOutboundHeaders = headers.toArray(new Header[headers.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setOutboundHeaders(Header... headers) {
|
||||
if (headers == null) {
|
||||
this.userOutboundHeaders = null;
|
||||
} else {
|
||||
for (Header h : headers) {
|
||||
if (h == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
Header[] hl = new Header[headers.length];
|
||||
System.arraycopy(headers, 0, hl, 0, headers.length);
|
||||
userOutboundHeaders = hl;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Header> getInboundHeaders() {
|
||||
return Collections.unmodifiableList(((MessageHeaders)
|
||||
responseContext.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY)).asList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setAddress(String address) {
|
||||
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, address);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> S getSPI(Class<S> spiType) {
|
||||
for (Component c : components) {
|
||||
S s = c.getSPI(spiType);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return owner.getSPI(spiType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Component> getComponents() {
|
||||
return components;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,971 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.ws.Closeable;
|
||||
import com.sun.xml.internal.ws.api.BindingID;
|
||||
import com.sun.xml.internal.ws.api.ComponentFeature;
|
||||
import com.sun.xml.internal.ws.api.ComponentsFeature;
|
||||
import com.sun.xml.internal.ws.api.ComponentFeature.Target;
|
||||
import com.sun.xml.internal.ws.api.EndpointAddress;
|
||||
import com.sun.xml.internal.ws.api.WSService;
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.client.ServiceInterceptor;
|
||||
import com.sun.xml.internal.ws.api.client.ServiceInterceptorFactory;
|
||||
import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
|
||||
import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
|
||||
import com.sun.xml.internal.ws.api.databinding.MetadataReader;
|
||||
import com.sun.xml.internal.ws.api.model.SEIModel;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLModel;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLService;
|
||||
import com.sun.xml.internal.ws.api.pipe.Stubs;
|
||||
import com.sun.xml.internal.ws.api.server.Container;
|
||||
import com.sun.xml.internal.ws.api.server.ContainerResolver;
|
||||
import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
|
||||
import com.sun.xml.internal.ws.client.HandlerConfigurator.AnnotationConfigurator;
|
||||
import com.sun.xml.internal.ws.client.HandlerConfigurator.HandlerResolverImpl;
|
||||
import com.sun.xml.internal.ws.client.sei.SEIStub;
|
||||
import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature;
|
||||
import com.sun.xml.internal.ws.developer.UsesJAXBContextFeature;
|
||||
import com.sun.xml.internal.ws.developer.WSBindingProvider;
|
||||
import com.sun.xml.internal.ws.model.RuntimeModeler;
|
||||
import com.sun.xml.internal.ws.model.SOAPSEIModel;
|
||||
import com.sun.xml.internal.ws.resources.ClientMessages;
|
||||
import com.sun.xml.internal.ws.resources.DispatchMessages;
|
||||
import com.sun.xml.internal.ws.resources.ProviderApiMessages;
|
||||
import com.sun.xml.internal.ws.util.JAXWSUtils;
|
||||
import com.sun.xml.internal.ws.util.ServiceConfigurationError;
|
||||
import com.sun.xml.internal.ws.util.ServiceFinder;
|
||||
import com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser;
|
||||
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.jws.HandlerChain;
|
||||
import javax.jws.WebService;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.ws.BindingProvider;
|
||||
import javax.xml.ws.Dispatch;
|
||||
import javax.xml.ws.EndpointReference;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebServiceClient;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import javax.xml.ws.WebServiceFeature;
|
||||
import javax.xml.ws.handler.HandlerResolver;
|
||||
import javax.xml.ws.soap.AddressingFeature;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import static com.sun.xml.internal.ws.util.xml.XmlUtil.createDefaultCatalogResolver;
|
||||
|
||||
/**
|
||||
* <code>Service</code> objects provide the client view of a Web service.
|
||||
*
|
||||
* <p><code>Service</code> acts as a factory of the following:
|
||||
* <ul>
|
||||
* <li>Proxies for a target service endpoint.
|
||||
* <li>Instances of <code>javax.xml.ws.Dispatch</code> for
|
||||
* dynamic message-oriented invocation of a remote
|
||||
* operation.
|
||||
* </li>
|
||||
*
|
||||
* <p>The ports available on a service can be enumerated using the
|
||||
* <code>getPorts</code> method. Alternatively, you can pass a
|
||||
* service endpoint interface to the unary <code>getPort</code> method
|
||||
* and let the runtime select a compatible port.
|
||||
*
|
||||
* <p>Handler chains for all the objects created by a <code>Service</code>
|
||||
* can be set by means of the provided <code>HandlerRegistry</code>.
|
||||
*
|
||||
* <p>An <code>Executor</code> may be set on the service in order
|
||||
* to gain better control over the threads used to dispatch asynchronous
|
||||
* callbacks. For instance, thread pooling with certain parameters
|
||||
* can be enabled by creating a <code>ThreadPoolExecutor</code> and
|
||||
* registering it with the service.
|
||||
*
|
||||
* @author WS Development Team
|
||||
* @see Executor
|
||||
* @since JAX-WS 2.0
|
||||
*/
|
||||
public class WSServiceDelegate extends WSService {
|
||||
/**
|
||||
* All ports.
|
||||
* <p>
|
||||
* This includes ports statically known to WSDL, as well as
|
||||
* ones that are dynamically added
|
||||
* through {@link #addPort(QName, String, String)}.
|
||||
* <p>
|
||||
* For statically known ports we'll have {@link SEIPortInfo}.
|
||||
* For dynamically added ones we'll have {@link PortInfo}.
|
||||
*/
|
||||
private final Map<QName, PortInfo> ports = new HashMap<QName, PortInfo>();
|
||||
// For monitoring
|
||||
protected Map<QName, PortInfo> getQNameToPortInfoMap() { return ports; }
|
||||
|
||||
/**
|
||||
* Whenever we create {@link BindingProvider}, we use this to configure handlers.
|
||||
*/
|
||||
private @NotNull HandlerConfigurator handlerConfigurator = new HandlerResolverImpl(null);
|
||||
|
||||
private final Class<? extends Service> serviceClass;
|
||||
|
||||
private final WebServiceFeatureList features;
|
||||
|
||||
/**
|
||||
* Name of the service for which this {@link WSServiceDelegate} is created for.
|
||||
*/
|
||||
private final @NotNull QName serviceName;
|
||||
|
||||
/**
|
||||
* Information about SEI, keyed by their interface type.
|
||||
*/
|
||||
// private final Map<Class,SEIPortInfo> seiContext = new HashMap<Class,SEIPortInfo>();
|
||||
private final Map<QName,SEIPortInfo> seiContext = new HashMap<QName,SEIPortInfo>();
|
||||
|
||||
// This executor is used for all the async invocations for all proxies
|
||||
// created from this service. But once the proxy is created, then changing
|
||||
// this executor doesn't affect the already created proxies.
|
||||
private volatile Executor executor;
|
||||
|
||||
/**
|
||||
* The WSDL service that this {@link Service} object represents.
|
||||
* <p>
|
||||
* This field is null iff no WSDL is given to {@link Service}.
|
||||
* This fiels can be be null if the service is created without wsdl but later
|
||||
* the epr supplies a wsdl that can be parsed.
|
||||
*/
|
||||
private @Nullable WSDLService wsdlService;
|
||||
|
||||
private final Container container;
|
||||
/**
|
||||
* Multiple {@link ServiceInterceptor}s are aggregated into one.
|
||||
*/
|
||||
/*package*/ final @NotNull ServiceInterceptor serviceInterceptor;
|
||||
private URL wsdlURL;
|
||||
|
||||
public WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class<? extends Service> serviceClass, WebServiceFeature... features) {
|
||||
this(wsdlDocumentLocation, serviceName, serviceClass, new WebServiceFeatureList(features));
|
||||
}
|
||||
|
||||
protected WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class<? extends Service> serviceClass, WebServiceFeatureList features) {
|
||||
this(
|
||||
wsdlDocumentLocation==null ? null : new StreamSource(wsdlDocumentLocation.toExternalForm()),
|
||||
serviceName,serviceClass, features);
|
||||
wsdlURL = wsdlDocumentLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceClass
|
||||
* Either {@link Service}.class or other generated service-derived classes.
|
||||
*/
|
||||
public WSServiceDelegate(@Nullable Source wsdl, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeature... features) {
|
||||
this(wsdl, serviceName, serviceClass, new WebServiceFeatureList(features));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceClass
|
||||
* Either {@link Service}.class or other generated service-derived classes.
|
||||
*/
|
||||
protected WSServiceDelegate(@Nullable Source wsdl, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeatureList features) {
|
||||
this(wsdl, null, serviceName, serviceClass, features);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceClass
|
||||
* Either {@link Service}.class or other generated service-derived classes.
|
||||
*/
|
||||
public WSServiceDelegate(@Nullable Source wsdl, @Nullable WSDLService service, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeature... features) {
|
||||
this(wsdl, service, serviceName, serviceClass, new WebServiceFeatureList(features));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceClass
|
||||
* Either {@link Service}.class or other generated service-derived classes.
|
||||
*/
|
||||
public WSServiceDelegate(@Nullable Source wsdl, @Nullable WSDLService service, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeatureList features) {
|
||||
//we cant create a Service without serviceName
|
||||
if (serviceName == null) {
|
||||
throw new WebServiceException(ClientMessages.INVALID_SERVICE_NAME_NULL(null));
|
||||
}
|
||||
|
||||
this.features = features;
|
||||
|
||||
InitParams initParams = INIT_PARAMS.get();
|
||||
INIT_PARAMS.set(null); // mark it as consumed
|
||||
if(initParams==null) {
|
||||
initParams = EMPTY_PARAMS;
|
||||
}
|
||||
|
||||
this.serviceName = serviceName;
|
||||
this.serviceClass = serviceClass;
|
||||
Container tContainer = initParams.getContainer()!=null ? initParams.getContainer() : ContainerResolver.getInstance().getContainer();
|
||||
if (tContainer == Container.NONE) {
|
||||
tContainer = new ClientContainer();
|
||||
}
|
||||
this.container = tContainer;
|
||||
|
||||
ComponentFeature cf = this.features.get(ComponentFeature.class);
|
||||
if (cf != null) {
|
||||
switch(cf.getTarget()) {
|
||||
case SERVICE:
|
||||
getComponents().add(cf.getComponent());
|
||||
break;
|
||||
case CONTAINER:
|
||||
this.container.getComponents().add(cf.getComponent());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
ComponentsFeature csf = this.features.get(ComponentsFeature.class);
|
||||
if (csf != null) {
|
||||
for (ComponentFeature cfi : csf.getComponentFeatures()) {
|
||||
switch(cfi.getTarget()) {
|
||||
case SERVICE:
|
||||
getComponents().add(cfi.getComponent());
|
||||
break;
|
||||
case CONTAINER:
|
||||
this.container.getComponents().add(cfi.getComponent());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load interceptor
|
||||
ServiceInterceptor interceptor = ServiceInterceptorFactory.load(this, Thread.currentThread().getContextClassLoader());
|
||||
ServiceInterceptor si = container.getSPI(ServiceInterceptor.class);
|
||||
if (si != null) {
|
||||
interceptor = ServiceInterceptor.aggregate(interceptor, si);
|
||||
}
|
||||
this.serviceInterceptor = interceptor;
|
||||
|
||||
if (service == null) {
|
||||
//if wsdl is null, try and get it from the WebServiceClient.wsdlLocation
|
||||
if(wsdl == null){
|
||||
if(serviceClass != Service.class){
|
||||
WebServiceClient wsClient = AccessController.doPrivileged(new PrivilegedAction<WebServiceClient>() {
|
||||
public WebServiceClient run() {
|
||||
return serviceClass.getAnnotation(WebServiceClient.class);
|
||||
}
|
||||
});
|
||||
String wsdlLocation = wsClient.wsdlLocation();
|
||||
wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation));
|
||||
wsdl = new StreamSource(wsdlLocation);
|
||||
}
|
||||
}
|
||||
if (wsdl != null) {
|
||||
try {
|
||||
URL url = wsdl.getSystemId()==null ? null : JAXWSUtils.getEncodedURL(wsdl.getSystemId());
|
||||
WSDLModel model = parseWSDL(url, wsdl, serviceClass);
|
||||
service = model.getService(this.serviceName);
|
||||
if (service == null)
|
||||
throw new WebServiceException(
|
||||
ClientMessages.INVALID_SERVICE_NAME(this.serviceName,
|
||||
buildNameList(model.getServices().keySet())));
|
||||
// fill in statically known ports
|
||||
for (WSDLPort port : service.getPorts())
|
||||
ports.put(port.getName(), new PortInfo(this, port));
|
||||
} catch (MalformedURLException e) {
|
||||
throw new WebServiceException(ClientMessages.INVALID_WSDL_URL(wsdl.getSystemId()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// fill in statically known ports
|
||||
for (WSDLPort port : service.getPorts())
|
||||
ports.put(port.getName(), new PortInfo(this, port));
|
||||
}
|
||||
this.wsdlService = service;
|
||||
|
||||
if (serviceClass != Service.class) {
|
||||
//if @HandlerChain present, set HandlerResolver on service context
|
||||
HandlerChain handlerChain =
|
||||
AccessController.doPrivileged(new PrivilegedAction<HandlerChain>() {
|
||||
public HandlerChain run() {
|
||||
return serviceClass.getAnnotation(HandlerChain.class);
|
||||
}
|
||||
});
|
||||
if (handlerChain != null)
|
||||
handlerConfigurator = new AnnotationConfigurator(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the WSDL and builds {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLModel}.
|
||||
* @param wsdlDocumentLocation
|
||||
* Either this or <tt>wsdl</tt> parameter must be given.
|
||||
* Null location means the system won't be able to resolve relative references in the WSDL,
|
||||
*/
|
||||
private WSDLModel parseWSDL(URL wsdlDocumentLocation, Source wsdlSource, Class serviceClass) {
|
||||
try {
|
||||
return RuntimeWSDLParser.parse(wsdlDocumentLocation, wsdlSource, createCatalogResolver(),
|
||||
true, getContainer(), serviceClass, ServiceFinder.find(WSDLParserExtension.class).toArray());
|
||||
} catch (IOException e) {
|
||||
throw new WebServiceException(e);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new WebServiceException(e);
|
||||
} catch (SAXException e) {
|
||||
throw new WebServiceException(e);
|
||||
} catch (ServiceConfigurationError e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected EntityResolver createCatalogResolver() {
|
||||
return createDefaultCatalogResolver();
|
||||
}
|
||||
|
||||
public Executor getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
public void setExecutor(Executor executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public HandlerResolver getHandlerResolver() {
|
||||
return handlerConfigurator.getResolver();
|
||||
}
|
||||
|
||||
/*package*/ final HandlerConfigurator getHandlerConfigurator() {
|
||||
return handlerConfigurator;
|
||||
}
|
||||
|
||||
public void setHandlerResolver(HandlerResolver resolver) {
|
||||
handlerConfigurator = new HandlerResolverImpl(resolver);
|
||||
}
|
||||
|
||||
public <T> T getPort(QName portName, Class<T> portInterface) throws WebServiceException {
|
||||
return getPort(portName, portInterface, EMPTY_FEATURES);
|
||||
}
|
||||
|
||||
public <T> T getPort(QName portName, Class<T> portInterface, WebServiceFeature... features) {
|
||||
if (portName == null || portInterface == null)
|
||||
throw new IllegalArgumentException();
|
||||
WSDLService tWsdlService = this.wsdlService;
|
||||
if (tWsdlService == null) {
|
||||
// assigning it to local variable and not setting it back to this.wsdlService intentionally
|
||||
// as we don't want to include the service instance with information gathered from sei
|
||||
tWsdlService = getWSDLModelfromSEI(portInterface);
|
||||
//still null? throw error need wsdl metadata to create a proxy
|
||||
if (tWsdlService == null) {
|
||||
throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName()));
|
||||
}
|
||||
|
||||
}
|
||||
WSDLPort portModel = getPortModel(tWsdlService, portName);
|
||||
return getPort(portModel.getEPR(), portName, portInterface, new WebServiceFeatureList(features));
|
||||
}
|
||||
|
||||
public <T> T getPort(EndpointReference epr, Class<T> portInterface, WebServiceFeature... features) {
|
||||
return getPort(WSEndpointReference.create(epr),portInterface,features);
|
||||
}
|
||||
|
||||
public <T> T getPort(WSEndpointReference wsepr, Class<T> portInterface, WebServiceFeature... features) {
|
||||
//get the portType from SEI, so that it can be used if EPR does n't have endpointName
|
||||
WebServiceFeatureList featureList = new WebServiceFeatureList(features);
|
||||
QName portTypeName = RuntimeModeler.getPortTypeName(portInterface, getMetadadaReader(featureList, portInterface.getClassLoader()));
|
||||
//if port name is not specified in EPR, it will use portTypeName to get it from the WSDL model.
|
||||
QName portName = getPortNameFromEPR(wsepr, portTypeName);
|
||||
return getPort(wsepr,portName,portInterface, featureList);
|
||||
}
|
||||
|
||||
protected <T> T getPort(WSEndpointReference wsepr, QName portName, Class<T> portInterface,
|
||||
WebServiceFeatureList features) {
|
||||
ComponentFeature cf = features.get(ComponentFeature.class);
|
||||
if (cf != null && !Target.STUB.equals(cf.getTarget())) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
ComponentsFeature csf = features.get(ComponentsFeature.class);
|
||||
if (csf != null) {
|
||||
for (ComponentFeature cfi : csf.getComponentFeatures()) {
|
||||
if (!Target.STUB.equals(cfi.getTarget()))
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
features.addAll(this.features);
|
||||
|
||||
SEIPortInfo spi = addSEI(portName, portInterface, features);
|
||||
return createEndpointIFBaseProxy(wsepr,portName,portInterface,features, spi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getPort(Class<T> portInterface, WebServiceFeature... features) {
|
||||
//get the portType from SEI
|
||||
QName portTypeName = RuntimeModeler.getPortTypeName(portInterface, getMetadadaReader(new WebServiceFeatureList(features), portInterface.getClassLoader()));
|
||||
WSDLService tmpWsdlService = this.wsdlService;
|
||||
if (tmpWsdlService == null) {
|
||||
// assigning it to local variable and not setting it back to this.wsdlService intentionally
|
||||
// as we don't want to include the service instance with information gathered from sei
|
||||
tmpWsdlService = getWSDLModelfromSEI(portInterface);
|
||||
//still null? throw error need wsdl metadata to create a proxy
|
||||
if(tmpWsdlService == null) {
|
||||
throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName()));
|
||||
}
|
||||
}
|
||||
//get the first port corresponding to the SEI
|
||||
WSDLPort port = tmpWsdlService.getMatchingPort(portTypeName);
|
||||
if (port == null) {
|
||||
throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName));
|
||||
}
|
||||
QName portName = port.getName();
|
||||
return getPort(portName, portInterface,features);
|
||||
}
|
||||
|
||||
public <T> T getPort(Class<T> portInterface) throws WebServiceException {
|
||||
return getPort(portInterface, EMPTY_FEATURES);
|
||||
}
|
||||
|
||||
public void addPort(QName portName, String bindingId, String endpointAddress) throws WebServiceException {
|
||||
if (!ports.containsKey(portName)) {
|
||||
BindingID bid = (bindingId == null) ? BindingID.SOAP11_HTTP : BindingID.parse(bindingId);
|
||||
ports.put(portName,
|
||||
new PortInfo(this, (endpointAddress == null) ? null :
|
||||
EndpointAddress.create(endpointAddress), portName, bid));
|
||||
} else
|
||||
throw new WebServiceException(DispatchMessages.DUPLICATE_PORT(portName.toString()));
|
||||
}
|
||||
|
||||
|
||||
public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode) throws WebServiceException {
|
||||
return createDispatch(portName, aClass, mode, EMPTY_FEATURES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Dispatch<T> createDispatch(QName portName, WSEndpointReference wsepr, Class<T> aClass, Service.Mode mode, WebServiceFeature... features) {
|
||||
return createDispatch(portName, wsepr, aClass, mode, new WebServiceFeatureList(features));
|
||||
}
|
||||
|
||||
public <T> Dispatch<T> createDispatch(QName portName, WSEndpointReference wsepr, Class<T> aClass, Service.Mode mode, WebServiceFeatureList features) {
|
||||
PortInfo port = safeGetPort(portName);
|
||||
|
||||
ComponentFeature cf = features.get(ComponentFeature.class);
|
||||
if (cf != null && !Target.STUB.equals(cf.getTarget())) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
ComponentsFeature csf = features.get(ComponentsFeature.class);
|
||||
if (csf != null) {
|
||||
for (ComponentFeature cfi : csf.getComponentFeatures()) {
|
||||
if (!Target.STUB.equals(cfi.getTarget()))
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
features.addAll(this.features);
|
||||
|
||||
BindingImpl binding = port.createBinding(features, null, null);
|
||||
binding.setMode(mode);
|
||||
Dispatch<T> dispatch = Stubs.createDispatch(port, this, binding, aClass, mode, wsepr);
|
||||
serviceInterceptor.postCreateDispatch((WSBindingProvider) dispatch);
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode, WebServiceFeature... features) {
|
||||
return createDispatch(portName, aClass, mode, new WebServiceFeatureList(features));
|
||||
}
|
||||
|
||||
public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode, WebServiceFeatureList features) {
|
||||
WSEndpointReference wsepr = null;
|
||||
boolean isAddressingEnabled = false;
|
||||
AddressingFeature af = features.get(AddressingFeature.class);
|
||||
if (af == null) {
|
||||
af = this.features.get(AddressingFeature.class);
|
||||
}
|
||||
if (af != null && af.isEnabled())
|
||||
isAddressingEnabled = true;
|
||||
MemberSubmissionAddressingFeature msa = features.get(MemberSubmissionAddressingFeature.class);
|
||||
if (msa == null) {
|
||||
msa = this.features.get(MemberSubmissionAddressingFeature.class);
|
||||
}
|
||||
if (msa != null && msa.isEnabled())
|
||||
isAddressingEnabled = true;
|
||||
if(isAddressingEnabled && wsdlService != null && wsdlService.get(portName) != null) {
|
||||
wsepr = wsdlService.get(portName).getEPR();
|
||||
}
|
||||
return createDispatch(portName, wsepr, aClass, mode, features);
|
||||
}
|
||||
|
||||
public <T> Dispatch<T> createDispatch(EndpointReference endpointReference, Class<T> type, Service.Mode mode, WebServiceFeature... features) {
|
||||
WSEndpointReference wsepr = new WSEndpointReference(endpointReference);
|
||||
QName portName = addPortEpr(wsepr);
|
||||
return createDispatch(portName, wsepr, type, mode, features);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains {@link PortInfo} for the given name, with error check.
|
||||
*/
|
||||
public
|
||||
@NotNull
|
||||
PortInfo safeGetPort(QName portName) {
|
||||
PortInfo port = ports.get(portName);
|
||||
if (port == null) {
|
||||
throw new WebServiceException(ClientMessages.INVALID_PORT_NAME(portName, buildNameList(ports.keySet())));
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
private StringBuilder buildNameList(Collection<QName> names) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (QName qn : names) {
|
||||
if (sb.length() > 0) sb.append(',');
|
||||
sb.append(qn);
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
public EndpointAddress getEndpointAddress(QName qName) {
|
||||
PortInfo p = ports.get(qName);
|
||||
return p != null ? p.targetEndpoint : null;
|
||||
}
|
||||
|
||||
public Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode) throws WebServiceException {
|
||||
return createDispatch(portName, jaxbContext, mode, EMPTY_FEATURES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dispatch<Object> createDispatch(QName portName, WSEndpointReference wsepr, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeature... features) {
|
||||
return createDispatch(portName, wsepr, jaxbContext, mode, new WebServiceFeatureList(features));
|
||||
}
|
||||
|
||||
protected Dispatch<Object> createDispatch(QName portName, WSEndpointReference wsepr, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeatureList features) {
|
||||
PortInfo port = safeGetPort(portName);
|
||||
|
||||
ComponentFeature cf = features.get(ComponentFeature.class);
|
||||
if (cf != null && !Target.STUB.equals(cf.getTarget())) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
ComponentsFeature csf = features.get(ComponentsFeature.class);
|
||||
if (csf != null) {
|
||||
for (ComponentFeature cfi : csf.getComponentFeatures()) {
|
||||
if (!Target.STUB.equals(cfi.getTarget()))
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
features.addAll(this.features);
|
||||
|
||||
BindingImpl binding = port.createBinding(features, null, null);
|
||||
binding.setMode(mode);
|
||||
Dispatch<Object> dispatch = Stubs.createJAXBDispatch(
|
||||
port, binding, jaxbContext, mode,wsepr);
|
||||
serviceInterceptor.postCreateDispatch((WSBindingProvider)dispatch);
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Container getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
public Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeature... webServiceFeatures) {
|
||||
return createDispatch(portName, jaxbContext, mode, new WebServiceFeatureList(webServiceFeatures));
|
||||
}
|
||||
|
||||
protected Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeatureList features) {
|
||||
WSEndpointReference wsepr = null;
|
||||
boolean isAddressingEnabled = false;
|
||||
AddressingFeature af = features.get(AddressingFeature.class);
|
||||
if (af == null) {
|
||||
af = this.features.get(AddressingFeature.class);
|
||||
}
|
||||
if (af != null && af.isEnabled())
|
||||
isAddressingEnabled = true;
|
||||
MemberSubmissionAddressingFeature msa = features.get(MemberSubmissionAddressingFeature.class);
|
||||
if (msa == null) {
|
||||
msa = this.features.get(MemberSubmissionAddressingFeature.class);
|
||||
}
|
||||
if (msa != null && msa.isEnabled())
|
||||
isAddressingEnabled = true;
|
||||
if(isAddressingEnabled && wsdlService != null && wsdlService.get(portName) != null) {
|
||||
wsepr = wsdlService.get(portName).getEPR();
|
||||
}
|
||||
return createDispatch(portName, wsepr, jaxbContext, mode, features);
|
||||
}
|
||||
|
||||
public Dispatch<Object> createDispatch(EndpointReference endpointReference, JAXBContext context, Service.Mode mode, WebServiceFeature... features) {
|
||||
WSEndpointReference wsepr = new WSEndpointReference(endpointReference);
|
||||
QName portName = addPortEpr(wsepr);
|
||||
return createDispatch(portName, wsepr, context, mode, features);
|
||||
}
|
||||
|
||||
private QName addPortEpr(WSEndpointReference wsepr) {
|
||||
if (wsepr == null)
|
||||
throw new WebServiceException(ProviderApiMessages.NULL_EPR());
|
||||
QName eprPortName = getPortNameFromEPR(wsepr, null);
|
||||
//add Port, if it does n't exist;
|
||||
// TODO: what if it has different epr address?
|
||||
{
|
||||
PortInfo portInfo = new PortInfo(this, (wsepr.getAddress() == null) ? null : EndpointAddress.create(wsepr.getAddress()), eprPortName,
|
||||
getPortModel(wsdlService, eprPortName).getBinding().getBindingId());
|
||||
if (!ports.containsKey(eprPortName)) {
|
||||
ports.put(eprPortName, portInfo);
|
||||
}
|
||||
}
|
||||
return eprPortName;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param wsepr EndpointReference from which portName will be extracted.
|
||||
* If EndpointName ( port name) is null in EPR, then it will try to get if from WSDLModel using portType QName
|
||||
* @param portTypeName
|
||||
* should be null in dispatch case
|
||||
* should be non null in SEI case
|
||||
* @return
|
||||
* port name from EPR after validating various metadat elements.
|
||||
* Also if service instance does n't have wsdl,
|
||||
* then it gets the WSDL metadata from EPR and builds wsdl model.
|
||||
*/
|
||||
private QName getPortNameFromEPR(@NotNull WSEndpointReference wsepr, @Nullable QName portTypeName) {
|
||||
QName portName;
|
||||
WSEndpointReference.Metadata metadata = wsepr.getMetaData();
|
||||
QName eprServiceName = metadata.getServiceName();
|
||||
QName eprPortName = metadata.getPortName();
|
||||
if ((eprServiceName != null ) && !eprServiceName.equals(serviceName)) {
|
||||
throw new WebServiceException("EndpointReference WSDL ServiceName differs from Service Instance WSDL Service QName.\n"
|
||||
+ " The two Service QNames must match");
|
||||
}
|
||||
if (wsdlService == null) {
|
||||
Source eprWsdlSource = metadata.getWsdlSource();
|
||||
if (eprWsdlSource == null) {
|
||||
throw new WebServiceException(ProviderApiMessages.NULL_WSDL());
|
||||
}
|
||||
try {
|
||||
WSDLModel eprWsdlMdl = parseWSDL(new URL(wsepr.getAddress()), eprWsdlSource, null);
|
||||
wsdlService = eprWsdlMdl.getService(serviceName);
|
||||
if (wsdlService == null)
|
||||
throw new WebServiceException(ClientMessages.INVALID_SERVICE_NAME(serviceName,
|
||||
buildNameList(eprWsdlMdl.getServices().keySet())));
|
||||
} catch (MalformedURLException e) {
|
||||
throw new WebServiceException(ClientMessages.INVALID_ADDRESS(wsepr.getAddress()));
|
||||
}
|
||||
}
|
||||
portName = eprPortName;
|
||||
|
||||
if (portName == null && portTypeName != null) {
|
||||
//get the first port corresponding to the SEI
|
||||
WSDLPort port = wsdlService.getMatchingPort(portTypeName);
|
||||
if (port == null)
|
||||
throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName));
|
||||
portName = port.getName();
|
||||
}
|
||||
if (portName == null)
|
||||
throw new WebServiceException(ProviderApiMessages.NULL_PORTNAME());
|
||||
if (wsdlService.get(portName) == null)
|
||||
throw new WebServiceException(ClientMessages.INVALID_EPR_PORT_NAME(portName, buildWsdlPortNames()));
|
||||
|
||||
return portName;
|
||||
|
||||
}
|
||||
|
||||
private <T> T createProxy(final Class<T> portInterface, final InvocationHandler pis) {
|
||||
|
||||
// When creating the proxy, use a ClassLoader that can load classes
|
||||
// from both the interface class and also from this classes
|
||||
// classloader. This is necessary when this code is used in systems
|
||||
// such as OSGi where the class loader for the interface class may
|
||||
// not be able to load internal JAX-WS classes like
|
||||
// "WSBindingProvider", but the class loader for this class may not
|
||||
// be able to load the interface class.
|
||||
final ClassLoader loader = getDelegatingLoader(portInterface.getClassLoader(),
|
||||
WSServiceDelegate.class.getClassLoader());
|
||||
|
||||
// accessClassInPackage privilege needs to be granted ...
|
||||
RuntimePermission perm = new RuntimePermission("accessClassInPackage.com.sun." + "xml.internal.*");
|
||||
PermissionCollection perms = perm.newPermissionCollection();
|
||||
perms.add(perm);
|
||||
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<T>() {
|
||||
@Override
|
||||
public T run() {
|
||||
Object proxy = Proxy.newProxyInstance(loader,
|
||||
new Class[]{portInterface, WSBindingProvider.class, Closeable.class}, pis);
|
||||
return portInterface.cast(proxy);
|
||||
}
|
||||
},
|
||||
new AccessControlContext(
|
||||
new ProtectionDomain[]{
|
||||
new ProtectionDomain(null, perms)
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private WSDLService getWSDLModelfromSEI(final Class sei) {
|
||||
WebService ws = AccessController.doPrivileged(new PrivilegedAction<WebService>() {
|
||||
public WebService run() {
|
||||
return (WebService) sei.getAnnotation(WebService.class);
|
||||
}
|
||||
});
|
||||
if (ws == null || ws.wsdlLocation().equals(""))
|
||||
return null;
|
||||
String wsdlLocation = ws.wsdlLocation();
|
||||
wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation));
|
||||
Source wsdl = new StreamSource(wsdlLocation);
|
||||
WSDLService service = null;
|
||||
|
||||
try {
|
||||
URL url = wsdl.getSystemId() == null ? null : new URL(wsdl.getSystemId());
|
||||
WSDLModel model = parseWSDL(url, wsdl, sei);
|
||||
service = model.getService(this.serviceName);
|
||||
if (service == null)
|
||||
throw new WebServiceException(
|
||||
ClientMessages.INVALID_SERVICE_NAME(this.serviceName,
|
||||
buildNameList(model.getServices().keySet())));
|
||||
} catch (MalformedURLException e) {
|
||||
throw new WebServiceException(ClientMessages.INVALID_WSDL_URL(wsdl.getSystemId()));
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
public QName getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
public Class getServiceClass() {
|
||||
return serviceClass;
|
||||
}
|
||||
|
||||
public Iterator<QName> getPorts() throws WebServiceException {
|
||||
// KK: the spec seems to be ambigous about whether
|
||||
// this returns ports that are dynamically added or not.
|
||||
return ports.keySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getWSDLDocumentLocation() {
|
||||
if(wsdlService==null) return null;
|
||||
try {
|
||||
return new URL(wsdlService.getParent().getLocation().getSystemId());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new AssertionError(e); // impossible
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T createEndpointIFBaseProxy(@Nullable WSEndpointReference epr, QName portName, Class<T> portInterface,
|
||||
WebServiceFeatureList webServiceFeatures, SEIPortInfo eif) {
|
||||
//fail if service doesnt have WSDL
|
||||
if (wsdlService == null) {
|
||||
throw new WebServiceException(ClientMessages.INVALID_SERVICE_NO_WSDL(serviceName));
|
||||
}
|
||||
|
||||
if (wsdlService.get(portName)==null) {
|
||||
throw new WebServiceException(
|
||||
ClientMessages.INVALID_PORT_NAME(portName,buildWsdlPortNames()));
|
||||
}
|
||||
|
||||
BindingImpl binding = eif.createBinding(webServiceFeatures, portInterface);
|
||||
InvocationHandler pis = getStubHandler(binding, eif, epr);
|
||||
|
||||
T proxy = createProxy(portInterface, pis);
|
||||
|
||||
if (serviceInterceptor != null) {
|
||||
serviceInterceptor.postCreateProxy((WSBindingProvider)proxy, portInterface);
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
|
||||
protected InvocationHandler getStubHandler(BindingImpl binding, SEIPortInfo eif, @Nullable WSEndpointReference epr) {
|
||||
return new SEIStub(eif, binding, eif.model, epr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists up the port names in WSDL. For error diagnostics.
|
||||
*/
|
||||
private StringBuilder buildWsdlPortNames() {
|
||||
Set<QName> wsdlPortNames = new HashSet<QName>();
|
||||
for (WSDLPort port : wsdlService.getPorts()) {
|
||||
wsdlPortNames.add(port.getName());
|
||||
}
|
||||
return buildNameList(wsdlPortNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@link WSDLPortImpl} with error check.
|
||||
*
|
||||
* @return guaranteed to be non-null.
|
||||
*/
|
||||
public @NotNull WSDLPort getPortModel(WSDLService wsdlService, QName portName) {
|
||||
WSDLPort port = wsdlService.get(portName);
|
||||
if (port == null)
|
||||
throw new WebServiceException(
|
||||
ClientMessages.INVALID_PORT_NAME(portName,buildWsdlPortNames()));
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contributes to the construction of {@link WSServiceDelegate} by filling in
|
||||
* {@link SEIPortInfo} about a given SEI (linked from the {@link Service}-derived class.)
|
||||
*/
|
||||
//todo: valid port in wsdl
|
||||
private SEIPortInfo addSEI(QName portName, Class portInterface, WebServiceFeatureList features) throws WebServiceException {
|
||||
boolean ownModel = useOwnSEIModel(features);
|
||||
if (ownModel) {
|
||||
// Create a new model and do not cache it
|
||||
return createSEIPortInfo(portName, portInterface, features);
|
||||
}
|
||||
|
||||
SEIPortInfo spi = seiContext.get(portName);
|
||||
if (spi == null) {
|
||||
spi = createSEIPortInfo(portName, portInterface, features);
|
||||
seiContext.put(spi.portName, spi);
|
||||
ports.put(spi.portName, spi);
|
||||
}
|
||||
return spi;
|
||||
}
|
||||
|
||||
public SEIModel buildRuntimeModel(QName serviceName, QName portName, Class portInterface, WSDLPort wsdlPort, WebServiceFeatureList features) {
|
||||
DatabindingFactory fac = DatabindingFactory.newInstance();
|
||||
DatabindingConfig config = new DatabindingConfig();
|
||||
config.setContractClass(portInterface);
|
||||
config.getMappingInfo().setServiceName(serviceName);
|
||||
config.setWsdlPort(wsdlPort);
|
||||
config.setFeatures(features);
|
||||
config.setClassLoader(portInterface.getClassLoader());
|
||||
config.getMappingInfo().setPortName(portName);
|
||||
config.setWsdlURL(wsdlURL);
|
||||
// if ExternalMetadataFeature present, ExternalMetadataReader will be created ...
|
||||
config.setMetadataReader(getMetadadaReader(features, portInterface.getClassLoader()));
|
||||
|
||||
com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl)fac.createRuntime(config);
|
||||
|
||||
return rt.getModel();
|
||||
}
|
||||
|
||||
private MetadataReader getMetadadaReader(WebServiceFeatureList features, ClassLoader classLoader) {
|
||||
if (features == null) return null;
|
||||
com.oracle.webservices.internal.api.databinding.ExternalMetadataFeature ef =
|
||||
features.get(com.oracle.webservices.internal.api.databinding.ExternalMetadataFeature.class);
|
||||
// TODO-Miran: would it be necessary to disable secure xml processing?
|
||||
if (ef != null)
|
||||
return ef.getMetadataReader(classLoader, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
private SEIPortInfo createSEIPortInfo(QName portName, Class portInterface, WebServiceFeatureList features) {
|
||||
WSDLPort wsdlPort = getPortModel(wsdlService, portName);
|
||||
SEIModel model = buildRuntimeModel(serviceName, portName, portInterface, wsdlPort, features);
|
||||
|
||||
return new SEIPortInfo(this, portInterface, (SOAPSEIModel) model, wsdlPort);
|
||||
}
|
||||
|
||||
private boolean useOwnSEIModel(WebServiceFeatureList features) {
|
||||
return features.contains(UsesJAXBContextFeature.class);
|
||||
}
|
||||
|
||||
public WSDLService getWsdlService() {
|
||||
return wsdlService;
|
||||
}
|
||||
|
||||
static class DaemonThreadFactory implements ThreadFactory {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread daemonThread = new Thread(r);
|
||||
daemonThread.setDaemon(Boolean.TRUE);
|
||||
return daemonThread;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final WebServiceFeature[] EMPTY_FEATURES = new WebServiceFeature[0];
|
||||
|
||||
private static ClassLoader getDelegatingLoader(ClassLoader loader1, ClassLoader loader2) {
|
||||
if (loader1 == null) return loader2;
|
||||
if (loader2 == null) return loader1;
|
||||
return new DelegatingLoader(loader1, loader2);
|
||||
}
|
||||
|
||||
private static final class DelegatingLoader extends ClassLoader {
|
||||
private final ClassLoader loader;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((loader == null) ? 0 : loader.hashCode());
|
||||
result = prime * result
|
||||
+ ((getParent() == null) ? 0 : getParent().hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DelegatingLoader other = (DelegatingLoader) obj;
|
||||
if (loader == null) {
|
||||
if (other.loader != null)
|
||||
return false;
|
||||
} else if (!loader.equals(other.loader))
|
||||
return false;
|
||||
if (getParent() == null) {
|
||||
if (other.getParent() != null)
|
||||
return false;
|
||||
} else if (!getParent().equals(other.getParent()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
DelegatingLoader(ClassLoader loader1, ClassLoader loader2) {
|
||||
super(loader2);
|
||||
this.loader = loader1;
|
||||
}
|
||||
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
return loader.loadClass(name);
|
||||
}
|
||||
|
||||
protected URL findResource(String name) {
|
||||
return loader.getResource(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
import com.sun.xml.internal.ws.client.PortInfo;
|
||||
import com.sun.xml.internal.ws.encoding.xml.XMLMessage;
|
||||
import com.sun.xml.internal.ws.encoding.xml.XMLMessage.MessageDataSource;
|
||||
import com.sun.xml.internal.ws.message.source.PayloadSourceMessage;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author WS Development Team
|
||||
* @version 1.0
|
||||
*/
|
||||
public class DataSourceDispatch extends DispatchImpl<DataSource> {
|
||||
@Deprecated
|
||||
public DataSourceDispatch(QName port, Service.Mode mode, WSServiceDelegate service, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(port, mode, service, pipe, binding, epr );
|
||||
}
|
||||
|
||||
public DataSourceDispatch(WSPortInfo portInfo, Service.Mode mode,BindingImpl binding, WSEndpointReference epr) {
|
||||
super(portInfo, mode, binding, epr );
|
||||
}
|
||||
|
||||
Packet createPacket(DataSource arg) {
|
||||
|
||||
switch (mode) {
|
||||
case PAYLOAD:
|
||||
throw new IllegalArgumentException("DataSource use is not allowed in Service.Mode.PAYLOAD\n");
|
||||
case MESSAGE:
|
||||
return new Packet(XMLMessage.create(arg, binding.getFeatures()));
|
||||
default:
|
||||
throw new WebServiceException("Unrecognized message mode");
|
||||
}
|
||||
}
|
||||
|
||||
DataSource toReturnValue(Packet response) {
|
||||
Message message = response.getInternalMessage();
|
||||
return (message instanceof MessageDataSource)
|
||||
? ((MessageDataSource)message).getDataSource()
|
||||
: XMLMessage.getDataSource(message, binding.getFeatures());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.ws.api.BindingID;
|
||||
import com.sun.xml.internal.ws.api.SOAPVersion;
|
||||
import com.sun.xml.internal.ws.api.WSBinding;
|
||||
import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.api.message.AddressingUtils;
|
||||
import com.sun.xml.internal.ws.api.message.Attachment;
|
||||
import com.sun.xml.internal.ws.api.message.AttachmentSet;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Fiber;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.server.Container;
|
||||
import com.sun.xml.internal.ws.api.server.ContainerResolver;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.*;
|
||||
import com.sun.xml.internal.ws.encoding.soap.DeserializationException;
|
||||
import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
|
||||
import com.sun.xml.internal.ws.message.AttachmentSetImpl;
|
||||
import com.sun.xml.internal.ws.message.DataHandlerAttachment;
|
||||
import com.sun.xml.internal.ws.resources.DispatchMessages;
|
||||
|
||||
import javax.activation.DataHandler;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.ws.AsyncHandler;
|
||||
import javax.xml.ws.BindingProvider;
|
||||
import javax.xml.ws.Dispatch;
|
||||
import javax.xml.ws.Response;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.Service.Mode;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import javax.xml.ws.handler.MessageContext;
|
||||
import javax.xml.ws.http.HTTPBinding;
|
||||
import javax.xml.ws.soap.SOAPBinding;
|
||||
import javax.xml.ws.soap.SOAPFaultException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>DispatchImpl</code> abstract class provides support
|
||||
* for the dynamic invocation of a service endpoint operation using XML
|
||||
* constructs, JAXB objects or <code>SOAPMessage</code>. The <code>javax.xml.ws.Service</code>
|
||||
* interface acts as a factory for the creation of <code>DispatchImpl</code>
|
||||
* instances.
|
||||
*
|
||||
* @author WS Development Team
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class DispatchImpl<T> extends Stub implements Dispatch<T> {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(DispatchImpl.class.getName());
|
||||
|
||||
final Service.Mode mode;
|
||||
final SOAPVersion soapVersion;
|
||||
final boolean allowFaultResponseMsg;
|
||||
static final long AWAIT_TERMINATION_TIME = 800L;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param port dispatch instance is associated with this wsdl port qName
|
||||
* @param mode Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
|
||||
* @param owner Service that created the Dispatch
|
||||
* @param pipe Master pipe for the pipeline
|
||||
* @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
|
||||
*/
|
||||
@Deprecated
|
||||
protected DispatchImpl(QName port, Service.Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, @Nullable WSEndpointReference epr) {
|
||||
super(port, owner, pipe, binding, (owner.getWsdlService() != null)? owner.getWsdlService().get(port) : null , owner.getEndpointAddress(port), epr);
|
||||
this.mode = mode;
|
||||
this.soapVersion = binding.getSOAPVersion();
|
||||
this.allowFaultResponseMsg = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param portInfo dispatch instance is associated with this portInfo
|
||||
* @param mode Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
|
||||
* @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
|
||||
*/
|
||||
protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, @Nullable WSEndpointReference epr) {
|
||||
this(portInfo, mode, binding, epr, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param portInfo dispatch instance is associated with this portInfo
|
||||
* @param mode Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
|
||||
* @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
|
||||
* @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
|
||||
*/
|
||||
protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
|
||||
this(portInfo, mode, binding, null, epr, allowFaultResponseMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param portInfo dispatch instance is associated with this portInfo
|
||||
* @param mode Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
|
||||
* @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
|
||||
* @param pipe Master pipe for the pipeline
|
||||
* @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
|
||||
*/
|
||||
protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, Tube pipe, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
|
||||
super(portInfo, binding, pipe, portInfo.getEndpointAddress(), epr);
|
||||
this.mode = mode;
|
||||
this.soapVersion = binding.getSOAPVersion();
|
||||
this.allowFaultResponseMsg = allowFaultResponseMsg;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param portportInfo dispatch instance is associated with this wsdl port qName
|
||||
* @param mode Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
|
||||
* @param pipe Master pipe for the pipeline
|
||||
* @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
|
||||
* @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
|
||||
*/
|
||||
protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, Tube pipe, BindingImpl binding, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
|
||||
super(portInfo, binding, pipe, portInfo.getEndpointAddress(), epr);
|
||||
this.mode = mode;
|
||||
this.soapVersion = binding.getSOAPVersion();
|
||||
this.allowFaultResponseMsg = allowFaultResponseMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method that is implemented by each concrete Dispatch class
|
||||
* @param msg message passed in from the client program on the invocation
|
||||
* @return The Message created returned as the Interface in actuallity a
|
||||
* concrete Message Type
|
||||
*/
|
||||
abstract Packet createPacket(T msg);
|
||||
|
||||
/**
|
||||
* Obtains the value to return from the response message.
|
||||
*/
|
||||
abstract T toReturnValue(Packet response);
|
||||
|
||||
public final Response<T> invokeAsync(T param) {
|
||||
Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
|
||||
try {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
dumpParam(param, "invokeAsync(T)");
|
||||
}
|
||||
AsyncInvoker invoker = new DispatchAsyncInvoker(param);
|
||||
AsyncResponseImpl<T> ft = new AsyncResponseImpl<T>(invoker,null);
|
||||
invoker.setReceiver(ft);
|
||||
ft.run();
|
||||
return ft;
|
||||
} finally {
|
||||
ContainerResolver.getDefault().exitContainer(old);
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpParam(T param, String method) {
|
||||
if (param instanceof Packet) {
|
||||
Packet message = (Packet)param;
|
||||
|
||||
String action;
|
||||
String msgId;
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
AddressingVersion av = DispatchImpl.this.getBinding().getAddressingVersion();
|
||||
SOAPVersion sv = DispatchImpl.this.getBinding().getSOAPVersion();
|
||||
action =
|
||||
av != null && message.getMessage() != null ?
|
||||
AddressingUtils.getAction(message.getMessage().getHeaders(), av, sv) : null;
|
||||
msgId =
|
||||
av != null && message.getMessage() != null ?
|
||||
AddressingUtils.getMessageID(message.getMessage().getHeaders(), av, sv) : null;
|
||||
LOGGER.fine("In DispatchImpl." + method + " for message with action: " + action + " and msg ID: " + msgId + " msg: " + message.getMessage());
|
||||
|
||||
if (message.getMessage() == null) {
|
||||
LOGGER.fine("Dispatching null message for action: " + action + " and msg ID: " + msgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public final Future<?> invokeAsync(T param, AsyncHandler<T> asyncHandler) {
|
||||
Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
|
||||
try {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
dumpParam(param, "invokeAsync(T, AsyncHandler<T>)");
|
||||
}
|
||||
AsyncInvoker invoker = new DispatchAsyncInvoker(param);
|
||||
AsyncResponseImpl<T> ft = new AsyncResponseImpl<T>(invoker,asyncHandler);
|
||||
invoker.setReceiver(ft);
|
||||
invoker.setNonNullAsyncHandlerGiven(asyncHandler != null);
|
||||
|
||||
ft.run();
|
||||
return ft;
|
||||
} finally {
|
||||
ContainerResolver.getDefault().exitContainer(old);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously invokes a service.
|
||||
*
|
||||
* See {@link #process(Packet, RequestContext, ResponseContextReceiver)} on
|
||||
* why it takes a {@link RequestContext} and {@link ResponseContextReceiver} as a parameter.
|
||||
*/
|
||||
public final T doInvoke(T in, RequestContext rc, ResponseContextReceiver receiver){
|
||||
Packet response = null;
|
||||
try {
|
||||
try {
|
||||
checkNullAllowed(in, rc, binding, mode);
|
||||
|
||||
Packet message = createPacket(in);
|
||||
message.setState(Packet.State.ClientRequest);
|
||||
resolveEndpointAddress(message, rc);
|
||||
setProperties(message,true);
|
||||
response = process(message,rc,receiver);
|
||||
Message msg = response.getMessage();
|
||||
|
||||
// REVIEW: eliminate allowFaultResponseMsg, but make that behavior default for MessageDispatch, PacketDispatch
|
||||
if(msg != null && msg.isFault() &&
|
||||
!allowFaultResponseMsg) {
|
||||
SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
|
||||
// passing null means there is no checked excpetion we're looking for all
|
||||
// it will get back to us is a protocol exception
|
||||
throw (SOAPFaultException)faultBuilder.createException(null);
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
//TODO: i18nify
|
||||
throw new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(),e);
|
||||
} catch(WebServiceException e){
|
||||
//it could be a WebServiceException or a ProtocolException
|
||||
throw e;
|
||||
} catch(Throwable e){
|
||||
// it could be a RuntimeException resulting due to some internal bug or
|
||||
// its some other exception resulting from user error, wrap it in
|
||||
// WebServiceException
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
|
||||
return toReturnValue(response);
|
||||
} finally {
|
||||
// REVIEW: Move to AsyncTransportProvider
|
||||
if (response != null && response.transportBackChannel != null)
|
||||
response.transportBackChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
public final T invoke(T in) {
|
||||
Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
|
||||
try {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
dumpParam(in, "invoke(T)");
|
||||
}
|
||||
|
||||
return doInvoke(in,requestContext,this);
|
||||
} finally {
|
||||
ContainerResolver.getDefault().exitContainer(old);
|
||||
}
|
||||
}
|
||||
|
||||
public final void invokeOneWay(T in) {
|
||||
Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
|
||||
try {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
dumpParam(in, "invokeOneWay(T)");
|
||||
}
|
||||
|
||||
try {
|
||||
checkNullAllowed(in, requestContext, binding, mode);
|
||||
|
||||
Packet request = createPacket(in);
|
||||
request.setState(Packet.State.ClientRequest);
|
||||
setProperties(request,false);
|
||||
process(request,requestContext,this);
|
||||
} catch(WebServiceException e){
|
||||
//it could be a WebServiceException or a ProtocolException
|
||||
throw e;
|
||||
} catch(Throwable e){
|
||||
// it could be a RuntimeException resulting due to some internal bug or
|
||||
// its some other exception resulting from user error, wrap it in
|
||||
// WebServiceException
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
} finally {
|
||||
ContainerResolver.getDefault().exitContainer(old);
|
||||
}
|
||||
}
|
||||
|
||||
void setProperties(Packet packet, boolean expectReply) {
|
||||
packet.expectReply = expectReply;
|
||||
}
|
||||
|
||||
static boolean isXMLHttp(@NotNull WSBinding binding) {
|
||||
return binding.getBindingId().equals(BindingID.XML_HTTP);
|
||||
}
|
||||
|
||||
static boolean isPAYLOADMode(@NotNull Service.Mode mode) {
|
||||
return mode == Service.Mode.PAYLOAD;
|
||||
}
|
||||
|
||||
static void checkNullAllowed(@Nullable Object in, RequestContext rc, WSBinding binding, Service.Mode mode) {
|
||||
|
||||
if (in != null)
|
||||
return;
|
||||
|
||||
//With HTTP Binding a null invocation parameter can not be used
|
||||
//with HTTP Request Method == POST
|
||||
if (isXMLHttp(binding)){
|
||||
if (methodNotOk(rc))
|
||||
throw new WebServiceException(DispatchMessages.INVALID_NULLARG_XMLHTTP_REQUEST_METHOD(HTTP_REQUEST_METHOD_POST, HTTP_REQUEST_METHOD_GET));
|
||||
} else { //soapBinding
|
||||
if (mode == Service.Mode.MESSAGE )
|
||||
throw new WebServiceException(DispatchMessages.INVALID_NULLARG_SOAP_MSGMODE(mode.name(), Service.Mode.PAYLOAD.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
static boolean methodNotOk(@NotNull RequestContext rc) {
|
||||
String requestMethod = (String)rc.get(MessageContext.HTTP_REQUEST_METHOD);
|
||||
String request = (requestMethod == null)? HTTP_REQUEST_METHOD_POST: requestMethod;
|
||||
// if method == post or put with a null invocation parameter in xml/http binding this is not ok
|
||||
return HTTP_REQUEST_METHOD_POST.equalsIgnoreCase(request) || HTTP_REQUEST_METHOD_PUT.equalsIgnoreCase(request);
|
||||
}
|
||||
|
||||
public static void checkValidSOAPMessageDispatch(WSBinding binding, Service.Mode mode) {
|
||||
// Dispatch<SOAPMessage> is only valid for soap binding and in Service.Mode.MESSAGE
|
||||
if (DispatchImpl.isXMLHttp(binding))
|
||||
throw new WebServiceException(DispatchMessages.INVALID_SOAPMESSAGE_DISPATCH_BINDING(HTTPBinding.HTTP_BINDING, SOAPBinding.SOAP11HTTP_BINDING + " or " + SOAPBinding.SOAP12HTTP_BINDING));
|
||||
if (DispatchImpl.isPAYLOADMode(mode))
|
||||
throw new WebServiceException(DispatchMessages.INVALID_SOAPMESSAGE_DISPATCH_MSGMODE(mode.name(), Service.Mode.MESSAGE.toString()));
|
||||
}
|
||||
|
||||
public static void checkValidDataSourceDispatch(WSBinding binding, Service.Mode mode) {
|
||||
// Dispatch<DataSource> is only valid with xml/http binding and in Service.Mode.MESSAGE
|
||||
if (!DispatchImpl.isXMLHttp(binding))
|
||||
throw new WebServiceException(DispatchMessages.INVALID_DATASOURCE_DISPATCH_BINDING("SOAP/HTTP", HTTPBinding.HTTP_BINDING));
|
||||
if (DispatchImpl.isPAYLOADMode(mode))
|
||||
throw new WebServiceException(DispatchMessages.INVALID_DATASOURCE_DISPATCH_MSGMODE(mode.name(), Service.Mode.MESSAGE.toString()));
|
||||
}
|
||||
|
||||
public final @NotNull QName getPortName() {
|
||||
return portname;
|
||||
}
|
||||
|
||||
void resolveEndpointAddress(@NotNull final Packet message, @NotNull final RequestContext requestContext) {
|
||||
final boolean p = message.packetTakesPriorityOverRequestContext;
|
||||
|
||||
//resolve endpoint look for query parameters, pathInfo
|
||||
String endpoint;
|
||||
if (p && message.endpointAddress != null) {
|
||||
endpoint = message.endpointAddress.toString();
|
||||
} else {
|
||||
endpoint = (String) requestContext.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
|
||||
}
|
||||
// This is existing before packetTakesPriorityOverRequestContext so leaving in place.
|
||||
if (endpoint == null) {
|
||||
if (message.endpointAddress == null) throw new WebServiceException(DispatchMessages.INVALID_NULLARG_URI());
|
||||
endpoint = message.endpointAddress.toString();
|
||||
}
|
||||
|
||||
String pathInfo = null;
|
||||
String queryString = null;
|
||||
if (p && message.invocationProperties.get(MessageContext.PATH_INFO) != null) {
|
||||
pathInfo = (String) message.invocationProperties.get(MessageContext.PATH_INFO);
|
||||
} else if (requestContext.get(MessageContext.PATH_INFO) != null) {
|
||||
pathInfo = (String) requestContext.get(MessageContext.PATH_INFO);
|
||||
}
|
||||
|
||||
if (p && message.invocationProperties.get(MessageContext.QUERY_STRING) != null) {
|
||||
queryString = (String) message.invocationProperties.get(MessageContext.QUERY_STRING);
|
||||
} else if (requestContext.get(MessageContext.QUERY_STRING) != null) {
|
||||
queryString = (String) requestContext.get(MessageContext.QUERY_STRING);
|
||||
}
|
||||
|
||||
if (pathInfo != null || queryString != null) {
|
||||
pathInfo = checkPath(pathInfo);
|
||||
queryString = checkQuery(queryString);
|
||||
if (endpoint != null) {
|
||||
try {
|
||||
final URI endpointURI = new URI(endpoint);
|
||||
endpoint = resolveURI(endpointURI, pathInfo, queryString);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new WebServiceException(DispatchMessages.INVALID_URI(endpoint));
|
||||
}
|
||||
}
|
||||
}
|
||||
// These two lines used to be inside the above if. It is outside so:
|
||||
// - in cases where there is no setting of address on a Packet before invocation or no pathInfo/queryString
|
||||
// this will just put back what it found in the requestContext - basically a noop.
|
||||
// - but when info is in the Packet this will update so it will get used later.
|
||||
// Remember - we are operating on a copied RequestContext at this point - not the sticky one in the Stub.
|
||||
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
|
||||
// This is not necessary because a later step will copy the resolvedEndpoint put above into message.
|
||||
//message.endpointAddress = EndpointAddress.create(endpoint);
|
||||
}
|
||||
|
||||
protected @NotNull String resolveURI(@NotNull URI endpointURI, @Nullable String pathInfo, @Nullable String queryString) {
|
||||
String query = null;
|
||||
String fragment = null;
|
||||
if (queryString != null) {
|
||||
final URI result;
|
||||
try {
|
||||
URI tp = new URI(null, null, endpointURI.getPath(), queryString, null);
|
||||
result = endpointURI.resolve(tp);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new WebServiceException(DispatchMessages.INVALID_QUERY_STRING(queryString));
|
||||
}
|
||||
query = result.getQuery();
|
||||
fragment = result.getFragment();
|
||||
}
|
||||
|
||||
final String path = (pathInfo != null) ? pathInfo : endpointURI.getPath();
|
||||
try {
|
||||
//final URI temp = new URI(null, null, path, query, fragment);
|
||||
//return endpointURI.resolve(temp).toURL().toExternalForm();
|
||||
// Using the following HACK instead of the above to avoid double encoding of
|
||||
// the query. Application's QUERY_STRING is encoded using URLEncoder.encode().
|
||||
// If we use that query in URI's constructor, it is encoded again.
|
||||
// URLEncoder's encoding is not the same as URI's encoding of the query.
|
||||
// See {@link URL}
|
||||
StringBuilder spec = new StringBuilder();
|
||||
if (path != null) {
|
||||
spec.append(path);
|
||||
}
|
||||
if (query != null) {
|
||||
spec.append("?");
|
||||
spec.append(query);
|
||||
}
|
||||
if (fragment != null) {
|
||||
spec.append("#");
|
||||
spec.append(fragment);
|
||||
}
|
||||
return new URL(endpointURI.toURL(), spec.toString()).toExternalForm();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new WebServiceException(DispatchMessages.INVALID_URI_RESOLUTION(path));
|
||||
}
|
||||
}
|
||||
|
||||
private static String checkPath(@Nullable String path) {
|
||||
//does it begin with /
|
||||
return (path == null || path.startsWith("/")) ? path : "/" + path;
|
||||
}
|
||||
|
||||
private static String checkQuery(@Nullable String query) {
|
||||
if (query == null) return null;
|
||||
|
||||
if (query.indexOf('?') == 0)
|
||||
throw new WebServiceException(DispatchMessages.INVALID_QUERY_LEADING_CHAR(query));
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
protected AttachmentSet setOutboundAttachments() {
|
||||
HashMap<String, DataHandler> attachments = (HashMap<String, DataHandler>)
|
||||
getRequestContext().get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
|
||||
|
||||
if (attachments != null) {
|
||||
List<Attachment> alist = new ArrayList();
|
||||
for (Map.Entry<String, DataHandler> att : attachments.entrySet()) {
|
||||
DataHandlerAttachment dha = new DataHandlerAttachment(att.getKey(), att.getValue());
|
||||
alist.add(dha);
|
||||
}
|
||||
return new AttachmentSetImpl(alist);
|
||||
}
|
||||
return new AttachmentSetImpl();
|
||||
}
|
||||
|
||||
/* private void getInboundAttachments(Message msg) {
|
||||
AttachmentSet attachments = msg.getAttachments();
|
||||
if (!attachments.isEmpty()) {
|
||||
Map<String, DataHandler> in = new HashMap<String, DataHandler>();
|
||||
for (Attachment attachment : attachments)
|
||||
in.put(attachment.getContentId(), attachment.asDataHandler());
|
||||
getResponseContext().put(MessageContext.INBOUND_MESSAGE_ATTACHMENTS, in);
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Calls {@link DispatchImpl#doInvoke(Object,RequestContext,ResponseContextReceiver)}.
|
||||
*/
|
||||
private class Invoker implements Callable {
|
||||
private final T param;
|
||||
// snapshot the context now. this is necessary to avoid concurrency issue,
|
||||
// and is required by the spec
|
||||
private final RequestContext rc = requestContext.copy();
|
||||
|
||||
/**
|
||||
* Because of the object instantiation order,
|
||||
* we can't take this as a constructor parameter.
|
||||
*/
|
||||
private ResponseContextReceiver receiver;
|
||||
|
||||
Invoker(T param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public T call() throws Exception {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
dumpParam(param, "call()");
|
||||
}
|
||||
return doInvoke(param,rc,receiver);
|
||||
}
|
||||
|
||||
void setReceiver(ResponseContextReceiver receiver) {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private class DispatchAsyncInvoker extends AsyncInvoker {
|
||||
private final T param;
|
||||
// snapshot the context now. this is necessary to avoid concurrency issue,
|
||||
// and is required by the spec
|
||||
private final RequestContext rc = requestContext.copy();
|
||||
|
||||
DispatchAsyncInvoker(T param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public void do_run () {
|
||||
checkNullAllowed(param, rc, binding, mode);
|
||||
final Packet message = createPacket(param);
|
||||
message.setState(Packet.State.ClientRequest);
|
||||
message.nonNullAsyncHandlerGiven = this.nonNullAsyncHandlerGiven;
|
||||
resolveEndpointAddress(message, rc);
|
||||
setProperties(message,true);
|
||||
|
||||
String action = null;
|
||||
String msgId = null;
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
AddressingVersion av = DispatchImpl.this.getBinding().getAddressingVersion();
|
||||
SOAPVersion sv = DispatchImpl.this.getBinding().getSOAPVersion();
|
||||
action =
|
||||
av != null && message.getMessage() != null ?
|
||||
AddressingUtils.getAction(message.getMessage().getHeaders(), av, sv) : null;
|
||||
msgId =
|
||||
av != null&& message.getMessage() != null ?
|
||||
AddressingUtils.getMessageID(message.getMessage().getHeaders(), av, sv) : null;
|
||||
LOGGER.fine("In DispatchAsyncInvoker.do_run for async message with action: " + action + " and msg ID: " + msgId);
|
||||
}
|
||||
|
||||
final String actionUse = action;
|
||||
final String msgIdUse = msgId;
|
||||
|
||||
Fiber.CompletionCallback callback = new Fiber.CompletionCallback() {
|
||||
public void onCompletion(@NotNull Packet response) {
|
||||
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse);
|
||||
}
|
||||
|
||||
Message msg = response.getMessage();
|
||||
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse + " msg: " + msg);
|
||||
}
|
||||
|
||||
try {
|
||||
if(msg != null && msg.isFault() &&
|
||||
!allowFaultResponseMsg) {
|
||||
SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
|
||||
// passing null means there is no checked excpetion we're looking for all
|
||||
// it will get back to us is a protocol exception
|
||||
throw (SOAPFaultException)faultBuilder.createException(null);
|
||||
}
|
||||
responseImpl.setResponseContext(new ResponseContext(response));
|
||||
responseImpl.set(toReturnValue(response), null);
|
||||
} catch (JAXBException e) {
|
||||
//TODO: i18nify
|
||||
responseImpl.set(null, new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(),e));
|
||||
} catch(WebServiceException e){
|
||||
//it could be a WebServiceException or a ProtocolException
|
||||
responseImpl.set(null, e);
|
||||
} catch(Throwable e){
|
||||
// It could be any RuntimeException resulting due to some internal bug.
|
||||
// or its some other exception resulting from user error, wrap it in
|
||||
// WebServiceException
|
||||
responseImpl.set(null, new WebServiceException(e));
|
||||
}
|
||||
}
|
||||
public void onCompletion(@NotNull Throwable error) {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse + " Throwable: " + error.toString());
|
||||
}
|
||||
if (error instanceof WebServiceException) {
|
||||
responseImpl.set(null, error);
|
||||
|
||||
} else {
|
||||
//its RuntimeException or some other exception resulting from user error, wrap it in
|
||||
// WebServiceException
|
||||
responseImpl.set(null, new WebServiceException(error));
|
||||
}
|
||||
}
|
||||
};
|
||||
processAsync(responseImpl,message,rc, callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOutboundHeaders(Object... headers) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
static final String HTTP_REQUEST_METHOD_GET="GET";
|
||||
static final String HTTP_REQUEST_METHOD_POST="POST";
|
||||
static final String HTTP_REQUEST_METHOD_PUT="PUT";
|
||||
|
||||
@Deprecated
|
||||
public static Dispatch<Source> createSourceDispatch(QName port, Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
if(isXMLHttp(binding))
|
||||
return new RESTSourceDispatch(port,mode,owner,pipe,binding,epr);
|
||||
else
|
||||
return new SOAPSourceDispatch(port,mode,owner,pipe,binding,epr);
|
||||
}
|
||||
|
||||
public static Dispatch<Source> createSourceDispatch(WSPortInfo portInfo, Mode mode, BindingImpl binding, WSEndpointReference epr) {
|
||||
if (isXMLHttp(binding))
|
||||
return new RESTSourceDispatch(portInfo, mode, binding, epr);
|
||||
else
|
||||
return new SOAPSourceDispatch(portInfo, mode, binding, epr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.xml.internal.bind.api.JAXBRIContext;
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.message.Header;
|
||||
import com.sun.xml.internal.ws.api.message.Headers;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Messages;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
import com.sun.xml.internal.ws.message.jaxb.JAXBDispatchMessage;
|
||||
import com.sun.xml.internal.ws.spi.db.BindingContextFactory;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* The <code>JAXBDispatch</code> class provides support
|
||||
* for the dynamic invocation of a service endpoint operation using
|
||||
* JAXB objects. The <code>javax.xml.ws.Service</code>
|
||||
* interface acts as a factory for the creation of <code>JAXBDispatch</code>
|
||||
* instances.
|
||||
*
|
||||
* @author WS Development Team
|
||||
* @version 1.0
|
||||
*/
|
||||
public class JAXBDispatch extends DispatchImpl<Object> {
|
||||
|
||||
private final JAXBContext jaxbcontext;
|
||||
|
||||
// We will support a JAXBContext parameter from an unknown JAXB
|
||||
// implementation by marshaling and unmarshaling directly from the
|
||||
// context object, as there is no Bond available.
|
||||
private final boolean isContextSupported;
|
||||
|
||||
@Deprecated
|
||||
public JAXBDispatch(QName port, JAXBContext jc, Service.Mode mode, WSServiceDelegate service, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(port, mode, service, pipe, binding, epr);
|
||||
this.jaxbcontext = jc;
|
||||
this.isContextSupported = BindingContextFactory.isContextSupported(jc);
|
||||
}
|
||||
|
||||
public JAXBDispatch(WSPortInfo portInfo, JAXBContext jc, Service.Mode mode, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(portInfo, mode, binding, epr);
|
||||
this.jaxbcontext = jc;
|
||||
this.isContextSupported = BindingContextFactory.isContextSupported(jc);
|
||||
}
|
||||
|
||||
Object toReturnValue(Packet response) {
|
||||
try {
|
||||
Unmarshaller unmarshaller = jaxbcontext.createUnmarshaller();
|
||||
Message msg = response.getMessage();
|
||||
switch (mode) {
|
||||
case PAYLOAD:
|
||||
return msg.<Object>readPayloadAsJAXB(unmarshaller);
|
||||
case MESSAGE:
|
||||
Source result = msg.readEnvelopeAsSource();
|
||||
return unmarshaller.unmarshal(result);
|
||||
default:
|
||||
throw new WebServiceException("Unrecognized dispatch mode");
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Packet createPacket(Object msg) {
|
||||
assert jaxbcontext != null;
|
||||
|
||||
Message message;
|
||||
if (mode == Service.Mode.MESSAGE) {
|
||||
message = isContextSupported ?
|
||||
new JAXBDispatchMessage(BindingContextFactory.create(jaxbcontext), msg, soapVersion) :
|
||||
new JAXBDispatchMessage(jaxbcontext, msg, soapVersion);
|
||||
} else {
|
||||
if (msg == null) {
|
||||
message = Messages.createEmpty(soapVersion);
|
||||
} else {
|
||||
message = isContextSupported ?
|
||||
Messages.create(jaxbcontext, msg, soapVersion) :
|
||||
Messages.createRaw(jaxbcontext, msg, soapVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return new Packet(message);
|
||||
|
||||
}
|
||||
|
||||
public void setOutboundHeaders(Object... headers) {
|
||||
if (headers == null)
|
||||
throw new IllegalArgumentException();
|
||||
Header[] hl = new Header[headers.length];
|
||||
for (int i = 0; i < hl.length; i++) {
|
||||
if (headers[i] == null)
|
||||
throw new IllegalArgumentException();
|
||||
// TODO: handle any JAXBContext.
|
||||
hl[i] = Headers.create((JAXBRIContext) jaxbcontext, headers[i]);
|
||||
}
|
||||
super.setOutboundHeaders(hl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
import com.sun.xml.internal.ws.client.PortInfo;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.Dispatch;
|
||||
import javax.xml.ws.Service.Mode;
|
||||
|
||||
/**
|
||||
* {@link Dispatch} implementation for {@link Message}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @since 2.1.1
|
||||
*/
|
||||
public class MessageDispatch extends DispatchImpl<Message> {
|
||||
@Deprecated
|
||||
public MessageDispatch(QName port, WSServiceDelegate service, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(port, Mode.MESSAGE, service, pipe, binding, epr);
|
||||
}
|
||||
|
||||
public MessageDispatch(WSPortInfo portInfo, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(portInfo, Mode.MESSAGE, binding, epr, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
Message toReturnValue(Packet response) {
|
||||
return response.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
Packet createPacket(Message msg) {
|
||||
return new Packet(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.client.ThrowableInPacketCompletionFeature;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Fiber;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.Dispatch;
|
||||
import javax.xml.ws.Service.Mode;
|
||||
|
||||
/**
|
||||
* {@link Dispatch} implementation for {@link Packet}.
|
||||
*
|
||||
* @since 2.2.6
|
||||
*/
|
||||
public class PacketDispatch extends DispatchImpl<Packet> {
|
||||
private final boolean isDeliverThrowableInPacket;
|
||||
|
||||
@Deprecated
|
||||
public PacketDispatch(QName port, WSServiceDelegate owner, Tube pipe, BindingImpl binding, @Nullable WSEndpointReference epr) {
|
||||
super(port, Mode.MESSAGE, owner, pipe, binding, epr);
|
||||
isDeliverThrowableInPacket = calculateIsDeliverThrowableInPacket(binding);
|
||||
}
|
||||
|
||||
|
||||
public PacketDispatch(WSPortInfo portInfo, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
this(portInfo, pipe, binding, epr, true);
|
||||
}
|
||||
|
||||
public PacketDispatch(WSPortInfo portInfo, Tube pipe, BindingImpl binding, WSEndpointReference epr, boolean allowFaultResponseMsg) {
|
||||
super(portInfo, Mode.MESSAGE, pipe, binding, epr, allowFaultResponseMsg);
|
||||
isDeliverThrowableInPacket = calculateIsDeliverThrowableInPacket(binding);
|
||||
}
|
||||
|
||||
public PacketDispatch(WSPortInfo portInfo, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(portInfo, Mode.MESSAGE, binding, epr, true);
|
||||
isDeliverThrowableInPacket = calculateIsDeliverThrowableInPacket(binding);
|
||||
}
|
||||
|
||||
private boolean calculateIsDeliverThrowableInPacket(BindingImpl binding) {
|
||||
return binding.isFeatureEnabled(ThrowableInPacketCompletionFeature.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureFiber(Fiber fiber) {
|
||||
fiber.setDeliverThrowableInPacket(isDeliverThrowableInPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
Packet toReturnValue(Packet response) {
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
Packet createPacket(Packet request) {
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Messages;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
import com.sun.xml.internal.ws.client.PortInfo;
|
||||
import com.sun.xml.internal.ws.encoding.xml.XMLMessage;
|
||||
import com.sun.xml.internal.ws.message.source.PayloadSourceMessage;
|
||||
import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.toFeatureArray;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.ws.Dispatch;
|
||||
import javax.xml.ws.Service.Mode;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* {@link Dispatch} implementation for {@link Source} and XML/HTTP binding.
|
||||
*
|
||||
* @author Kathy Walsh
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @see SOAPSourceDispatch
|
||||
*/
|
||||
final class RESTSourceDispatch extends DispatchImpl<Source> {
|
||||
@Deprecated
|
||||
public RESTSourceDispatch(QName port, Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(port, mode, owner, pipe, binding, epr);
|
||||
assert isXMLHttp(binding);
|
||||
}
|
||||
|
||||
public RESTSourceDispatch(WSPortInfo portInfo, Mode mode, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(portInfo, mode, binding, epr);
|
||||
assert isXMLHttp(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
Source toReturnValue(Packet response) {
|
||||
Message msg = response.getMessage();
|
||||
try {
|
||||
return new StreamSource(XMLMessage.getDataSource(msg, binding.getFeatures()).getInputStream());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Packet createPacket(Source msg) {
|
||||
Message message;
|
||||
|
||||
if(msg==null)
|
||||
message = Messages.createEmpty(soapVersion);
|
||||
else
|
||||
message = new PayloadSourceMessage(null, msg, setOutboundAttachments(), soapVersion);
|
||||
|
||||
return new Packet(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.message.saaj.SAAJFactory;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
import com.sun.xml.internal.ws.client.PortInfo;
|
||||
import com.sun.xml.internal.ws.message.saaj.SAAJMessage;
|
||||
import com.sun.xml.internal.ws.resources.DispatchMessages;
|
||||
import com.sun.xml.internal.ws.transport.Headers;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.soap.MimeHeader;
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import javax.xml.ws.handler.MessageContext;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The <code>SOAPMessageDispatch</code> class provides support
|
||||
* for the dynamic invocation of a service endpoint operation using
|
||||
* the <code>SOAPMessage</code> class. The <code>javax.xml.ws.Service</code>
|
||||
* interface acts as a factory for the creation of <code>SOAPMessageDispatch</code>
|
||||
* instances.
|
||||
*
|
||||
* @author WS Development Team
|
||||
* @version 1.0
|
||||
*/
|
||||
public class SOAPMessageDispatch extends com.sun.xml.internal.ws.client.dispatch.DispatchImpl<SOAPMessage> {
|
||||
@Deprecated
|
||||
public SOAPMessageDispatch(QName port, Service.Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(port, mode, owner, pipe, binding, epr);
|
||||
}
|
||||
|
||||
public SOAPMessageDispatch(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(portInfo, mode, binding, epr);
|
||||
}
|
||||
|
||||
Packet createPacket(SOAPMessage arg) {
|
||||
Iterator iter = arg.getMimeHeaders().getAllHeaders();
|
||||
Headers ch = new Headers();
|
||||
while(iter.hasNext()) {
|
||||
MimeHeader mh = (MimeHeader) iter.next();
|
||||
ch.add(mh.getName(), mh.getValue());
|
||||
}
|
||||
Packet packet = new Packet(SAAJFactory.create(arg));
|
||||
packet.invocationProperties.put(MessageContext.HTTP_REQUEST_HEADERS, ch);
|
||||
return packet;
|
||||
}
|
||||
|
||||
SOAPMessage toReturnValue(Packet response) {
|
||||
try {
|
||||
|
||||
//not sure if this is the correct way to deal with this.
|
||||
if ( response ==null || response.getMessage() == null )
|
||||
throw new WebServiceException(DispatchMessages.INVALID_RESPONSE());
|
||||
else
|
||||
return response.getMessage().readAsSOAPMessage();
|
||||
} catch (SOAPException e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.dispatch;
|
||||
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Messages;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
import com.sun.xml.internal.ws.client.PortInfo;
|
||||
import com.sun.xml.internal.ws.message.source.PayloadSourceMessage;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.ws.Service.Mode;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>SOAPSourceDispatch</code> class provides support
|
||||
* for the dynamic invocation of a service endpoint operation using XML
|
||||
* constructs. The <code>javax.xml.ws.Service</code>
|
||||
* interface acts as a factory for the creation of <code>SOAPSourceDispatch</code>
|
||||
* instances.
|
||||
*
|
||||
* @author WS Development Team
|
||||
* @version 1.0
|
||||
* @see RESTSourceDispatch
|
||||
*/
|
||||
final class SOAPSourceDispatch extends DispatchImpl<Source> {
|
||||
@Deprecated
|
||||
public SOAPSourceDispatch(QName port, Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(port, mode, owner, pipe, binding, epr);
|
||||
assert !isXMLHttp(binding);
|
||||
}
|
||||
|
||||
public SOAPSourceDispatch(WSPortInfo portInfo, Mode mode, BindingImpl binding, WSEndpointReference epr) {
|
||||
super(portInfo, mode, binding, epr);
|
||||
assert !isXMLHttp(binding);
|
||||
}
|
||||
|
||||
|
||||
Source toReturnValue(Packet response) {
|
||||
Message msg = response.getMessage();
|
||||
|
||||
switch (mode) {
|
||||
case PAYLOAD:
|
||||
return msg.readPayloadAsSource();
|
||||
case MESSAGE:
|
||||
return msg.readEnvelopeAsSource();
|
||||
default:
|
||||
throw new WebServiceException("Unrecognized dispatch mode");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Packet createPacket(Source msg) {
|
||||
|
||||
final Message message;
|
||||
|
||||
if (msg == null)
|
||||
message = Messages.createEmpty(soapVersion);
|
||||
else {
|
||||
switch (mode) {
|
||||
case PAYLOAD:
|
||||
message = new PayloadSourceMessage(null, msg, setOutboundAttachments(), soapVersion);
|
||||
break;
|
||||
case MESSAGE:
|
||||
message = Messages.create(msg, soapVersion);
|
||||
break;
|
||||
default:
|
||||
throw new WebServiceException("Unrecognized message mode");
|
||||
}
|
||||
}
|
||||
|
||||
return new Packet(message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
157
jdkSrc/jdk8/com/sun/xml/internal/ws/client/package-info.java
Normal file
157
jdkSrc/jdk8/com/sun/xml/internal/ws/client/package-info.java
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <h1>JAX-WS 2.0.1 Client Runtime</h1>
|
||||
* <P>This document describes the architecture of client side
|
||||
* JAX-WS 2.0.1 runtime.
|
||||
*
|
||||
* <h3>JAX-WS 2.0.1 Client Sequence Diagram</h3>
|
||||
* <img src='../../../../../jaxws/basic-client.seq.png'>
|
||||
* <h3>JAX-WS 2.0.1 Asynchronous Invocation Sequence Diagram</h3>
|
||||
* <img src='../../../../../jaxws/client-async.seq.png'>
|
||||
* <h3>JAX-WS 2.0.1 Dispatch Invocation Sequence Diagram</h3>
|
||||
* <img src='../../../../../jaxws/dispatch.seq.png'>
|
||||
|
||||
* <H3>Message Flow</H3>
|
||||
* {@link com.sun.xml.internal.ws.client.WebService} provides client view of a Web service.
|
||||
* WebService.getPort returns an instance of {@link com.sun.xml.internal.ws.client.EndpointIFInvocationHandler}
|
||||
* with {@link com.sun.pept.ept.ContactInfoList} and {@link com.sun.pept.Delegate}
|
||||
* initialized. A method invocation on the port, obtained from WebService, invokes
|
||||
* {@link com.sun.xml.internal.ws.client.EndpointIFInvocationHandler#invoke}. This method
|
||||
* then creates a {@link com.sun.pept.ept.MessageInfo} and populates the data
|
||||
* (parameters specified by the user) and metadata such as RuntimeContext, RequestContext,
|
||||
* Message Exchange Pattern into this MessageInfo. This method then invokes
|
||||
* {@link com.sun.pept.Delegate#send} and returns the response.
|
||||
* <P></P>
|
||||
* The Delegate.send method iterates through the ContactInfoList and picks up the
|
||||
* correct {@link com.sun.pept.ept.ContactInfo} based upon the binding id of
|
||||
* {@link javax.xml.ws.BindingProvider} and sets it on the MessageInfo. After the
|
||||
* Delegate obtains a specific ContactInfo it uses that ContactInfo to obtain a
|
||||
* protocol-specific {@link com.sun.pept.protocol.MessageDispatcher}. There will be
|
||||
* two types of client-side MessageDispatchers for JAX-WS 2.0.1,
|
||||
* {@link com.sun.xml.internal.ws.protocol.soap.client.SOAPMessageDispatcher} and
|
||||
* {@link com.sun.xml.internal.ws.protocol.xml.client.XMLMessageDispatcher}. The Delegate
|
||||
* then invokes {@link com.sun.pept.protocol.MessageDispatcher#send}. The
|
||||
* MessageDispatcher.send method makes a decision about the synchronous and
|
||||
* asynchronous nature of the message exchange pattern and invokes separate methods
|
||||
* accordingly.
|
||||
* <p></P>
|
||||
* The MessageDispatcher uses ContactInfo to obtain
|
||||
* a {@link com.sun.xml.internal.ws.encoding.soap.client.SOAPXMLEncoder} which converts
|
||||
* the MessageInfo to {@link com.sun.xml.internal.ws.encoding.soap.internal.InternalMessage}.
|
||||
* There will be two types of client-side SOAPXMLEncoder for JAX-WS 2.0.1,
|
||||
* SOAPXMEncoder for SOAP 1.1 and {@link com.sun.xml.internal.ws.encoding.soap.client.SOAP12XMLEncoder}
|
||||
* for SOAP 1.2. The MessageDispatcher invokes configured handlers and use the
|
||||
* codec to convert the InternalMessage to a {@link javax.xml.soap.SOAPMessage}.
|
||||
* The metadata from the MessageInfo is classified into {@link javax.xml.soap.MimeHeaders}
|
||||
* of this SOAPMessage and context information for {@link com.sun.xml.internal.ws.api.server.WSConnection}.
|
||||
* The SOAPMessge is then written to the output stream of the WSConnection
|
||||
* obtained from MessageInfo.
|
||||
*<P></P>
|
||||
* The MessageDispatcher.receive method handles the response. The
|
||||
* SOAPMessageDispatcher extracts the SOAPMessage from the input stream of
|
||||
* WSConnection and performs the mustUnderstand processing followed by invocation
|
||||
* of any handlers. The MessageDispatcher uses ContactInfo to obtain a
|
||||
* {@link com.sun.xml.internal.ws.encoding.soap.client.SOAPXMLDecoder} which converts the SOAPMessage
|
||||
* to InternalMessage and then InternalMessage to MessageInfo. There will be two types of
|
||||
* client-side SOAPXMLDecoder for JAX-WS 2.0.1, SOAPXMLDencoder for SOAP 1.1 and
|
||||
* {@link com.sun.xml.internal.ws.encoding.soap.client.SOAP12XMLDecoder} for SOAP 1.2. The
|
||||
* response is returned back to the client code via Delegate.
|
||||
*
|
||||
* <H3>External Interactions</H3>
|
||||
* <H4>SAAJ API</H4>
|
||||
* <UL>
|
||||
* <LI><P>JAX-WS creates SAAJ SOAPMessage from the HttpServletRequest.
|
||||
* At present, JAX-WS reads all the bytes from the request stream and
|
||||
* then creates SOAPMessage along with the HTTP headers.</P>
|
||||
* </UL>
|
||||
* <P>MessageFactory(binding).createMessage(MimeHeaders, InputStream)</P>
|
||||
* <UL>
|
||||
* <LI><P>SOAPMessage parses the content from the stream including MIME
|
||||
* data</P>
|
||||
* <LI><P>com.sun.xml.internal.ws.server.SOAPMessageDispatcher::checkHeadersPeekBody()</P>
|
||||
* <P>SOAPMessage.getSOAPHeader() is used for mustUnderstand processing
|
||||
* of headers. It further uses
|
||||
* SOAPHeader.examineMustUnderstandHeaderElements(role)</P>
|
||||
* <P>SOAPMessage.getSOAPBody().getFistChild() is used for guessing the
|
||||
* MEP of the request</P>
|
||||
* <LI><P>com.sun.xml.internal.ws.handler.HandlerChainCaller:insertFaultMessage()</P>
|
||||
* <P>SOAPMessage.getSOAPPart().getEnvelope() and some other SAAJ calls
|
||||
* are made to create a fault in the SOAPMessage</P>
|
||||
* <LI><P>com.sun.xml.internal.ws.handler.LogicalMessageImpl::getPayload()
|
||||
* interacts with SAAJ to get body from SOAPMessage</P>
|
||||
* <LI><P>com.sun.xml.internal.ws.encoding.soap.SOAPEncoder.toSOAPMessage(com.sun.xml.internal.ws.encoding.soap.internal.InternalMessage,
|
||||
* SOAPMessage). There is a scenario where there is SOAPMessage and a
|
||||
* logical handler sets payload as Source. To write to the stream,
|
||||
* SOAPMessage.writeTo() is used but before that the body needs to be
|
||||
* updated with logical handler' Source. Need to verify if this
|
||||
* scenario is still happening since Handler.close() is changed to take
|
||||
* MessageContext.</P>
|
||||
* <LI><P>com.sun.xml.internal.ws.handlerSOAPMessageContextImpl.getHeaders()
|
||||
* uses SAAJ API to get headers.</P>
|
||||
* <LI><P>SOAPMessage.writeTo() is used to write response. At present,
|
||||
* it writes into byte[] and this byte[] is written to
|
||||
* HttpServletResponse.</P>
|
||||
* </UL>
|
||||
* <H4>JAXB API</H4>
|
||||
* <P>JAX-WS RI uses the JAXB API to marshall/unmarshall user created
|
||||
* JAXB objects with user created {@link javax.xml.bind.JAXBContext JAXBContext}.
|
||||
* Handler, Dispatch in JAX-WS API provide ways for the user to specify his/her own
|
||||
* JAXBContext. {@link com.sun.xml.internal.ws.encoding.jaxb.JAXBTypeSerializer JAXBTypeSerializer} class uses all these methods.</P>
|
||||
* <UL>
|
||||
* <LI><p>{@link javax.xml.bind.Marshaller#marshal(Object,XMLStreamWriter) Marshaller.marshal(Object,XMLStreamWriter)}</p>
|
||||
* <LI><P>{@link javax.xml.bind.Marshaller#marshal(Object,Result) Marshaller.marshal(Object, DomResult)}</P>
|
||||
* <LI><P>{@link javax.xml.bind.Unmarshaller#unmarshal(XMLStreamReader) Object Unmarshaller.unmarshal(XMLStreamReader)}</P>
|
||||
* <LI><P>{@link javax.xml.bind.Unmarshaller#unmarshal(Source) Object Unmarshaller.unmarshal(Source)}</P>
|
||||
* </UL>
|
||||
* The following two JAXB classes are implemented by JAX-WS to enable/implement MTOM and XOP
|
||||
* <UL>
|
||||
* <LI><P>{@link javax.xml.bind.attachment.AttachmentMarshaller AttachmentMarshaller}</P>
|
||||
* <LI><P>{@link javax.xml.bind.attachment.AttachmentUnmarshaller AttachmentUnmarshaller}</P>
|
||||
* </UL>
|
||||
* <H4>JAXB Runtime-API (private contract)</H4>
|
||||
* <P>JAX-WS RI uses these private API for serialization/deserialization
|
||||
* purposes. This private API is used to serialize/deserialize method
|
||||
* parameters at the time of JAXBTypeSerializer class uses all
|
||||
* these methods.</P>
|
||||
* <UL>
|
||||
* <LI><P>{@link com.sun.xml.internal.bind.api.Bridge#marshal(BridgeContext, Object, XMLStreamWriter) Bridge.marshal(BridgeContext, Object, XMLStreamWriter)}</P>
|
||||
* <LI><P>{@link com.sun.xml.internal.bind.api.Bridge#marshal(BridgeContext, Object, Node) Bridge.marshal(BridgeContext, Object, Node)}</P>
|
||||
* <LI><P>{@link com.sun.xml.internal.bind.api.Bridge#unmarshal(BridgeContext, XMLStreamReader) Object Bridge.unmarshal(BridgeContext, XMLStreamReader)}</P>
|
||||
* </UL>
|
||||
*
|
||||
* @ArchitectureDocument
|
||||
**/
|
||||
package com.sun.xml.internal.ws.client;
|
||||
|
||||
import com.sun.xml.internal.bind.api.BridgeContext;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
//import com.sun.tools.internal.ws.wsdl.document.soap.SOAPBinding;
|
||||
|
||||
import com.oracle.webservices.internal.api.databinding.JavaCallInfo;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.pipe.Fiber;
|
||||
import com.sun.xml.internal.ws.client.AsyncInvoker;
|
||||
import com.sun.xml.internal.ws.client.AsyncResponseImpl;
|
||||
import com.sun.xml.internal.ws.client.RequestContext;
|
||||
import com.sun.xml.internal.ws.client.ResponseContext;
|
||||
|
||||
import javax.xml.ws.AsyncHandler;
|
||||
import javax.xml.ws.Response;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Common part between {@link CallbackMethodHandler} and {@link PollingMethodHandler}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
abstract class AsyncMethodHandler extends MethodHandler {
|
||||
|
||||
AsyncMethodHandler(SEIStub owner, Method m) {
|
||||
super(owner, m);
|
||||
}
|
||||
|
||||
// private final ResponseBuilder responseBuilder;
|
||||
// /**
|
||||
// * Async bean class that has setters for all out parameters
|
||||
// */
|
||||
// private final @Nullable Class asyncBeanClass;
|
||||
//
|
||||
// AsyncMethodHandler(SEIStub owner, JavaMethodImpl jm, JavaMethodImpl sync) {
|
||||
// super(owner, sync);
|
||||
//
|
||||
// List<ParameterImpl> rp = sync.getResponseParameters();
|
||||
// int size = 0;
|
||||
// for( ParameterImpl param : rp ) {
|
||||
// if (param.isWrapperStyle()) {
|
||||
// WrapperParameter wrapParam = (WrapperParameter)param;
|
||||
// size += wrapParam.getWrapperChildren().size();
|
||||
// if (sync.getBinding().getStyle() == Style.DOCUMENT) {
|
||||
// // doc/asyncBeanClass - asyncBeanClass bean is in async signature
|
||||
// // Add 2 or more so that it is considered as async bean case
|
||||
// size += 2;
|
||||
// }
|
||||
// } else {
|
||||
// ++size;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Class tempWrap = null;
|
||||
// if (size > 1) {
|
||||
// rp = jm.getResponseParameters();
|
||||
// for(ParameterImpl param : rp) {
|
||||
// if (param.isWrapperStyle()) {
|
||||
// WrapperParameter wrapParam = (WrapperParameter)param;
|
||||
// if (sync.getBinding().getStyle() == Style.DOCUMENT) {
|
||||
// // doc/asyncBeanClass style
|
||||
// tempWrap = (Class)wrapParam.getTypeReference().type;
|
||||
// break;
|
||||
// }
|
||||
// for(ParameterImpl p : wrapParam.getWrapperChildren()) {
|
||||
// if (p.getIndex() == -1) {
|
||||
// tempWrap = (Class)p.getTypeReference().type;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (tempWrap != null) {
|
||||
// break;
|
||||
// }
|
||||
// } else {
|
||||
// if (param.getIndex() == -1) {
|
||||
// tempWrap = (Class)param.getTypeReference().type;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// asyncBeanClass = tempWrap;
|
||||
//
|
||||
// switch(size) {
|
||||
// case 0 :
|
||||
// responseBuilder = buildResponseBuilder(sync, ValueSetterFactory.NONE);
|
||||
// break;
|
||||
// case 1 :
|
||||
// responseBuilder = buildResponseBuilder(sync, ValueSetterFactory.SINGLE);
|
||||
// break;
|
||||
// default :
|
||||
// responseBuilder = buildResponseBuilder(sync, new ValueSetterFactory.AsyncBeanValueSetterFactory(asyncBeanClass));
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
protected final Response<Object> doInvoke(Object proxy, Object[] args, AsyncHandler handler) {
|
||||
|
||||
AsyncInvoker invoker = new SEIAsyncInvoker(proxy, args);
|
||||
invoker.setNonNullAsyncHandlerGiven(handler != null);
|
||||
AsyncResponseImpl<Object> ft = new AsyncResponseImpl<Object>(invoker,handler);
|
||||
invoker.setReceiver(ft);
|
||||
ft.run();
|
||||
return ft;
|
||||
}
|
||||
|
||||
private class SEIAsyncInvoker extends AsyncInvoker {
|
||||
// snapshot the context now. this is necessary to avoid concurrency issue,
|
||||
// and is required by the spec
|
||||
private final RequestContext rc = owner.requestContext.copy();
|
||||
private final Object[] args;
|
||||
|
||||
SEIAsyncInvoker(Object proxy, Object[] args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public void do_run () {
|
||||
JavaCallInfo call = owner.databinding.createJavaCallInfo(method, args);
|
||||
Packet req = (Packet)owner.databinding.serializeRequest(call);
|
||||
|
||||
Fiber.CompletionCallback callback = new Fiber.CompletionCallback() {
|
||||
|
||||
public void onCompletion(@NotNull Packet response) {
|
||||
responseImpl.setResponseContext(new ResponseContext(response));
|
||||
Message msg = response.getMessage();
|
||||
if (msg == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Object[] rargs = new Object[1];
|
||||
JavaCallInfo call = owner.databinding.createJavaCallInfo(method, rargs);
|
||||
call = owner.databinding.deserializeResponse(response, call);
|
||||
if (call.getException() != null) {
|
||||
throw call.getException();
|
||||
} else {
|
||||
responseImpl.set(rargs[0], null);
|
||||
}
|
||||
// dbHandler.readResponse(response, call);
|
||||
// responseImpl.set(rargs[0], null);
|
||||
// if(msg.isFault()) {
|
||||
// SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
|
||||
// throw faultBuilder.createException(checkedExceptions);
|
||||
// } else {
|
||||
// Object[] rargs = new Object[1];
|
||||
// if (asyncBeanClass != null) {
|
||||
// rargs[0] = asyncBeanClass.newInstance();
|
||||
// }
|
||||
// responseBuilder.readResponse(msg, rargs);
|
||||
// responseImpl.set(rargs[0], null);
|
||||
// }
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof RuntimeException) {
|
||||
if (t instanceof WebServiceException) {
|
||||
responseImpl.set(null, t);
|
||||
return;
|
||||
}
|
||||
} else if (t instanceof Exception) {
|
||||
responseImpl.set(null, t);
|
||||
return;
|
||||
}
|
||||
//its RuntimeException or some other exception resulting from user error, wrap it in
|
||||
// WebServiceException
|
||||
responseImpl.set(null, new WebServiceException(t));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onCompletion(@NotNull Throwable error) {
|
||||
if (error instanceof WebServiceException) {
|
||||
responseImpl.set(null, error);
|
||||
} else {
|
||||
//its RuntimeException or some other exception resulting from user error, wrap it in
|
||||
// WebServiceException
|
||||
responseImpl.set(null, new WebServiceException(error));
|
||||
}
|
||||
}
|
||||
};
|
||||
owner.doProcessAsync(responseImpl, req, rc, callback);
|
||||
}
|
||||
}
|
||||
|
||||
ValueGetterFactory getValueGetterFactory() {
|
||||
return ValueGetterFactory.ASYNC;
|
||||
}
|
||||
|
||||
}
|
||||
298
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/BodyBuilder.java
Normal file
298
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/BodyBuilder.java
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.api.SOAPVersion;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Messages;
|
||||
import com.sun.xml.internal.ws.message.jaxb.JAXBMessage;
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
import com.sun.xml.internal.ws.model.WrapperParameter;
|
||||
import com.sun.xml.internal.ws.spi.db.BindingContext;
|
||||
import com.sun.xml.internal.ws.spi.db.XMLBridge;
|
||||
import com.sun.xml.internal.ws.spi.db.PropertyAccessor;
|
||||
import com.sun.xml.internal.ws.spi.db.WrapperComposite;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.Holder;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Builds a JAXB object that represents the payload.
|
||||
*
|
||||
* @see MessageFiller
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class BodyBuilder {
|
||||
abstract Message createMessage(Object[] methodArgs);
|
||||
|
||||
static final BodyBuilder EMPTY_SOAP11 = new Empty(SOAPVersion.SOAP_11);
|
||||
static final BodyBuilder EMPTY_SOAP12 = new Empty(SOAPVersion.SOAP_12);
|
||||
|
||||
private static final class Empty extends BodyBuilder {
|
||||
private final SOAPVersion soapVersion;
|
||||
|
||||
public Empty(SOAPVersion soapVersion) {
|
||||
this.soapVersion = soapVersion;
|
||||
}
|
||||
|
||||
Message createMessage(Object[] methodArgs) {
|
||||
return Messages.createEmpty(soapVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for those {@link BodyBuilder}s that build a {@link Message}
|
||||
* from JAXB objects.
|
||||
*/
|
||||
private static abstract class JAXB extends BodyBuilder {
|
||||
/**
|
||||
* This object determines the binding of the object returned
|
||||
* from {@link #build(Object[])}.
|
||||
*/
|
||||
private final XMLBridge bridge;
|
||||
private final SOAPVersion soapVersion;
|
||||
|
||||
protected JAXB(XMLBridge bridge, SOAPVersion soapVersion) {
|
||||
assert bridge!=null;
|
||||
this.bridge = bridge;
|
||||
this.soapVersion = soapVersion;
|
||||
}
|
||||
|
||||
final Message createMessage(Object[] methodArgs) {
|
||||
return JAXBMessage.create( bridge, build(methodArgs), soapVersion );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a JAXB object that becomes the payload.
|
||||
*/
|
||||
abstract Object build(Object[] methodArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create a payload JAXB object just by taking
|
||||
* one of the parameters.
|
||||
*/
|
||||
final static class Bare extends JAXB {
|
||||
/**
|
||||
* The index of the method invocation parameters that goes into the payload.
|
||||
*/
|
||||
private final int methodPos;
|
||||
|
||||
private final ValueGetter getter;
|
||||
|
||||
/**
|
||||
* Creates a {@link BodyBuilder} from a bare parameter.
|
||||
*/
|
||||
Bare(ParameterImpl p, SOAPVersion soapVersion, ValueGetter getter) {
|
||||
super(p.getXMLBridge(), soapVersion);
|
||||
this.methodPos = p.getIndex();
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks up an object from the method arguments and uses it.
|
||||
*/
|
||||
Object build(Object[] methodArgs) {
|
||||
return getter.get(methodArgs[methodPos]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used to handle a 'wrapper' style request.
|
||||
* Common part of rpc/lit and doc/lit.
|
||||
*/
|
||||
abstract static class Wrapped extends JAXB {
|
||||
|
||||
/**
|
||||
* Where in the method argument list do they come from?
|
||||
*/
|
||||
protected final int[] indices;
|
||||
|
||||
/**
|
||||
* Abstracts away the {@link Holder} handling when touching method arguments.
|
||||
*/
|
||||
protected final ValueGetter[] getters;
|
||||
|
||||
/**
|
||||
* How does each wrapped parameter binds to XML?
|
||||
*/
|
||||
protected XMLBridge[] parameterBridges;
|
||||
|
||||
/**
|
||||
* List of Parameters packed in the body.
|
||||
* Only used for error diagnostics.
|
||||
*/
|
||||
protected List<ParameterImpl> children;
|
||||
|
||||
protected Wrapped(WrapperParameter wp, SOAPVersion soapVersion, ValueGetterFactory getter) {
|
||||
super(wp.getXMLBridge(), soapVersion);
|
||||
children = wp.getWrapperChildren();
|
||||
indices = new int[children.size()];
|
||||
getters = new ValueGetter[children.size()];
|
||||
for( int i=0; i<indices.length; i++ ) {
|
||||
ParameterImpl p = children.get(i);
|
||||
indices[i] = p.getIndex();
|
||||
getters[i] = getter.get(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Packs a bunch of arguments into a {@link WrapperComposite}.
|
||||
*/
|
||||
protected WrapperComposite buildWrapperComposite(Object[] methodArgs) {
|
||||
WrapperComposite cs = new WrapperComposite();
|
||||
cs.bridges = parameterBridges;
|
||||
cs.values = new Object[parameterBridges.length];
|
||||
|
||||
// fill in wrapped parameters from methodArgs
|
||||
for( int i=indices.length-1; i>=0; i-- ) {
|
||||
Object arg = getters[i].get(methodArgs[indices[i]]);
|
||||
if(arg==null) {
|
||||
throw new WebServiceException("Method Parameter: "+
|
||||
children.get(i).getName()+" cannot be null. This is BP 1.1 R2211 violation.");
|
||||
}
|
||||
cs.values[i] = arg;
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create a payload JAXB object by wrapping
|
||||
* multiple parameters into one "wrapper bean".
|
||||
*/
|
||||
final static class DocLit extends Wrapped {
|
||||
/**
|
||||
* How does each wrapped parameter binds to XML?
|
||||
*/
|
||||
private final PropertyAccessor[] accessors;
|
||||
|
||||
/**
|
||||
* Wrapper bean.
|
||||
*/
|
||||
private final Class wrapper;
|
||||
|
||||
/**
|
||||
* Needed to get wrapper instantiation method.
|
||||
*/
|
||||
private BindingContext bindingContext;
|
||||
private boolean dynamicWrapper;
|
||||
|
||||
/**
|
||||
* Creates a {@link BodyBuilder} from a {@link WrapperParameter}.
|
||||
*/
|
||||
DocLit(WrapperParameter wp, SOAPVersion soapVersion, ValueGetterFactory getter) {
|
||||
super(wp, soapVersion, getter);
|
||||
bindingContext = wp.getOwner().getBindingContext();
|
||||
wrapper = (Class)wp.getXMLBridge().getTypeInfo().type;
|
||||
dynamicWrapper = WrapperComposite.class.equals(wrapper);
|
||||
parameterBridges = new XMLBridge[children.size()];
|
||||
accessors = new PropertyAccessor[children.size()];
|
||||
for( int i=0; i<accessors.length; i++ ) {
|
||||
ParameterImpl p = children.get(i);
|
||||
QName name = p.getName();
|
||||
if (dynamicWrapper) {
|
||||
parameterBridges[i] = children.get(i).getInlinedRepeatedElementBridge();
|
||||
if (parameterBridges[i] == null) parameterBridges[i] = children.get(i).getXMLBridge();
|
||||
} else {
|
||||
try {
|
||||
accessors[i] = p.getOwner().getBindingContext().getElementPropertyAccessor(
|
||||
wrapper, name.getNamespaceURI(), name.getLocalPart() );
|
||||
} catch (JAXBException e) {
|
||||
throw new WebServiceException( // TODO: i18n
|
||||
wrapper+" do not have a property of the name "+name,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Packs a bunch of arguments into a {@link WrapperComposite}.
|
||||
*/
|
||||
Object build(Object[] methodArgs) {
|
||||
if (dynamicWrapper) return buildWrapperComposite(methodArgs);
|
||||
try {
|
||||
//Object bean = wrapper.newInstance();
|
||||
Object bean = bindingContext.newWrapperInstace(wrapper);
|
||||
|
||||
// fill in wrapped parameters from methodArgs
|
||||
for( int i=indices.length-1; i>=0; i-- ) {
|
||||
accessors[i].set(bean,getters[i].get(methodArgs[indices[i]]));
|
||||
}
|
||||
|
||||
return bean;
|
||||
} catch (InstantiationException e) {
|
||||
// this is irrecoverable
|
||||
Error x = new InstantiationError(e.getMessage());
|
||||
x.initCause(e);
|
||||
throw x;
|
||||
} catch (IllegalAccessException e) {
|
||||
// this is irrecoverable
|
||||
Error x = new IllegalAccessError(e.getMessage());
|
||||
x.initCause(e);
|
||||
throw x;
|
||||
} catch (com.sun.xml.internal.ws.spi.db.DatabindingException e) {
|
||||
// this can happen when the set method throw a checked exception or something like that
|
||||
throw new WebServiceException(e); // TODO:i18n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used to create a payload JAXB object by wrapping
|
||||
* multiple parameters into a {@link WrapperComposite}.
|
||||
*
|
||||
* <p>
|
||||
* This is used for rpc/lit, as we don't have a wrapper bean for it.
|
||||
* (TODO: Why don't we have a wrapper bean for this, when doc/lit does!?)
|
||||
*/
|
||||
final static class RpcLit extends Wrapped {
|
||||
|
||||
/**
|
||||
* Creates a {@link BodyBuilder} from a {@link WrapperParameter}.
|
||||
*/
|
||||
RpcLit(WrapperParameter wp, SOAPVersion soapVersion, ValueGetterFactory getter) {
|
||||
super(wp, soapVersion, getter);
|
||||
// we'll use CompositeStructure to pack requests
|
||||
assert wp.getTypeInfo().type==WrapperComposite.class;
|
||||
|
||||
parameterBridges = new XMLBridge[children.size()];
|
||||
for( int i=0; i<parameterBridges.length; i++ )
|
||||
parameterBridges[i] = children.get(i).getXMLBridge();
|
||||
}
|
||||
|
||||
Object build(Object[] methodArgs) {
|
||||
return buildWrapperComposite(methodArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.api.databinding.ClientCallBridge;
|
||||
import com.sun.xml.internal.ws.model.JavaMethodImpl;
|
||||
import javax.xml.ws.AsyncHandler;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* {@link MethodHandler} that uses {@link AsyncHandler}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class CallbackMethodHandler extends AsyncMethodHandler {
|
||||
|
||||
/**
|
||||
* Position of the argument that takes {@link AsyncHandler}.
|
||||
*/
|
||||
private final int handlerPos;
|
||||
|
||||
CallbackMethodHandler(SEIStub owner, Method m, int handlerPos) {
|
||||
super(owner, m);
|
||||
this.handlerPos = handlerPos;
|
||||
}
|
||||
|
||||
// CallbackMethodHandler(SEIStub owner, JavaMethodImpl jm, JavaMethodImpl core, int handlerPos) {
|
||||
// super(owner,jm,core);
|
||||
// this.handlerPos = handlerPos;
|
||||
// }
|
||||
|
||||
Future<?> invoke(Object proxy, Object[] args) throws WebServiceException {
|
||||
// the spec requires the last argument
|
||||
final AsyncHandler handler = (AsyncHandler)args[handlerPos];
|
||||
|
||||
return doInvoke(proxy, args, handler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.api.message.Attachment;
|
||||
import com.sun.xml.internal.ws.api.message.Headers;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.message.ByteArrayAttachment;
|
||||
import com.sun.xml.internal.ws.message.DataHandlerAttachment;
|
||||
import com.sun.xml.internal.ws.message.JAXBAttachment;
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
import com.sun.xml.internal.ws.spi.db.XMLBridge;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* Puts a non-payload message parameter to {@link Message}.
|
||||
*
|
||||
* <p>
|
||||
* Instance of this class is used to handle header parameters and attachment parameters.
|
||||
* They add things to {@link Message}.
|
||||
*
|
||||
* @see BodyBuilder
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
abstract class MessageFiller {
|
||||
|
||||
/**
|
||||
* The index of the method invocation parameters that this object looks for.
|
||||
*/
|
||||
protected final int methodPos;
|
||||
|
||||
protected MessageFiller( int methodPos) {
|
||||
this.methodPos = methodPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an argument of a method invocation into a {@link Message}.
|
||||
*/
|
||||
abstract void fillIn(Object[] methodArgs, Message msg);
|
||||
|
||||
/**
|
||||
* Adds a parameter as an MIME attachment to {@link Message}.
|
||||
*/
|
||||
static abstract class AttachmentFiller extends MessageFiller {
|
||||
protected final ParameterImpl param;
|
||||
protected final ValueGetter getter;
|
||||
protected final String mimeType;
|
||||
private final String contentIdPart;
|
||||
|
||||
protected AttachmentFiller(ParameterImpl param, ValueGetter getter) {
|
||||
super(param.getIndex());
|
||||
this.param = param;
|
||||
this.getter = getter;
|
||||
mimeType = param.getBinding().getMimeType();
|
||||
try {
|
||||
contentIdPart = URLEncoder.encode(param.getPartName(), "UTF-8")+'=';
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an MessageFiller based on the parameter type
|
||||
*
|
||||
* @param param
|
||||
* runtime Parameter that abstracts the annotated java parameter
|
||||
* @param getter
|
||||
* Gets a value from an object that represents a parameter passed
|
||||
* as a method argument.
|
||||
*/
|
||||
public static MessageFiller createAttachmentFiller(ParameterImpl param, ValueGetter getter) {
|
||||
Class type = (Class)param.getTypeInfo().type;
|
||||
if (DataHandler.class.isAssignableFrom(type) || Source.class.isAssignableFrom(type)) {
|
||||
return new DataHandlerFiller(param, getter);
|
||||
} else if (byte[].class==type) {
|
||||
return new ByteArrayFiller(param, getter);
|
||||
} else if(isXMLMimeType(param.getBinding().getMimeType())) {
|
||||
return new JAXBFiller(param, getter);
|
||||
} else {
|
||||
return new DataHandlerFiller(param, getter);
|
||||
}
|
||||
}
|
||||
|
||||
String getContentId() {
|
||||
return contentIdPart+UUID.randomUUID()+"@jaxws.sun.com";
|
||||
}
|
||||
}
|
||||
|
||||
private static class ByteArrayFiller extends AttachmentFiller {
|
||||
protected ByteArrayFiller(ParameterImpl param, ValueGetter getter) {
|
||||
super(param, getter);
|
||||
}
|
||||
void fillIn(Object[] methodArgs, Message msg) {
|
||||
String contentId = getContentId();
|
||||
Object obj = getter.get(methodArgs[methodPos]);
|
||||
Attachment att = new ByteArrayAttachment(contentId,(byte[])obj,mimeType);
|
||||
msg.getAttachments().add(att);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DataHandlerFiller extends AttachmentFiller {
|
||||
protected DataHandlerFiller(ParameterImpl param, ValueGetter getter) {
|
||||
super(param, getter);
|
||||
}
|
||||
void fillIn(Object[] methodArgs, Message msg) {
|
||||
String contentId = getContentId();
|
||||
Object obj = getter.get(methodArgs[methodPos]);
|
||||
DataHandler dh = (obj instanceof DataHandler) ? (DataHandler)obj : new DataHandler(obj,mimeType);
|
||||
Attachment att = new DataHandlerAttachment(contentId, dh);
|
||||
msg.getAttachments().add(att);
|
||||
}
|
||||
}
|
||||
|
||||
private static class JAXBFiller extends AttachmentFiller {
|
||||
protected JAXBFiller(ParameterImpl param, ValueGetter getter) {
|
||||
super(param, getter);
|
||||
}
|
||||
void fillIn(Object[] methodArgs, Message msg) {
|
||||
String contentId = getContentId();
|
||||
Object obj = getter.get(methodArgs[methodPos]);
|
||||
Attachment att = new JAXBAttachment(contentId, obj, param.getXMLBridge(), mimeType);
|
||||
msg.getAttachments().add(att);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter as an header.
|
||||
*/
|
||||
static final class Header extends MessageFiller {
|
||||
private final XMLBridge bridge;
|
||||
private final ValueGetter getter;
|
||||
|
||||
protected Header(int methodPos, XMLBridge bridge, ValueGetter getter) {
|
||||
super(methodPos);
|
||||
this.bridge = bridge;
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
void fillIn(Object[] methodArgs, Message msg) {
|
||||
Object value = getter.get(methodArgs[methodPos]);
|
||||
msg.getHeaders().add(Headers.create(bridge,value));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isXMLMimeType(String mimeType){
|
||||
return (mimeType.equals("text/xml") || mimeType.equals("application/xml"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
import com.sun.xml.internal.ws.api.databinding.ClientCallBridge;
|
||||
|
||||
/**
|
||||
* Handles an invocation of a method.
|
||||
*
|
||||
* <p>
|
||||
* Each instance of {@link MethodHandler} has an implicit knowledge of
|
||||
* a particular method that it handles.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class MethodHandler {
|
||||
|
||||
protected final SEIStub owner;
|
||||
protected Method method;
|
||||
|
||||
protected MethodHandler(SEIStub owner, Method m) {
|
||||
this.owner = owner;
|
||||
method = m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the method invocation.
|
||||
*
|
||||
* @param proxy
|
||||
* The proxy object exposed to the user. Must not be null.
|
||||
* @param args
|
||||
* The method invocation arguments. To handle asynchroonus method invocations
|
||||
* without array reallocation, this aray is allowed to be longer than the
|
||||
* actual number of arguments to the method. Additional array space should be
|
||||
* simply ignored.
|
||||
* @return
|
||||
* a return value from the method invocation. may be null.
|
||||
*
|
||||
* @throws WebServiceException
|
||||
* If used on the client side, a {@link WebServiceException} signals an error
|
||||
* during the service invocation.
|
||||
* @throws Throwable
|
||||
* some faults are reported in terms of checked exceptions.
|
||||
*/
|
||||
abstract Object invoke(Object proxy, Object[] args) throws WebServiceException, Throwable;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Utility class to invoke sun.reflect.misc.MethodUtil.invoke() if available. If not (other then Oracle JDK) fallbacks
|
||||
* to java.lang,reflect.Method.invoke()
|
||||
* <p/>
|
||||
* Be careful, copy of this class exists in several packages, iny modification must be done to other copies too!
|
||||
*/
|
||||
class MethodUtil {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(MethodUtil.class.getName());
|
||||
private static final Method INVOKE_METHOD;
|
||||
|
||||
static {
|
||||
Method method;
|
||||
try {
|
||||
Class<?> clazz = Class.forName("sun.reflect.misc.MethodUtil");
|
||||
method = clazz.getMethod("invoke", Method.class, Object.class, Object[].class);
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil found; it will be used to invoke methods.");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
method = null;
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil not found, probably non-Oracle JVM");
|
||||
}
|
||||
}
|
||||
INVOKE_METHOD = method;
|
||||
}
|
||||
|
||||
static Object invoke(Object target, Method method, Object[] args) throws IllegalAccessException, InvocationTargetException {
|
||||
if (INVOKE_METHOD != null) {
|
||||
// sun.reflect.misc.MethodUtil.invoke(method, owner, args)
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "Invoking method using sun.reflect.misc.MethodUtil");
|
||||
}
|
||||
try {
|
||||
return INVOKE_METHOD.invoke(null, method, target, args);
|
||||
} catch (InvocationTargetException ite) {
|
||||
// unwrap invocation exception added by reflection code ...
|
||||
throw unwrapException(ite);
|
||||
}
|
||||
} else {
|
||||
// other then Oracle JDK ...
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "Invoking method directly, probably non-Oracle JVM");
|
||||
}
|
||||
return method.invoke(target, args);
|
||||
}
|
||||
}
|
||||
|
||||
private static InvocationTargetException unwrapException(InvocationTargetException ite) {
|
||||
Throwable targetException = ite.getTargetException();
|
||||
if (targetException != null && targetException instanceof InvocationTargetException) {
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.log(Level.FINE, "Unwrapping invocation target exception");
|
||||
}
|
||||
return (InvocationTargetException) targetException;
|
||||
} else {
|
||||
return ite;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.sun.xml.internal.ws.api.databinding.ClientCallBridge;
|
||||
import com.sun.xml.internal.ws.model.JavaMethodImpl;
|
||||
import javax.xml.ws.Response;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* {@link MethodHandler} that handles asynchronous invocations through {@link Response}.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class PollingMethodHandler extends AsyncMethodHandler {
|
||||
|
||||
// PollingMethodHandler(SEIStub owner, JavaMethodImpl jm, JavaMethodImpl core) {
|
||||
// super(owner, jm, core);
|
||||
// }
|
||||
|
||||
PollingMethodHandler(SEIStub owner, Method m) {
|
||||
super(owner, m);
|
||||
}
|
||||
|
||||
Response<?> invoke(Object proxy, Object[] args) throws WebServiceException {
|
||||
return doInvoke(proxy,args,null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,721 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.api.SOAPVersion;
|
||||
import com.sun.xml.internal.ws.api.message.Attachment;
|
||||
import com.sun.xml.internal.ws.api.message.AttachmentSet;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.model.ParameterBinding;
|
||||
import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
|
||||
import com.sun.xml.internal.ws.message.AttachmentUnmarshallerImpl;
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
import com.sun.xml.internal.ws.model.WrapperParameter;
|
||||
import com.sun.xml.internal.ws.resources.ServerMessages;
|
||||
import com.sun.xml.internal.ws.spi.db.RepeatedElementBridge;
|
||||
import com.sun.xml.internal.ws.spi.db.XMLBridge;
|
||||
import com.sun.xml.internal.ws.spi.db.DatabindingException;
|
||||
import com.sun.xml.internal.ws.spi.db.PropertyAccessor;
|
||||
import com.sun.xml.internal.ws.spi.db.WrapperComposite;
|
||||
import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
|
||||
import com.sun.xml.internal.ws.encoding.StringDataContentHandler;
|
||||
import com.sun.xml.internal.ws.encoding.DataHandlerDataSource;
|
||||
|
||||
import javax.activation.DataHandler;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.soap.SOAPFault;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.ws.Holder;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import javax.xml.ws.soap.SOAPFaultException;
|
||||
import java.awt.Image;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Reads a response {@link Message}, disassembles it, and moves obtained Java values
|
||||
* to the expected places.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
public abstract class ResponseBuilder {
|
||||
/**
|
||||
* Reads a response {@link Message}, disassembles it, and moves obtained Java values
|
||||
* to the expected places.
|
||||
*
|
||||
* @param reply
|
||||
* The reply {@link Message} to be de-composed.
|
||||
* @param args
|
||||
* The Java arguments given to the SEI method invocation.
|
||||
* Some parts of the reply message may be set to {@link Holder}s in the arguments.
|
||||
* @return
|
||||
* If a part of the reply message is returned as a return value from
|
||||
* the SEI method, this method returns that value. Otherwise null.
|
||||
* @throws JAXBException
|
||||
* if there's an error during unmarshalling the reply message.
|
||||
* @throws XMLStreamException
|
||||
* if there's an error during unmarshalling the reply message.
|
||||
*/
|
||||
public abstract Object readResponse(Message reply, Object[] args) throws JAXBException, XMLStreamException;
|
||||
|
||||
static final class WrappedPartBuilder {
|
||||
private final XMLBridge bridge;
|
||||
private final ValueSetter setter;
|
||||
public WrappedPartBuilder(XMLBridge bridge, ValueSetter setter) {
|
||||
this.bridge = bridge;
|
||||
this.setter = setter;
|
||||
}
|
||||
final Object readResponse(Object[] args, XMLStreamReader r, AttachmentSet att) throws JAXBException {
|
||||
Object obj;
|
||||
AttachmentUnmarshallerImpl au = (att != null)?new AttachmentUnmarshallerImpl(att):null;
|
||||
if (bridge instanceof RepeatedElementBridge) {
|
||||
RepeatedElementBridge rbridge = (RepeatedElementBridge)bridge;
|
||||
ArrayList list = new ArrayList();
|
||||
QName name = r.getName();
|
||||
while (r.getEventType()==XMLStreamReader.START_ELEMENT && name.equals(r.getName())) {
|
||||
list.add(rbridge.unmarshal(r, au));
|
||||
XMLStreamReaderUtil.toNextTag(r, name);
|
||||
}
|
||||
obj = rbridge.collectionHandler().convert(list);
|
||||
} else {
|
||||
obj = bridge.unmarshal(r, au);
|
||||
}
|
||||
return setter.put(obj,args);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@link ResponseBuilder.PartBuilder} keyed by the element name (inside the wrapper element.)
|
||||
*/
|
||||
protected Map<QName,WrappedPartBuilder> wrappedParts = null;
|
||||
protected QName wrapperName;
|
||||
|
||||
protected Object readWrappedResponse(Message msg, Object[] args) throws JAXBException, XMLStreamException {
|
||||
Object retVal = null;
|
||||
|
||||
if (!msg.hasPayload()) {
|
||||
throw new WebServiceException("No payload. Expecting payload with "+wrapperName+" element");
|
||||
}
|
||||
XMLStreamReader reader = msg.readPayload();
|
||||
XMLStreamReaderUtil.verifyTag(reader,wrapperName);
|
||||
reader.nextTag();
|
||||
|
||||
while(reader.getEventType()==XMLStreamReader.START_ELEMENT) {
|
||||
// TODO: QName has a performance issue
|
||||
WrappedPartBuilder part = wrappedParts.get(reader.getName());
|
||||
if(part==null) {
|
||||
// no corresponding part found. ignore
|
||||
XMLStreamReaderUtil.skipElement(reader);
|
||||
reader.nextTag();
|
||||
} else {
|
||||
Object o = part.readResponse(args,reader, msg.getAttachments());
|
||||
// there's only at most one ResponseBuilder that returns a value.
|
||||
if(o!=null) {
|
||||
assert retVal==null;
|
||||
retVal = o;
|
||||
}
|
||||
}
|
||||
// skip any whitespace
|
||||
if (reader.getEventType() != XMLStreamConstants.START_ELEMENT &&
|
||||
reader.getEventType() != XMLStreamConstants.END_ELEMENT) {
|
||||
XMLStreamReaderUtil.nextElementContent(reader);
|
||||
}
|
||||
}
|
||||
|
||||
// we are done with the body
|
||||
reader.close();
|
||||
XMLStreamReaderFactory.recycle(reader);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static final class None extends ResponseBuilder {
|
||||
private None(){
|
||||
}
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) {
|
||||
msg.consume();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The singleton instance that produces null return value.
|
||||
* Used for operations that doesn't have any output.
|
||||
*/
|
||||
public final static ResponseBuilder NONE = new None();
|
||||
|
||||
/**
|
||||
* Returns the 'uninitialized' value for the given type.
|
||||
*
|
||||
* <p>
|
||||
* For primitive types, it's '0', and for reference types, it's null.
|
||||
*/
|
||||
@SuppressWarnings("element-type-mismatch")
|
||||
public static Object getVMUninitializedValue(Type type) {
|
||||
// if this map returns null, that means the 'type' is a reference type,
|
||||
// in which case 'null' is the correct null value, so this code is correct.
|
||||
return primitiveUninitializedValues.get(type);
|
||||
}
|
||||
|
||||
private static final Map<Class,Object> primitiveUninitializedValues = new HashMap<Class, Object>();
|
||||
|
||||
static {
|
||||
Map<Class, Object> m = primitiveUninitializedValues;
|
||||
m.put(int.class,(int)0);
|
||||
m.put(char.class,(char)0);
|
||||
m.put(byte.class,(byte)0);
|
||||
m.put(short.class,(short)0);
|
||||
m.put(long.class,(long)0);
|
||||
m.put(float.class,(float)0);
|
||||
m.put(double.class,(double)0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ResponseBuilder} that sets the VM uninitialized value to the type.
|
||||
*/
|
||||
public static final class NullSetter extends ResponseBuilder {
|
||||
private final ValueSetter setter;
|
||||
private final Object nullValue;
|
||||
|
||||
public NullSetter(ValueSetter setter, Object nullValue){
|
||||
assert setter!=null;
|
||||
this.nullValue = nullValue;
|
||||
this.setter = setter;
|
||||
}
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) {
|
||||
return setter.put(nullValue, args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ResponseBuilder} that is a composition of multiple
|
||||
* {@link ResponseBuilder}s.
|
||||
*
|
||||
* <p>
|
||||
* Sometimes we need to look at multiple parts of the reply message
|
||||
* (say, two header params, one body param, and three attachments, etc.)
|
||||
* and that's when this object is used to combine multiple {@link ResponseBuilder}s
|
||||
* (that each responsible for handling one part).
|
||||
*
|
||||
* <p>
|
||||
* The model guarantees that only at most one {@link ResponseBuilder} will
|
||||
* return a value as a return value (and everything else has to go to
|
||||
* {@link Holder}s.)
|
||||
*/
|
||||
public static final class Composite extends ResponseBuilder {
|
||||
private final ResponseBuilder[] builders;
|
||||
|
||||
public Composite(ResponseBuilder... builders) {
|
||||
this.builders = builders;
|
||||
}
|
||||
|
||||
public Composite(Collection<? extends ResponseBuilder> builders) {
|
||||
this(builders.toArray(new ResponseBuilder[builders.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) throws JAXBException, XMLStreamException {
|
||||
Object retVal = null;
|
||||
for (ResponseBuilder builder : builders) {
|
||||
Object r = builder.readResponse(msg,args);
|
||||
// there's only at most one ResponseBuilder that returns a value.
|
||||
if(r!=null) {
|
||||
assert retVal==null;
|
||||
retVal = r;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an Attachment into a Java parameter.
|
||||
*/
|
||||
public static abstract class AttachmentBuilder extends ResponseBuilder {
|
||||
protected final ValueSetter setter;
|
||||
protected final ParameterImpl param;
|
||||
private final String pname;
|
||||
private final String pname1;
|
||||
|
||||
AttachmentBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
this.setter = setter;
|
||||
this.param = param;
|
||||
this.pname = param.getPartName();
|
||||
this.pname1 = "<"+pname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AttachmentBuilder based on the parameter type
|
||||
*
|
||||
* @param param
|
||||
* runtime Parameter that abstracts the annotated java parameter
|
||||
* @param setter
|
||||
* specifies how the obtained value is set into the argument. Takes
|
||||
* care of Holder arguments.
|
||||
*/
|
||||
public static ResponseBuilder createAttachmentBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
Class type = (Class)param.getTypeInfo().type;
|
||||
if (DataHandler.class.isAssignableFrom(type)) {
|
||||
return new DataHandlerBuilder(param, setter);
|
||||
} else if (byte[].class==type) {
|
||||
return new ByteArrayBuilder(param, setter);
|
||||
} else if(Source.class.isAssignableFrom(type)) {
|
||||
return new SourceBuilder(param, setter);
|
||||
} else if(Image.class.isAssignableFrom(type)) {
|
||||
return new ImageBuilder(param, setter);
|
||||
} else if(InputStream.class==type) {
|
||||
return new InputStreamBuilder(param, setter);
|
||||
} else if(isXMLMimeType(param.getBinding().getMimeType())) {
|
||||
return new JAXBBuilder(param, setter);
|
||||
} else if(String.class.isAssignableFrom(type)) {
|
||||
return new StringBuilder(param, setter);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unexpected Attachment type ="+type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) throws JAXBException, XMLStreamException {
|
||||
// TODO not to loop
|
||||
for (Attachment att : msg.getAttachments()) {
|
||||
String part = getWSDLPartName(att);
|
||||
if (part == null) {
|
||||
continue;
|
||||
}
|
||||
if(part.equals(pname) || part.equals(pname1)){
|
||||
return mapAttachment(att, args);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract Object mapAttachment(Attachment att, Object[] args) throws JAXBException;
|
||||
}
|
||||
|
||||
private static final class DataHandlerBuilder extends AttachmentBuilder {
|
||||
DataHandlerBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
super(param, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object mapAttachment(Attachment att, Object[] args) {
|
||||
return setter.put(att.asDataHandler(), args);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class StringBuilder extends AttachmentBuilder {
|
||||
StringBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
super(param, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object mapAttachment(Attachment att, Object[] args) {
|
||||
att.getContentType();
|
||||
StringDataContentHandler sdh = new StringDataContentHandler();
|
||||
try {
|
||||
String str = (String)sdh.getContent(new DataHandlerDataSource(att.asDataHandler()));
|
||||
return setter.put(str, args);
|
||||
} catch(Exception e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ByteArrayBuilder extends AttachmentBuilder {
|
||||
ByteArrayBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
super(param, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object mapAttachment(Attachment att, Object[] args) {
|
||||
return setter.put(att.asByteArray(), args);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SourceBuilder extends AttachmentBuilder {
|
||||
SourceBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
super(param, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object mapAttachment(Attachment att, Object[] args) {
|
||||
return setter.put(att.asSource(), args);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ImageBuilder extends AttachmentBuilder {
|
||||
ImageBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
super(param, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object mapAttachment(Attachment att, Object[] args) {
|
||||
Image image;
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = att.asInputStream();
|
||||
image = ImageIO.read(is);
|
||||
} catch(IOException ioe) {
|
||||
throw new WebServiceException(ioe);
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch(IOException ioe) {
|
||||
throw new WebServiceException(ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
return setter.put(image, args);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class InputStreamBuilder extends AttachmentBuilder {
|
||||
InputStreamBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
super(param, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object mapAttachment(Attachment att, Object[] args) {
|
||||
return setter.put(att.asInputStream(), args);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class JAXBBuilder extends AttachmentBuilder {
|
||||
JAXBBuilder(ParameterImpl param, ValueSetter setter) {
|
||||
super(param, setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object mapAttachment(Attachment att, Object[] args) throws JAXBException {
|
||||
Object obj = param.getXMLBridge().unmarshal(att.asInputStream());
|
||||
return setter.put(obj, args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the WSDL part name of this attachment.
|
||||
*
|
||||
* <p>
|
||||
* According to WSI AP 1.0
|
||||
* <PRE>
|
||||
* 3.8 Value-space of Content-Id Header
|
||||
* Definition: content-id part encoding
|
||||
* The "content-id part encoding" consists of the concatenation of:
|
||||
* The value of the name attribute of the wsdl:part element referenced by the mime:content, in which characters disallowed in content-id headers (non-ASCII characters as represented by code points above 0x7F) are escaped as follows:
|
||||
* o Each disallowed character is converted to UTF-8 as one or more bytes.
|
||||
* o Any bytes corresponding to a disallowed character are escaped with the URI escaping mechanism (that is, converted to %HH, where HH is the hexadecimal notation of the byte value).
|
||||
* o The original character is replaced by the resulting character sequence.
|
||||
* The character '=' (0x3D).
|
||||
* A globally unique value such as a UUID.
|
||||
* The character '@' (0x40).
|
||||
* A valid domain name under the authority of the entity constructing the message.
|
||||
* </PRE>
|
||||
*
|
||||
* So a wsdl:part fooPart will be encoded as:
|
||||
* <fooPart=somereallybignumberlikeauuid@example.com>
|
||||
*
|
||||
* @return null
|
||||
* if the parsing fails.
|
||||
*/
|
||||
@SuppressWarnings("FinalStaticMethod")
|
||||
public static final String getWSDLPartName(com.sun.xml.internal.ws.api.message.Attachment att){
|
||||
String cId = att.getContentId();
|
||||
|
||||
int index = cId.lastIndexOf('@', cId.length());
|
||||
if(index == -1){
|
||||
return null;
|
||||
}
|
||||
String localPart = cId.substring(0, index);
|
||||
index = localPart.lastIndexOf('=', localPart.length());
|
||||
if(index == -1){
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return java.net.URLDecoder.decode(localPart.substring(0, index), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads a header into a JAXB object.
|
||||
*/
|
||||
public static final class Header extends ResponseBuilder {
|
||||
private final XMLBridge<?> bridge;
|
||||
private final ValueSetter setter;
|
||||
private final QName headerName;
|
||||
private final SOAPVersion soapVersion;
|
||||
|
||||
/**
|
||||
* @param soapVersion
|
||||
* SOAP1.1 or 1.2
|
||||
* @param name
|
||||
* The name of the header element.
|
||||
* @param bridge
|
||||
* specifies how to unmarshal a header into a JAXB object.
|
||||
* @param setter
|
||||
* specifies how the obtained value is returned to the client.
|
||||
*/
|
||||
public Header(SOAPVersion soapVersion, QName name, XMLBridge<?> bridge, ValueSetter setter) {
|
||||
this.soapVersion = soapVersion;
|
||||
this.headerName = name;
|
||||
this.bridge = bridge;
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
public Header(SOAPVersion soapVersion, ParameterImpl param, ValueSetter setter) {
|
||||
this(soapVersion,
|
||||
param.getTypeInfo().tagName,
|
||||
param.getXMLBridge(),
|
||||
setter);
|
||||
assert param.getOutBinding()== ParameterBinding.HEADER;
|
||||
}
|
||||
|
||||
private SOAPFaultException createDuplicateHeaderException() {
|
||||
try {
|
||||
SOAPFault fault = soapVersion.getSOAPFactory().createFault();
|
||||
fault.setFaultCode(soapVersion.faultCodeServer);
|
||||
fault.setFaultString(ServerMessages.DUPLICATE_PORT_KNOWN_HEADER(headerName));
|
||||
return new SOAPFaultException(fault);
|
||||
} catch(SOAPException e) {
|
||||
throw new WebServiceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) throws JAXBException {
|
||||
com.sun.xml.internal.ws.api.message.Header header = null;
|
||||
Iterator<com.sun.xml.internal.ws.api.message.Header> it =
|
||||
msg.getHeaders().getHeaders(headerName,true);
|
||||
if (it.hasNext()) {
|
||||
header = it.next();
|
||||
if (it.hasNext()) {
|
||||
throw createDuplicateHeaderException();
|
||||
}
|
||||
}
|
||||
|
||||
if(header!=null)
|
||||
return setter.put( header.readAsJAXB(bridge), args );
|
||||
else
|
||||
// header not found.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the whole payload into a single JAXB bean.
|
||||
*/
|
||||
public static final class Body extends ResponseBuilder {
|
||||
private final XMLBridge<?> bridge;
|
||||
private final ValueSetter setter;
|
||||
|
||||
/**
|
||||
* @param bridge
|
||||
* specifies how to unmarshal the payload into a JAXB object.
|
||||
* @param setter
|
||||
* specifies how the obtained value is returned to the client.
|
||||
*/
|
||||
public Body(XMLBridge<?> bridge, ValueSetter setter) {
|
||||
this.bridge = bridge;
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) throws JAXBException {
|
||||
return setter.put( msg.readPayloadAsJAXB(bridge), args );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats a payload as multiple parts wrapped into one element,
|
||||
* and processes all such wrapped parts.
|
||||
*/
|
||||
public static final class DocLit extends ResponseBuilder {
|
||||
/**
|
||||
* {@link PartBuilder} keyed by the element name (inside the wrapper element.)
|
||||
*/
|
||||
private final PartBuilder[] parts;
|
||||
|
||||
private final XMLBridge wrapper;
|
||||
|
||||
private boolean dynamicWrapper;
|
||||
|
||||
public DocLit(WrapperParameter wp, ValueSetterFactory setterFactory) {
|
||||
wrapperName = wp.getName();
|
||||
wrapper = wp.getXMLBridge();
|
||||
Class wrapperType = (Class) wrapper.getTypeInfo().type;
|
||||
dynamicWrapper = WrapperComposite.class.equals(wrapperType);
|
||||
|
||||
List<PartBuilder> tempParts = new ArrayList<PartBuilder>();
|
||||
|
||||
List<ParameterImpl> children = wp.getWrapperChildren();
|
||||
for (ParameterImpl p : children) {
|
||||
if(p.isIN())
|
||||
continue;
|
||||
QName name = p.getName();
|
||||
if (dynamicWrapper) {
|
||||
if (wrappedParts == null) wrappedParts = new HashMap<QName,WrappedPartBuilder>();
|
||||
XMLBridge xmlBridge = p.getInlinedRepeatedElementBridge();
|
||||
if (xmlBridge == null) xmlBridge = p.getXMLBridge();
|
||||
wrappedParts.put( p.getName(), new WrappedPartBuilder(xmlBridge, setterFactory.get(p)));
|
||||
} else {
|
||||
try {
|
||||
tempParts.add(new PartBuilder(
|
||||
wp.getOwner().getBindingContext().getElementPropertyAccessor(
|
||||
wrapperType,
|
||||
name.getNamespaceURI(),
|
||||
p.getName().getLocalPart()),
|
||||
setterFactory.get(p)
|
||||
));
|
||||
// wrapper parameter itself always bind to body, and
|
||||
// so do all its children
|
||||
assert p.getBinding()== ParameterBinding.BODY;
|
||||
} catch (JAXBException e) {
|
||||
throw new WebServiceException( // TODO: i18n
|
||||
wrapperType+" do not have a property of the name "+name,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.parts = tempParts.toArray(new PartBuilder[tempParts.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) throws JAXBException, XMLStreamException {
|
||||
if (dynamicWrapper) return readWrappedResponse(msg, args);
|
||||
Object retVal = null;
|
||||
|
||||
if (parts.length>0) {
|
||||
if (!msg.hasPayload()) {
|
||||
throw new WebServiceException("No payload. Expecting payload with "+wrapperName+" element");
|
||||
}
|
||||
XMLStreamReader reader = msg.readPayload();
|
||||
XMLStreamReaderUtil.verifyTag(reader,wrapperName);
|
||||
Object wrapperBean = wrapper.unmarshal(reader, (msg.getAttachments() != null) ?
|
||||
new AttachmentUnmarshallerImpl(msg.getAttachments()): null);
|
||||
|
||||
try {
|
||||
for (PartBuilder part : parts) {
|
||||
Object o = part.readResponse(args,wrapperBean);
|
||||
// there's only at most one ResponseBuilder that returns a value.
|
||||
// TODO: reorder parts so that the return value comes at the end.
|
||||
if(o!=null) {
|
||||
assert retVal==null;
|
||||
retVal = o;
|
||||
}
|
||||
}
|
||||
} catch (DatabindingException e) {
|
||||
// this can happen when the set method throw a checked exception or something like that
|
||||
throw new WebServiceException(e); // TODO:i18n
|
||||
}
|
||||
|
||||
// we are done with the body
|
||||
reader.close();
|
||||
XMLStreamReaderFactory.recycle(reader);
|
||||
} else {
|
||||
msg.consume();
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshals each wrapped part into a JAXB object and moves it
|
||||
* to the expected place.
|
||||
*/
|
||||
static final class PartBuilder {
|
||||
private final PropertyAccessor accessor;
|
||||
private final ValueSetter setter;
|
||||
|
||||
/**
|
||||
* @param accessor
|
||||
* specifies which portion of the wrapper bean to obtain the value from.
|
||||
* @param setter
|
||||
* specifies how the obtained value is returned to the client.
|
||||
*/
|
||||
public PartBuilder(PropertyAccessor accessor, ValueSetter setter) {
|
||||
this.accessor = accessor;
|
||||
this.setter = setter;
|
||||
assert accessor!=null && setter!=null;
|
||||
}
|
||||
|
||||
final Object readResponse( Object[] args, Object wrapperBean ) {
|
||||
Object obj = accessor.get(wrapperBean);
|
||||
return setter.put(obj,args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats a payload as multiple parts wrapped into one element,
|
||||
* and processes all such wrapped parts.
|
||||
*/
|
||||
public static final class RpcLit extends ResponseBuilder {
|
||||
public RpcLit(WrapperParameter wp, ValueSetterFactory setterFactory) {
|
||||
assert wp.getTypeInfo().type== WrapperComposite.class;
|
||||
wrapperName = wp.getName();
|
||||
wrappedParts = new HashMap<QName,WrappedPartBuilder>();
|
||||
List<ParameterImpl> children = wp.getWrapperChildren();
|
||||
for (ParameterImpl p : children) {
|
||||
wrappedParts.put( p.getName(), new WrappedPartBuilder(
|
||||
p.getXMLBridge(), setterFactory.get(p)
|
||||
));
|
||||
// wrapper parameter itself always bind to body, and
|
||||
// so do all its children
|
||||
assert p.getBinding()== ParameterBinding.BODY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readResponse(Message msg, Object[] args) throws JAXBException, XMLStreamException {
|
||||
return readWrappedResponse(msg, args);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isXMLMimeType(String mimeType){
|
||||
return mimeType.equals("text/xml") || mimeType.equals("application/xml");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.model.CheckedExceptionImpl;
|
||||
import com.sun.xml.internal.ws.model.JavaMethodImpl;
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
import com.sun.xml.internal.ws.model.WrapperParameter;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link com.sun.xml.internal.ws.client.sei.MethodHandler} that handles synchronous method invocations.
|
||||
*
|
||||
* <p>
|
||||
* This class mainly performs the following two tasks:
|
||||
* <ol>
|
||||
* <li>Accepts Object[] that represents arguments for a Java method,
|
||||
* and creates {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} that represents a request message.
|
||||
* <li>Takes a {@link com.sun.xml.internal.ws.api.message.Message] that represents a response,
|
||||
* and extracts the return value (and updates {@link javax.xml.ws.Holder }s.)
|
||||
* </ol>
|
||||
*
|
||||
* <h2>Creating {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage }</h2>
|
||||
* <p>
|
||||
* At the construction time, we prepare {@link com.sun.xml.internal.ws.client.sei.BodyBuilder} and {@link com.sun.xml.internal.ws.client.sei.MessageFiller}s
|
||||
* that know how to move arguments into a {@link com.sun.xml.internal.ws.api.message.Message }.
|
||||
* Some arguments go to the payload, some go to headers, still others go to attachments.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
abstract class SEIMethodHandler extends MethodHandler {
|
||||
|
||||
// these objects together create a message from method parameters
|
||||
private BodyBuilder bodyBuilder;
|
||||
private MessageFiller[] inFillers;
|
||||
|
||||
protected String soapAction;
|
||||
|
||||
protected boolean isOneWay;
|
||||
|
||||
protected JavaMethodImpl javaMethod;
|
||||
|
||||
protected Map<QName, CheckedExceptionImpl> checkedExceptions;
|
||||
|
||||
SEIMethodHandler(SEIStub owner) {
|
||||
super(owner, null);
|
||||
}
|
||||
|
||||
SEIMethodHandler(SEIStub owner, JavaMethodImpl method) {
|
||||
super(owner, null);
|
||||
|
||||
//keep all the CheckedException model for the detail qname
|
||||
this.checkedExceptions = new HashMap<QName, CheckedExceptionImpl>();
|
||||
for(CheckedExceptionImpl ce : method.getCheckedExceptions()){
|
||||
checkedExceptions.put(ce.getBond().getTypeInfo().tagName, ce);
|
||||
}
|
||||
//If a non-"" soapAction is specified, wsa:action the SOAPAction
|
||||
if(method.getInputAction() != null && !method.getBinding().getSOAPAction().equals("") ) {
|
||||
this.soapAction = method.getInputAction();
|
||||
} else {
|
||||
this.soapAction = method.getBinding().getSOAPAction();
|
||||
}
|
||||
this.javaMethod = method;
|
||||
|
||||
{// prepare objects for creating messages
|
||||
List<ParameterImpl> rp = method.getRequestParameters();
|
||||
|
||||
BodyBuilder tmpBodyBuilder = null;
|
||||
List<MessageFiller> fillers = new ArrayList<MessageFiller>();
|
||||
|
||||
for (ParameterImpl param : rp) {
|
||||
ValueGetter getter = getValueGetterFactory().get(param);
|
||||
|
||||
switch(param.getInBinding().kind) {
|
||||
case BODY:
|
||||
if(param.isWrapperStyle()) {
|
||||
if(param.getParent().getBinding().isRpcLit())
|
||||
tmpBodyBuilder = new BodyBuilder.RpcLit((WrapperParameter)param, owner.soapVersion, getValueGetterFactory());
|
||||
else
|
||||
tmpBodyBuilder = new BodyBuilder.DocLit((WrapperParameter)param, owner.soapVersion, getValueGetterFactory());
|
||||
} else {
|
||||
tmpBodyBuilder = new BodyBuilder.Bare(param, owner.soapVersion, getter);
|
||||
}
|
||||
break;
|
||||
case HEADER:
|
||||
fillers.add(new MessageFiller.Header(
|
||||
param.getIndex(),
|
||||
param.getXMLBridge(),
|
||||
getter ));
|
||||
break;
|
||||
case ATTACHMENT:
|
||||
fillers.add(MessageFiller.AttachmentFiller.createAttachmentFiller(param, getter));
|
||||
break;
|
||||
case UNBOUND:
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError(); // impossible
|
||||
}
|
||||
}
|
||||
|
||||
if(tmpBodyBuilder==null) {
|
||||
// no parameter binds to body. we create an empty message
|
||||
switch(owner.soapVersion) {
|
||||
case SOAP_11:
|
||||
tmpBodyBuilder = BodyBuilder.EMPTY_SOAP11;
|
||||
break;
|
||||
case SOAP_12:
|
||||
tmpBodyBuilder = BodyBuilder.EMPTY_SOAP12;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
this.bodyBuilder = tmpBodyBuilder;
|
||||
this.inFillers = fillers.toArray(new MessageFiller[fillers.size()]);
|
||||
}
|
||||
|
||||
this.isOneWay = method.getMEP().isOneWay();
|
||||
}
|
||||
|
||||
ResponseBuilder buildResponseBuilder(JavaMethodImpl method, ValueSetterFactory setterFactory) {
|
||||
// prepare objects for processing response
|
||||
List<ParameterImpl> rp = method.getResponseParameters();
|
||||
List<ResponseBuilder> builders = new ArrayList<ResponseBuilder>();
|
||||
|
||||
for( ParameterImpl param : rp ) {
|
||||
ValueSetter setter;
|
||||
switch(param.getOutBinding().kind) {
|
||||
case BODY:
|
||||
if(param.isWrapperStyle()) {
|
||||
if(param.getParent().getBinding().isRpcLit())
|
||||
builders.add(new ResponseBuilder.RpcLit((WrapperParameter)param, setterFactory));
|
||||
else
|
||||
builders.add(new ResponseBuilder.DocLit((WrapperParameter)param, setterFactory));
|
||||
} else {
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(new ResponseBuilder.Body(param.getXMLBridge(),setter));
|
||||
}
|
||||
break;
|
||||
case HEADER:
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(new ResponseBuilder.Header(owner.soapVersion, param, setter));
|
||||
break;
|
||||
case ATTACHMENT:
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(ResponseBuilder.AttachmentBuilder.createAttachmentBuilder(param, setter));
|
||||
break;
|
||||
case UNBOUND:
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(new ResponseBuilder.NullSetter(setter,
|
||||
ResponseBuilder.getVMUninitializedValue(param.getTypeInfo().type)));
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
ResponseBuilder rb;
|
||||
switch(builders.size()) {
|
||||
case 0:
|
||||
rb = ResponseBuilder.NONE;
|
||||
break;
|
||||
case 1:
|
||||
rb = builders.get(0);
|
||||
break;
|
||||
default:
|
||||
rb = new ResponseBuilder.Composite(builders);
|
||||
}
|
||||
return rb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a request {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} from method arguments.
|
||||
* @param args proxy invocation arguments
|
||||
* @return Message for the arguments
|
||||
*/
|
||||
Message createRequestMessage(Object[] args) {
|
||||
Message msg = bodyBuilder.createMessage(args);
|
||||
|
||||
for (MessageFiller filler : inFillers)
|
||||
filler.fillIn(args,msg);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
abstract ValueGetterFactory getValueGetterFactory();
|
||||
|
||||
}
|
||||
201
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/SEIStub.java
Normal file
201
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/SEIStub.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.xml.internal.ws.api.SOAPVersion;
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.client.WSPortInfo;
|
||||
import com.sun.xml.internal.ws.api.databinding.Databinding;
|
||||
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
|
||||
import com.sun.xml.internal.ws.api.message.Header;
|
||||
import com.sun.xml.internal.ws.api.message.Headers;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.model.MEP;
|
||||
import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
|
||||
import com.sun.xml.internal.ws.api.pipe.Fiber;
|
||||
import com.sun.xml.internal.ws.api.pipe.Tube;
|
||||
import com.sun.xml.internal.ws.api.server.Container;
|
||||
import com.sun.xml.internal.ws.api.server.ContainerResolver;
|
||||
import com.sun.xml.internal.ws.binding.BindingImpl;
|
||||
import com.sun.xml.internal.ws.client.AsyncResponseImpl;
|
||||
import com.sun.xml.internal.ws.client.RequestContext;
|
||||
import com.sun.xml.internal.ws.client.ResponseContextReceiver;
|
||||
import com.sun.xml.internal.ws.client.Stub;
|
||||
import com.sun.xml.internal.ws.client.WSServiceDelegate;
|
||||
import com.sun.xml.internal.ws.model.JavaMethodImpl;
|
||||
import com.sun.xml.internal.ws.model.SOAPSEIModel;
|
||||
import com.sun.xml.internal.ws.wsdl.OperationDispatcher;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link Stub} that handles method invocations
|
||||
* through a strongly-typed endpoint interface.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class SEIStub extends Stub implements InvocationHandler {
|
||||
|
||||
Databinding databinding;
|
||||
|
||||
@Deprecated
|
||||
public SEIStub(WSServiceDelegate owner, BindingImpl binding, SOAPSEIModel seiModel, Tube master, WSEndpointReference epr) {
|
||||
super(owner, master, binding, seiModel.getPort(), seiModel.getPort().getAddress(), epr);
|
||||
this.seiModel = seiModel;
|
||||
this.soapVersion = binding.getSOAPVersion();
|
||||
databinding = seiModel.getDatabinding();
|
||||
initMethodHandlers();
|
||||
}
|
||||
|
||||
// added portInterface to the constructor, otherwise AsyncHandler won't work
|
||||
public SEIStub(WSPortInfo portInfo, BindingImpl binding, SOAPSEIModel seiModel, WSEndpointReference epr) {
|
||||
super(portInfo, binding, seiModel.getPort().getAddress(),epr);
|
||||
this.seiModel = seiModel;
|
||||
this.soapVersion = binding.getSOAPVersion();
|
||||
databinding = seiModel.getDatabinding();
|
||||
initMethodHandlers();
|
||||
}
|
||||
|
||||
private void initMethodHandlers() {
|
||||
Map<WSDLBoundOperation, JavaMethodImpl> syncs = new HashMap<WSDLBoundOperation, JavaMethodImpl>();
|
||||
|
||||
// fill in methodHandlers.
|
||||
// first fill in sychronized versions
|
||||
for (JavaMethodImpl m : seiModel.getJavaMethods()) {
|
||||
if (!m.getMEP().isAsync) {
|
||||
SyncMethodHandler handler = new SyncMethodHandler(this, m);
|
||||
syncs.put(m.getOperation(), m);
|
||||
methodHandlers.put(m.getMethod(), handler);
|
||||
}
|
||||
}
|
||||
|
||||
for (JavaMethodImpl jm : seiModel.getJavaMethods()) {
|
||||
JavaMethodImpl sync = syncs.get(jm.getOperation());
|
||||
if (jm.getMEP() == MEP.ASYNC_CALLBACK) {
|
||||
Method m = jm.getMethod();
|
||||
CallbackMethodHandler handler = new CallbackMethodHandler(
|
||||
this, m, m.getParameterTypes().length - 1);
|
||||
methodHandlers.put(m, handler);
|
||||
}
|
||||
if (jm.getMEP() == MEP.ASYNC_POLL) {
|
||||
Method m = jm.getMethod();
|
||||
PollingMethodHandler handler = new PollingMethodHandler(this, m);
|
||||
methodHandlers.put(m, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final SOAPSEIModel seiModel;
|
||||
|
||||
public final SOAPVersion soapVersion;
|
||||
|
||||
/**
|
||||
* Nullable when there is no associated WSDL Model
|
||||
* @return
|
||||
*/
|
||||
public @Nullable
|
||||
OperationDispatcher getOperationDispatcher() {
|
||||
if(operationDispatcher == null && wsdlPort != null)
|
||||
operationDispatcher = new OperationDispatcher(wsdlPort,binding,seiModel);
|
||||
return operationDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* For each method on the port interface we have
|
||||
* a {@link MethodHandler} that processes it.
|
||||
*/
|
||||
private final Map<Method, MethodHandler> methodHandlers = new HashMap<Method, MethodHandler>();
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
validateInputs(proxy, method);
|
||||
Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
|
||||
try {
|
||||
MethodHandler handler = methodHandlers.get(method);
|
||||
if (handler != null) {
|
||||
return handler.invoke(proxy, args);
|
||||
} else {
|
||||
// we handle the other method invocations by ourselves
|
||||
try {
|
||||
return method.invoke(this, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
// impossible
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
ContainerResolver.getDefault().exitContainer(old);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateInputs(Object proxy, Method method) {
|
||||
if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) {
|
||||
throw new IllegalStateException("Passed object is not proxy!");
|
||||
}
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
if (method == null || declaringClass == null
|
||||
|| Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("Invoking static method is not allowed!");
|
||||
}
|
||||
}
|
||||
|
||||
public final Packet doProcess(Packet request, RequestContext rc, ResponseContextReceiver receiver) {
|
||||
return super.process(request, rc, receiver);
|
||||
}
|
||||
|
||||
public final void doProcessAsync(AsyncResponseImpl<?> receiver, Packet request, RequestContext rc, Fiber.CompletionCallback callback) {
|
||||
super.processAsync(receiver, request, rc, callback);
|
||||
}
|
||||
|
||||
protected final @NotNull QName getPortName() {
|
||||
return wsdlPort.getName();
|
||||
}
|
||||
|
||||
|
||||
public void setOutboundHeaders(Object... headers) {
|
||||
if(headers==null)
|
||||
throw new IllegalArgumentException();
|
||||
Header[] hl = new Header[headers.length];
|
||||
for( int i=0; i<hl.length; i++ ) {
|
||||
if(headers[i]==null)
|
||||
throw new IllegalArgumentException();
|
||||
hl[i] = Headers.create(seiModel.getBindingContext(),headers[i]);
|
||||
}
|
||||
super.setOutboundHeaders(hl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.jws.soap.SOAPBinding.Style;
|
||||
|
||||
import com.sun.xml.internal.ws.api.message.MessageContextFactory;
|
||||
import com.sun.xml.internal.ws.model.JavaMethodImpl;
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
import com.sun.xml.internal.ws.model.WrapperParameter;
|
||||
|
||||
public class StubAsyncHandler extends StubHandler {
|
||||
|
||||
private final Class asyncBeanClass;
|
||||
|
||||
public StubAsyncHandler(JavaMethodImpl jm, JavaMethodImpl sync, MessageContextFactory mcf) {
|
||||
super(sync, mcf);
|
||||
|
||||
List<ParameterImpl> rp = sync.getResponseParameters();
|
||||
int size = 0;
|
||||
for( ParameterImpl param : rp ) {
|
||||
if (param.isWrapperStyle()) {
|
||||
WrapperParameter wrapParam = (WrapperParameter)param;
|
||||
size += wrapParam.getWrapperChildren().size();
|
||||
if (sync.getBinding().getStyle() == Style.DOCUMENT) {
|
||||
// doc/asyncBeanClass - asyncBeanClass bean is in async signature
|
||||
// Add 2 or more so that it is considered as async bean case
|
||||
size += 2;
|
||||
}
|
||||
} else {
|
||||
++size;
|
||||
}
|
||||
}
|
||||
|
||||
Class tempWrap = null;
|
||||
if (size > 1) {
|
||||
rp = jm.getResponseParameters();
|
||||
for(ParameterImpl param : rp) {
|
||||
if (param.isWrapperStyle()) {
|
||||
WrapperParameter wrapParam = (WrapperParameter)param;
|
||||
if (sync.getBinding().getStyle() == Style.DOCUMENT) {
|
||||
// doc/asyncBeanClass style
|
||||
tempWrap = (Class)wrapParam.getTypeInfo().type;
|
||||
break;
|
||||
}
|
||||
for(ParameterImpl p : wrapParam.getWrapperChildren()) {
|
||||
if (p.getIndex() == -1) {
|
||||
tempWrap = (Class)p.getTypeInfo().type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tempWrap != null) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (param.getIndex() == -1) {
|
||||
tempWrap = (Class)param.getTypeInfo().type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
asyncBeanClass = tempWrap;
|
||||
|
||||
switch(size) {
|
||||
case 0 :
|
||||
responseBuilder = buildResponseBuilder(sync, ValueSetterFactory.NONE);
|
||||
break;
|
||||
case 1 :
|
||||
responseBuilder = buildResponseBuilder(sync, ValueSetterFactory.SINGLE);
|
||||
break;
|
||||
default :
|
||||
responseBuilder = buildResponseBuilder(sync, new ValueSetterFactory.AsyncBeanValueSetterFactory(asyncBeanClass));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void initArgs(Object[] args) throws Exception {
|
||||
if (asyncBeanClass != null) {
|
||||
args[0] = asyncBeanClass.newInstance();
|
||||
}
|
||||
}
|
||||
|
||||
ValueGetterFactory getValueGetterFactory() {
|
||||
return ValueGetterFactory.ASYNC;
|
||||
}
|
||||
}
|
||||
272
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/StubHandler.java
Normal file
272
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/StubHandler.java
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.oracle.webservices.internal.api.databinding.JavaCallInfo;
|
||||
import com.sun.xml.internal.ws.api.SOAPVersion;
|
||||
import com.sun.xml.internal.ws.api.databinding.ClientCallBridge;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.MessageContextFactory;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.api.model.JavaMethod;
|
||||
import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
|
||||
import com.sun.xml.internal.ws.model.CheckedExceptionImpl;
|
||||
import com.sun.xml.internal.ws.model.JavaMethodImpl;
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
import com.sun.xml.internal.ws.model.WrapperParameter;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link com.sun.xml.internal.ws.client.sei.MethodHandler} that handles synchronous method invocations.
|
||||
* This is refactored from SEIMethodHandler.
|
||||
* <p>
|
||||
* This class mainly performs the following two tasks:
|
||||
* <ol>
|
||||
* <li>Accepts Object[] that represents arguments for a Java method,
|
||||
* and creates {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} that represents a request message.
|
||||
* <li>Takes a {@link com.sun.xml.internal.ws.api.message.Message} that represents a response,
|
||||
* and extracts the return value (and updates {@link javax.xml.ws.Holder }s.)
|
||||
* </ol>
|
||||
*
|
||||
* <h2>Creating {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage }</h2>
|
||||
* <p>
|
||||
* At the construction time, we prepare {@link com.sun.xml.internal.ws.client.sei.BodyBuilder} and {@link com.sun.xml.internal.ws.client.sei.MessageFiller}s
|
||||
* that know how to move arguments into a {@link com.sun.xml.internal.ws.api.message.Message }.
|
||||
* Some arguments go to the payload, some go to headers, still others go to attachments.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Jitendra Kotamraju
|
||||
* @author shih-chang.chen@oracle.com
|
||||
*/
|
||||
public class StubHandler implements ClientCallBridge {
|
||||
|
||||
// these objects together create a message from method parameters
|
||||
private final BodyBuilder bodyBuilder;
|
||||
private final MessageFiller[] inFillers;
|
||||
protected final String soapAction;
|
||||
protected final boolean isOneWay;
|
||||
protected final JavaMethodImpl javaMethod;
|
||||
protected final Map<QName, CheckedExceptionImpl> checkedExceptions;
|
||||
protected SOAPVersion soapVersion = SOAPVersion.SOAP_11;
|
||||
protected ResponseBuilder responseBuilder;
|
||||
protected MessageContextFactory packetFactory;
|
||||
|
||||
public StubHandler(JavaMethodImpl method, MessageContextFactory mcf) {
|
||||
//keep all the CheckedException model for the detail qname
|
||||
this.checkedExceptions = new HashMap<QName, CheckedExceptionImpl>();
|
||||
for(CheckedExceptionImpl ce : method.getCheckedExceptions()){
|
||||
checkedExceptions.put(ce.getBond().getTypeInfo().tagName, ce);
|
||||
}
|
||||
//If a non-"" soapAction is specified, wsa:action the SOAPAction
|
||||
String soapActionFromBinding = method.getBinding().getSOAPAction();
|
||||
if(method.getInputAction() != null && soapActionFromBinding != null && !soapActionFromBinding.equals("") ) {
|
||||
this.soapAction = method.getInputAction();
|
||||
} else {
|
||||
this.soapAction = soapActionFromBinding;
|
||||
}
|
||||
this.javaMethod = method;
|
||||
packetFactory = mcf;
|
||||
|
||||
soapVersion = javaMethod.getBinding().getSOAPVersion();
|
||||
|
||||
{// prepare objects for creating messages
|
||||
List<ParameterImpl> rp = method.getRequestParameters();
|
||||
|
||||
BodyBuilder bodyBuilder = null;
|
||||
List<MessageFiller> fillers = new ArrayList<MessageFiller>();
|
||||
|
||||
for (ParameterImpl param : rp) {
|
||||
ValueGetter getter = getValueGetterFactory().get(param);
|
||||
|
||||
switch(param.getInBinding().kind) {
|
||||
case BODY:
|
||||
if(param.isWrapperStyle()) {
|
||||
if(param.getParent().getBinding().isRpcLit())
|
||||
bodyBuilder = new BodyBuilder.RpcLit((WrapperParameter)param, soapVersion, getValueGetterFactory());
|
||||
else
|
||||
bodyBuilder = new BodyBuilder.DocLit((WrapperParameter)param, soapVersion, getValueGetterFactory());
|
||||
} else {
|
||||
bodyBuilder = new BodyBuilder.Bare(param, soapVersion, getter);
|
||||
}
|
||||
break;
|
||||
case HEADER:
|
||||
fillers.add(new MessageFiller.Header(
|
||||
param.getIndex(),
|
||||
param.getXMLBridge(),
|
||||
getter ));
|
||||
break;
|
||||
case ATTACHMENT:
|
||||
fillers.add(MessageFiller.AttachmentFiller.createAttachmentFiller(param, getter));
|
||||
break;
|
||||
case UNBOUND:
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError(); // impossible
|
||||
}
|
||||
}
|
||||
|
||||
if(bodyBuilder==null) {
|
||||
// no parameter binds to body. we create an empty message
|
||||
switch(soapVersion) {
|
||||
case SOAP_11:
|
||||
bodyBuilder = BodyBuilder.EMPTY_SOAP11;
|
||||
break;
|
||||
case SOAP_12:
|
||||
bodyBuilder = BodyBuilder.EMPTY_SOAP12;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
this.bodyBuilder = bodyBuilder;
|
||||
this.inFillers = fillers.toArray(new MessageFiller[fillers.size()]);
|
||||
}
|
||||
|
||||
this.isOneWay = method.getMEP().isOneWay();
|
||||
responseBuilder = buildResponseBuilder(method, ValueSetterFactory.SYNC);
|
||||
}
|
||||
|
||||
ResponseBuilder buildResponseBuilder(JavaMethodImpl method, ValueSetterFactory setterFactory) {
|
||||
// prepare objects for processing response
|
||||
List<ParameterImpl> rp = method.getResponseParameters();
|
||||
List<ResponseBuilder> builders = new ArrayList<ResponseBuilder>();
|
||||
|
||||
for( ParameterImpl param : rp ) {
|
||||
ValueSetter setter;
|
||||
switch(param.getOutBinding().kind) {
|
||||
case BODY:
|
||||
if(param.isWrapperStyle()) {
|
||||
if(param.getParent().getBinding().isRpcLit())
|
||||
builders.add(new ResponseBuilder.RpcLit((WrapperParameter)param, setterFactory));
|
||||
else
|
||||
builders.add(new ResponseBuilder.DocLit((WrapperParameter)param, setterFactory));
|
||||
} else {
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(new ResponseBuilder.Body(param.getXMLBridge(),setter));
|
||||
}
|
||||
break;
|
||||
case HEADER:
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(new ResponseBuilder.Header(soapVersion, param, setter));
|
||||
break;
|
||||
case ATTACHMENT:
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(ResponseBuilder.AttachmentBuilder.createAttachmentBuilder(param, setter));
|
||||
break;
|
||||
case UNBOUND:
|
||||
setter = setterFactory.get(param);
|
||||
builders.add(new ResponseBuilder.NullSetter(setter,
|
||||
ResponseBuilder.getVMUninitializedValue(param.getTypeInfo().type)));
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
ResponseBuilder rb;
|
||||
switch(builders.size()) {
|
||||
case 0:
|
||||
rb = ResponseBuilder.NONE;
|
||||
break;
|
||||
case 1:
|
||||
rb = builders.get(0);
|
||||
break;
|
||||
default:
|
||||
rb = new ResponseBuilder.Composite(builders);
|
||||
}
|
||||
return rb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a request {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} from method arguments.
|
||||
* @param args proxy invocation arguments
|
||||
* @return Message for the arguments
|
||||
*/
|
||||
public Packet createRequestPacket(JavaCallInfo args) {
|
||||
Message msg = bodyBuilder.createMessage(args.getParameters());
|
||||
|
||||
for (MessageFiller filler : inFillers) filler.fillIn(args.getParameters(),msg);
|
||||
|
||||
Packet req = (Packet)packetFactory.createContext(msg);
|
||||
req.setState(Packet.State.ClientRequest);
|
||||
req.soapAction = soapAction;
|
||||
req.expectReply = !isOneWay;
|
||||
req.getMessage().assertOneWay(isOneWay);
|
||||
req.setWSDLOperation(getOperationName());
|
||||
return req;
|
||||
}
|
||||
|
||||
ValueGetterFactory getValueGetterFactory() {
|
||||
return ValueGetterFactory.SYNC;
|
||||
}
|
||||
|
||||
public JavaCallInfo readResponse(Packet p, JavaCallInfo call) throws Throwable {
|
||||
Message msg = p.getMessage();
|
||||
if(msg.isFault()) {
|
||||
SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
|
||||
Throwable t = faultBuilder.createException(checkedExceptions);
|
||||
call.setException(t);
|
||||
throw t;
|
||||
} else {
|
||||
initArgs(call.getParameters());
|
||||
Object ret = responseBuilder.readResponse(msg, call.getParameters());
|
||||
call.setReturnValue(ret);
|
||||
return call;
|
||||
}
|
||||
}
|
||||
|
||||
public QName getOperationName() {
|
||||
//TODO javaMethod.getOperation()
|
||||
return javaMethod.getOperationQName();
|
||||
}
|
||||
|
||||
public String getSoapAction() {
|
||||
return soapAction;
|
||||
}
|
||||
|
||||
public boolean isOneWay() {
|
||||
return isOneWay;
|
||||
}
|
||||
|
||||
protected void initArgs(Object[] args) throws Exception {
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return javaMethod.getMethod();
|
||||
}
|
||||
|
||||
public JavaMethod getOperationModel() {
|
||||
return javaMethod;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.oracle.webservices.internal.api.databinding.JavaCallInfo;
|
||||
import com.sun.xml.internal.ws.api.message.Message;
|
||||
import com.sun.xml.internal.ws.api.message.Packet;
|
||||
import com.sun.xml.internal.ws.client.RequestContext;
|
||||
import com.sun.xml.internal.ws.client.ResponseContextReceiver;
|
||||
import com.sun.xml.internal.ws.encoding.soap.DeserializationException;
|
||||
import com.sun.xml.internal.ws.message.jaxb.JAXBMessage;
|
||||
import com.sun.xml.internal.ws.model.JavaMethodImpl;
|
||||
import com.sun.xml.internal.ws.resources.DispatchMessages;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.ws.Holder;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* {@link MethodHandler} that handles synchronous method invocations.
|
||||
*
|
||||
* <p>
|
||||
* This class mainly performs the following two tasks:
|
||||
* <ol>
|
||||
* <li>Accepts Object[] that represents arguments for a Java method,
|
||||
* and creates {@link JAXBMessage} that represents a request message.
|
||||
* <li>Takes a {@link Message] that represents a response,
|
||||
* and extracts the return value (and updates {@link Holder}s.)
|
||||
* </ol>
|
||||
*
|
||||
* <h2>Creating {@link JAXBMessage}</h2>
|
||||
* <p>
|
||||
* At the construction time, we prepare {@link BodyBuilder} and {@link MessageFiller}s
|
||||
* that know how to move arguments into a {@link Message}.
|
||||
* Some arguments go to the payload, some go to headers, still others go to attachments.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class SyncMethodHandler extends MethodHandler {
|
||||
final boolean isVoid;
|
||||
final boolean isOneway;
|
||||
final JavaMethodImpl javaMethod;
|
||||
SyncMethodHandler(SEIStub owner, JavaMethodImpl jm) {
|
||||
super(owner, jm.getMethod());
|
||||
javaMethod = jm;
|
||||
isVoid = void.class.equals(jm.getMethod().getReturnType());
|
||||
isOneway = jm.getMEP().isOneWay();
|
||||
}
|
||||
|
||||
Object invoke(Object proxy, Object[] args) throws Throwable {
|
||||
return invoke(proxy,args,owner.requestContext,owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes synchronously, but with the given {@link RequestContext}
|
||||
* and {@link ResponseContextReceiver}.
|
||||
*
|
||||
* @param rc
|
||||
* This {@link RequestContext} is used for invoking this method.
|
||||
* We take this as a separate parameter because of the async invocation
|
||||
* handling, which requires a separate copy.
|
||||
*/
|
||||
Object invoke(Object proxy, Object[] args, RequestContext rc, ResponseContextReceiver receiver) throws Throwable {
|
||||
JavaCallInfo call = owner.databinding.createJavaCallInfo(method, args);
|
||||
Packet req = (Packet) owner.databinding.serializeRequest(call);
|
||||
// process the message
|
||||
Packet reply = owner.doProcess(req,rc,receiver);
|
||||
|
||||
Message msg = reply.getMessage();
|
||||
if(msg == null) {
|
||||
if (!isOneway || !isVoid) {
|
||||
throw new WebServiceException(DispatchMessages.INVALID_RESPONSE());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
call = owner.databinding.deserializeResponse(reply, call);
|
||||
if (call.getException() != null) {
|
||||
throw call.getException();
|
||||
} else {
|
||||
return call.getReturnValue();
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
throw new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(), e);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(),e);
|
||||
} finally {
|
||||
if (reply.transportBackChannel != null)
|
||||
reply.transportBackChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
ValueGetterFactory getValueGetterFactory() {
|
||||
return ValueGetterFactory.SYNC;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import javax.jws.WebParam.Mode;
|
||||
import javax.xml.ws.Holder;
|
||||
|
||||
/**
|
||||
* Gets a value from an object that represents a parameter passed
|
||||
* as a method argument.
|
||||
*
|
||||
* <p>
|
||||
* This abstraction hides the handling of {@link Holder}.
|
||||
*
|
||||
* <p>
|
||||
* {@link ValueGetter} is a stateless behavior encapsulation.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
enum ValueGetter {
|
||||
/**
|
||||
* {@link ValueGetter} that works for {@link Mode#IN} parameter.
|
||||
*
|
||||
* <p>
|
||||
* Since it's the IN mode, the parameter is not a {@link Holder},
|
||||
* therefore the parameter itself is a value.
|
||||
*/
|
||||
PLAIN() {
|
||||
Object get(Object parameter) {
|
||||
return parameter;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Creates {@link ValueGetter} that works for {@link Holder},
|
||||
* which is {@link Mode#INOUT} or {@link Mode#OUT}.
|
||||
*
|
||||
* <p>
|
||||
* In those {@link Mode}s, the parameter is a {@link Holder},
|
||||
* so the value to be sent is obtained by getting the value of the holder.
|
||||
*/
|
||||
HOLDER() {
|
||||
Object get(Object parameter) {
|
||||
if(parameter==null)
|
||||
// the user is allowed to pass in null where a Holder is expected.
|
||||
return null;
|
||||
return ((Holder)parameter).value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the value to be sent, from a parameter given as a method argument.
|
||||
* @param parameter that is passed by proxy
|
||||
* @return if it holder then its value, otherise parameter itself
|
||||
*/
|
||||
abstract Object get(Object parameter);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
|
||||
import javax.jws.WebParam;
|
||||
|
||||
/**
|
||||
* {@link ValueGetterFactory} is used to create {@link ValueGetter} objects.
|
||||
*
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
abstract class ValueGetterFactory {
|
||||
|
||||
abstract ValueGetter get(ParameterImpl p);
|
||||
|
||||
static final ValueGetterFactory SYNC = new ValueGetterFactory() {
|
||||
ValueGetter get(ParameterImpl p) {
|
||||
return (p.getMode()== WebParam.Mode.IN || p.getIndex() == -1)
|
||||
? ValueGetter.PLAIN : ValueGetter.HOLDER;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* In case of SEI async signatures, there are no holders. The OUT
|
||||
* parameters go in async bean class
|
||||
*/
|
||||
static final ValueGetterFactory ASYNC = new ValueGetterFactory() {
|
||||
ValueGetter get(ParameterImpl p) {
|
||||
return ValueGetter.PLAIN;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
193
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/ValueSetter.java
Normal file
193
jdkSrc/jdk8/com/sun/xml/internal/ws/client/sei/ValueSetter.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.api.model.Parameter;
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
import com.sun.xml.internal.ws.spi.db.PropertyAccessor;
|
||||
|
||||
import javax.xml.ws.Holder;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
/**
|
||||
* Moves a Java value unmarshalled from a response message
|
||||
* to the right place.
|
||||
*
|
||||
* <p>
|
||||
* Sometimes values are returned as a return value, and
|
||||
* others are returned in the {@link Holder} value. Instances
|
||||
* of this interface abstracts this detail.
|
||||
*
|
||||
* <p>
|
||||
* {@link ValueSetter} is a stateless behavior encapsulation.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class ValueSetter {
|
||||
private ValueSetter() {}
|
||||
|
||||
/**
|
||||
* Moves the value to the expected place.
|
||||
*
|
||||
* @param obj
|
||||
* The unmarshalled object.
|
||||
* @param args
|
||||
* The arguments given to the Java method invocation. If <tt>obj</tt>
|
||||
* is supposed to be returned as a {@link Holder} value, a suitable
|
||||
* {@link Holder} is obtained from this argument list and <tt>obj</tt>
|
||||
* is set.
|
||||
*
|
||||
* @return
|
||||
* if <tt>obj</tt> is supposed to be returned as a return value
|
||||
* from the method, this method returns <tt>obj</tt>. Otherwise null.
|
||||
*/
|
||||
abstract Object put(Object obj, Object[] args);
|
||||
|
||||
/**
|
||||
* Singleton instance.
|
||||
*/
|
||||
private static final ValueSetter RETURN_VALUE = new ReturnValue();
|
||||
/**
|
||||
* {@link Param}s with small index numbers are used often,
|
||||
* so we pool them to reduce the footprint.
|
||||
*/
|
||||
private static final ValueSetter[] POOL = new ValueSetter[16];
|
||||
|
||||
static {
|
||||
for( int i=0; i<POOL.length; i++ )
|
||||
POOL[i] = new Param(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link ValueSetter} suitable for the given {@link Parameter}.
|
||||
*/
|
||||
static ValueSetter getSync(ParameterImpl p) {
|
||||
int idx = p.getIndex();
|
||||
|
||||
if(idx==-1)
|
||||
return RETURN_VALUE;
|
||||
if(idx<POOL.length)
|
||||
return POOL[idx];
|
||||
else
|
||||
return new Param(idx);
|
||||
}
|
||||
|
||||
|
||||
private static final class ReturnValue extends ValueSetter {
|
||||
Object put(Object obj, Object[] args) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
static final class Param extends ValueSetter {
|
||||
/**
|
||||
* Index of the argument to put the value to.
|
||||
*/
|
||||
private final int idx;
|
||||
|
||||
public Param(int idx) {
|
||||
this.idx = idx;
|
||||
}
|
||||
|
||||
Object put(Object obj, Object[] args) {
|
||||
Object arg = args[idx];
|
||||
if(arg!=null) {
|
||||
// we build model in such a way that this is guaranteed
|
||||
assert arg instanceof Holder;
|
||||
((Holder)arg).value = obj;
|
||||
}
|
||||
// else {
|
||||
// if null is given as a Holder, there's no place to return
|
||||
// the value, so just ignore.
|
||||
// }
|
||||
|
||||
// no value to return
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton instance.
|
||||
*/
|
||||
static final ValueSetter SINGLE_VALUE = new SingleValue();
|
||||
|
||||
/**
|
||||
* Used in case of async invocation, where there is only one OUT parameter
|
||||
*/
|
||||
private static final class SingleValue extends ValueSetter {
|
||||
/**
|
||||
* Set args[0] as the value
|
||||
*/
|
||||
Object put(Object obj, Object[] args) {
|
||||
args[0] = obj;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OUT parameters are set in async bean
|
||||
*/
|
||||
static final class AsyncBeanValueSetter extends ValueSetter {
|
||||
|
||||
private final PropertyAccessor accessor;
|
||||
|
||||
AsyncBeanValueSetter(ParameterImpl p, Class wrapper) {
|
||||
QName name = p.getName();
|
||||
try {
|
||||
accessor = p.getOwner().getBindingContext().getElementPropertyAccessor(
|
||||
wrapper, name.getNamespaceURI(), name.getLocalPart() );
|
||||
} catch (JAXBException e) {
|
||||
throw new WebServiceException( // TODO: i18n
|
||||
wrapper+" do not have a property of the name "+name,e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property in async bean instance
|
||||
*
|
||||
* @param obj property in async bean
|
||||
* @param args args[0] contains async bean instance
|
||||
* @return null always
|
||||
*/
|
||||
Object put(Object obj, Object[] args) {
|
||||
assert args != null;
|
||||
assert args.length == 1;
|
||||
assert args[0] != null;
|
||||
|
||||
Object bean = args[0];
|
||||
try {
|
||||
accessor.set(bean, obj);
|
||||
} catch (Exception e) {
|
||||
throw new WebServiceException(e); // TODO:i18n
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
|
||||
import com.sun.xml.internal.ws.model.ParameterImpl;
|
||||
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* {@link ValueSetterFactory} is used to create {@link ValueSetter}.
|
||||
*
|
||||
* @author Jitendra Kotamraju
|
||||
*/
|
||||
public abstract class ValueSetterFactory {
|
||||
|
||||
public abstract ValueSetter get(ParameterImpl p);
|
||||
|
||||
public static final ValueSetterFactory SYNC = new ValueSetterFactory() {
|
||||
public ValueSetter get(ParameterImpl p) {
|
||||
return ValueSetter.getSync(p);
|
||||
}
|
||||
};
|
||||
|
||||
public static final ValueSetterFactory NONE = new ValueSetterFactory() {
|
||||
public ValueSetter get(ParameterImpl p) {
|
||||
throw new WebServiceException("This shouldn't happen. No response parameters.");
|
||||
}
|
||||
};
|
||||
|
||||
public static final ValueSetterFactory SINGLE = new ValueSetterFactory() {
|
||||
public ValueSetter get(ParameterImpl p) {
|
||||
return ValueSetter.SINGLE_VALUE;
|
||||
}
|
||||
};
|
||||
|
||||
public static final class AsyncBeanValueSetterFactory extends ValueSetterFactory {
|
||||
private Class asyncBean;
|
||||
|
||||
public AsyncBeanValueSetterFactory(Class asyncBean) {
|
||||
this.asyncBean = asyncBean;
|
||||
}
|
||||
|
||||
public ValueSetter get(ParameterImpl p) {
|
||||
return new ValueSetter.AsyncBeanValueSetter(p, asyncBean);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link SEIStub} and its supporting code.
|
||||
*/
|
||||
package com.sun.xml.internal.ws.client.sei;
|
||||
Reference in New Issue
Block a user