You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@axis.apache.org by ve...@apache.org on 2011/08/10 23:17:16 UTC
svn commit: r1156372 [2/2] - in /axis/axis2/java/core/branches/1_6: ./
modules/addressing/src/org/apache/axis2/handlers/addressing/
modules/jaxws-integration/test-resources/wsdl/
modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/ modules/jax...
Modified: axis/axis2/java/core/branches/1_6/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/branches/1_6/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java?rev=1156372&r1=1156371&r2=1156372&view=diff
==============================================================================
--- axis/axis2/java/core/branches/1_6/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java (original)
+++ axis/axis2/java/core/branches/1_6/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java Wed Aug 10 21:17:15 2011
@@ -19,26 +19,41 @@
package org.apache.axis2.jaxws.client.dispatch;
import junit.framework.TestCase;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.description.Parameter;
+import org.apache.axis2.engine.AxisConfiguration;
+import org.apache.axis2.jaxws.Constants;
import org.apache.axis2.jaxws.description.DescriptionTestUtils2;
+import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.ServiceDescription;
+import org.apache.axis2.jaxws.description.builder.MDQConstants;
+import org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl;
import org.apache.axis2.jaxws.spi.ClientMetadataTest;
import org.apache.axis2.jaxws.spi.ServiceDelegate;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* Tests the caching and isolation of dynamic ports,i.e. those created with
* Service.addPort(...). Dynamic ports should
- * 1) Only be visible to services on which an addPort was done
+ * 1) Only be visible to the service instances on which an addPort was done
* 2) Share instances of the description objects (e.g. AxisService) for ports
- * added to different instances of the same service that use the same client
- * configuration
- * 3) Identical ports on services using different client configuration should
- * not be shared
+ * added to the same instance of a service
+ * 3) Different service instances of the same-named service should not share the
+ * the list of added dynamic ports. Even if the same named port is added to each
+ * service, they should not share metadata objects (e.g. EndpointDescription, AxisService)
+ *
+ * Also validate the property that enables the previous behavior that allowed
+ * sharing of dyamic ports across services on the same AxisConfiguration. With
+ * that property enabled, Dynamic ports should
+ * 1) Be shared across all services on the AxisConfiguration based on the key
+ * (PortQName, BindingId, EndpointAddress).
*/
public class DynamicPortCachingTests extends TestCase {
static final String namespaceURI = "http://dispatch.client.jaxws.axis2.apache.org";
@@ -49,11 +64,149 @@ public class DynamicPortCachingTests ext
static final String epr1 = null;
/**
- * Two different instances of the same service should share the same
- * description information (e.g. AxisService) if the same port is added
- * to both
+ * Validate setting the property enables the old behavior, which is that dynamic ports are
+ * shared across all services on an AxisConfiguration based on the key
+ * (PortQName, BindingId, EndpointAddress). This test validates that two ports that share the
+ * same Service QName will be share the same dynamic port objects.
+ *
+ * NOTE!!! This test exists for validating backwards compatability. This behavior was NOT
+ * intended in the runtime, but since it existed that way, customers could be depending on it.
+ */
+ public void testSamePortsSameServiceName_AxisConfig_PropertyTrue() {
+ try {
+ ClientMetadataTest.installCachingFactory();
+ QName svcQN = new QName(namespaceURI, svcLocalPart);
+
+ Service svc1 = Service.create(svcQN);
+ assertNotNull(svc1);
+ ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1);
+ assertNotNull(svcDlg1);
+ ServiceDescription svcDesc1 = svcDlg1.getServiceDescription();
+ assertNotNull(svcDesc1);
+
+ // Set the property to revert the behavior. Note that although we are passing ni
+ // a particular service, the property is set on the AxisConfig shared by all
+ // services.
+ setAxisConfigParameter(svc1, MDQConstants.SHARE_DYNAMIC_PORTS_ACROSS_SERVICES, "true");
+
+ Service svc2 = Service.create(svcQN);
+ assertNotNull(svc2);
+ ServiceDelegate svcDlg2 = DescriptionTestUtils2.getServiceDelegate(svc2);
+ assertNotNull(svcDlg2);
+ ServiceDescription svcDesc2 = svcDlg2.getServiceDescription();
+ assertNotNull(svcDesc2);
+
+ assertNotSame("Service instances should not be the same", svc1, svc2);
+ assertNotSame("Service delegates should not be the same", svcDlg1, svcDlg2);
+ assertSame("Instance of ServiceDescription should be the same", svcDesc1, svcDesc2);
+
+ // Add a port to 1st service, should not be visible under the 2nd service
+ svc1.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ assertEquals(0, getList(svc2.getPorts()).size());
+
+ // Add the same port to 2nd service, should now have same ports and description
+ // objects
+ svc2.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ assertEquals(1, getList(svc2.getPorts()).size());
+
+ // Make sure the EndpointDescription objects are shared.
+ Collection<?> epDesc1Collection =
+ ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1);
+ Collection<?> epDesc2Collection =
+ ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2);
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size());
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size());
+
+ EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray()[0];
+ EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray()[0];
+ assertSame("EndpointDescriptions not shared", epDesc1, epDesc2);
+
+ } finally {
+ ClientMetadataTest.restoreOriginalFactory();
+ }
+
+ }
+ /**
+ * Validate setting the property enables the old behavior, which is that dynamic ports are
+ * shared across all services on an AxisConfiguration based on the key
+ * (PortQName, BindingId, EndpointAddress). This test validates that two ports that have
+ * different Service QNames will still share the same dynamic port objects.
+ *
+ * NOTE!!! This test exists for validating backwards compatability. This behavior was NOT
+ * intended in the runtime, but since it existed that way, customers could be depending on it.
+ */
+ public void testSamePortsDifferentServiceName_AxisConfig_PropertyTrue() {
+ try {
+ ClientMetadataTest.installCachingFactory();
+ QName svcQN = new QName(namespaceURI, svcLocalPart);
+
+ Service svc1 = Service.create(svcQN);
+ assertNotNull(svc1);
+ ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1);
+ assertNotNull(svcDlg1);
+ ServiceDescription svcDesc1 = svcDlg1.getServiceDescription();
+ assertNotNull(svcDesc1);
+
+ // Set the property to revert the behavior. Note that although we are passing ni
+ // a particular service, the property is set on the AxisConfig shared by all
+ // services.
+ setAxisConfigParameter(svc1, MDQConstants.SHARE_DYNAMIC_PORTS_ACROSS_SERVICES, "true");
+
+ QName svcQN2 = new QName(namespaceURI, svcLocalPart + "2");
+ Service svc2 = Service.create(svcQN2);
+ assertNotNull(svc2);
+ ServiceDelegate svcDlg2 = DescriptionTestUtils2.getServiceDelegate(svc2);
+ assertNotNull(svcDlg2);
+ ServiceDescription svcDesc2 = svcDlg2.getServiceDescription();
+ assertNotNull(svcDesc2);
+
+ assertNotSame("Service instances should not be the same", svc1, svc2);
+ assertNotSame("Service delegates should not be the same", svcDlg1, svcDlg2);
+ assertNotSame("Instance of ServiceDescription should be the same", svcDesc1, svcDesc2);
+
+ // Add a port to 1st service, should not be visible under the 2nd service
+ svc1.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ assertEquals(0, getList(svc2.getPorts()).size());
+
+ // Add the same port to 2nd service, should now have same ports and description
+ // objects
+ svc2.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ assertEquals(1, getList(svc2.getPorts()).size());
+
+ // Make sure the EndpointDescription objects are shared.
+ Collection<?> epDesc1Collection =
+ ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1);
+ Collection<?> epDesc2Collection =
+ ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2);
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size());
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size());
+
+ EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray()[0];
+ EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray()[0];
+ assertSame("EndpointDescriptions not shared", epDesc1, epDesc2);
+
+ } finally {
+ ClientMetadataTest.restoreOriginalFactory();
+ }
+
+ }
+ /**
+ * Validate that without the property set to revert the behavior, the default is that the ports are
+ * NOT shared across different instances of services with the same name
*/
- public void _testSamePortsSameService() {
+ public void testSamePortsSameServiceNameDifferentInstances() {
try {
ClientMetadataTest.installCachingFactory();
QName svcQN = new QName(namespaceURI, svcLocalPart);
@@ -91,8 +244,122 @@ public class DynamicPortCachingTests ext
assertEquals(1, getList(svc1.getPorts()).size());
assertEquals(1, getList(svc2.getPorts()).size());
+ // Make sure the EndpointDescription objects are not shared.
+ Collection<?> epDesc1Collection =
+ ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1);
+ Collection<?> epDesc2Collection =
+ ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2);
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size());
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size());
+
+ EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray()[0];
+ EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray()[0];
+ assertNotSame("EndpointDescriptions not shared", epDesc1, epDesc2);
+ } finally {
+ ClientMetadataTest.restoreOriginalFactory();
+ }
+
+ }
+
+ /**
+ * Validate that adding the same dynamic port to the same service instance re-uses the same
+ * description objects (e.g. EndpointDescription)
+ */
+ public void testSamePortsSameServiceInstance() {
+ try {
+ ClientMetadataTest.installCachingFactory();
+ QName svcQN = new QName(namespaceURI, svcLocalPart);
+
+ Service svc1 = Service.create(svcQN);
+ assertNotNull(svc1);
+ ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1);
+ assertNotNull(svcDlg1);
+ ServiceDescription svcDesc1 = svcDlg1.getServiceDescription();
+ assertNotNull(svcDesc1);
+
+ // Add a port to service, save off the metadata to validate later
+ svc1.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ Collection<?> epDesc1Collection =
+ ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1);
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size());
+ EndpointDescription epDescFirstAddPort = (EndpointDescription) epDesc1Collection.toArray()[0];
+
+ // Add the same port to the same service instance, should use the same description objects
+ svc1.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ // Make sure the EndpointDescription object is reused for second port.
+ Collection<?> epDesc2Collection =
+ ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1);
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size());
+
+ EndpointDescription epDescSecondAddPort = (EndpointDescription) epDesc1Collection.toArray()[0];
+ assertSame("EndpointDescriptions not reused", epDescFirstAddPort, epDescSecondAddPort);
+
+ } finally {
+ ClientMetadataTest.restoreOriginalFactory();
+ }
+
+ }
+ /**
+ * Validate that ports added to services with different service names (and thus different service instances)
+ * are not shared.
+ */
+ public void testSamePortsDifferentServiceNames() {
+ try {
+ ClientMetadataTest.installCachingFactory();
+ QName svcQN = new QName(namespaceURI, svcLocalPart);
+ Service svc1 = Service.create(svcQN);
+ assertNotNull(svc1);
+ ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1);
+ assertNotNull(svcDlg1);
+ ServiceDescription svcDesc1 = svcDlg1.getServiceDescription();
+ assertNotNull(svcDesc1);
+
+ QName svcQN2 = new QName(namespaceURI, svcLocalPart + "2");
+ Service svc2 = Service.create(svcQN2);
+ assertNotNull(svc2);
+ ServiceDelegate svcDlg2 = DescriptionTestUtils2.getServiceDelegate(svc2);
+ assertNotNull(svcDlg2);
+ ServiceDescription svcDesc2 = svcDlg2.getServiceDescription();
+ assertNotNull(svcDesc2);
+
+ assertNotSame("Service instances should not be the same", svc1, svc2);
+ assertNotSame("Service delegates should not be the same", svcDlg1, svcDlg2);
+ assertNotSame("Instance of ServiceDescription should not be the same", svcDesc1, svcDesc2);
+
+ // Add a port to 1st service, should not be visible under the 2nd service
+ svc1.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ assertEquals(0, getList(svc2.getPorts()).size());
+
+ // Add the same port to 2nd service, should now have same ports and description
+ // objects
+ svc2.addPort(new QName(namespaceURI, dynamicPort1),
+ bindingID1,
+ epr1);
+ assertEquals(1, getList(svc1.getPorts()).size());
+ assertEquals(1, getList(svc2.getPorts()).size());
+
+ // Make sure the EndpointDescription objects are NOT shared.
+ Collection<?> epDesc1Collection =
+ ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1);
+ Collection<?> epDesc2Collection =
+ ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2);
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size());
+ assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size());
+
+ EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray().clone()[0];
+ EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray().clone()[0];
+ assertNotSame("EndpointDescriptions should not be shared across different services", epDesc1, epDesc2);
} finally {
ClientMetadataTest.restoreOriginalFactory();
@@ -124,4 +391,17 @@ public class DynamicPortCachingTests ext
}
return returnList;
}
+
+ private void setAxisConfigParameter(Service service, String key, String value) {
+ ServiceDelegate delegate = DescriptionTestUtils2.getServiceDelegate(service);
+ ServiceDescription svcDesc = delegate.getServiceDescription();
+ AxisConfiguration axisConfig = svcDesc.getAxisConfigContext().getAxisConfiguration();
+ Parameter parameter = new Parameter(key, value);
+ try {
+ axisConfig.addParameter(parameter);
+ } catch (AxisFault e) {
+ fail("Unable to set Parameter on AxisConfig due to exception " + e);
+ }
+ }
+
}
\ No newline at end of file
Modified: axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/ExceptionFactory.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/ExceptionFactory.java?rev=1156372&r1=1156371&r2=1156372&view=diff
==============================================================================
--- axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/ExceptionFactory.java (original)
+++ axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/ExceptionFactory.java Wed Aug 10 21:17:15 2011
@@ -323,6 +323,27 @@ public class ExceptionFactory {
pw.close();
return sw.getBuffer().toString();
}
-
+
+ /**
+ * Give a target Throwable, set the initialCause Throwable as the initial cause on the target.
+ * @param target The throwable on which to set the initial cause
+ * @param initialCause The initial cause to set on the target Throwable.
+ */
+ public static void setInitialCause(Throwable target, Throwable initialCause) {
+ if (target != null && initialCause != null) {
+ // Create a WebServiceException from the initialCause throwable. This skips over things like
+ // AxisFault as a cause. Set the result on the target throwable.
+ try {
+ WebServiceException localException = ExceptionFactory.makeWebServiceException(initialCause);
+ target.initCause(localException.getCause());
+ } catch (Throwable t) {
+ // If the cause had already been set, then it can't be set again; it throws an exception.
+ if (log.isDebugEnabled()) {
+ log.debug("Caught exception trying to set initial cause on: " + target +". Initial cause: " +
+ initialCause + ". Caught: " + t);
+ }
+ }
+ }
+ }
}
Modified: axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/builder/MDQConstants.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/builder/MDQConstants.java?rev=1156372&r1=1156371&r2=1156372&view=diff
==============================================================================
--- axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/builder/MDQConstants.java (original)
+++ axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/builder/MDQConstants.java Wed Aug 10 21:17:15 2011
@@ -98,4 +98,24 @@ public class MDQConstants {
public static final String SUN_WEB_METHOD_BEHAVIOR_CHANGE_VERSION = "2.1.6";
public static final String USE_POST_WEB_METHOD_RULES = "jaxws.runtime.usePostWebMethodRules";
+ /**
+ * Context Property:
+ * Name: jaxws.share.dynamic.ports.enable
+ * Value: String "false" or "true"
+ * Default: null, which is interpreted as "false"
+ * Can be set on:
+ * - Axis Configuration, which indicates that dynamic ports should be shared across services based on
+ * a key of (PortQName, BindingId, EndpointAddress)
+ *
+ * Dynamic ports, which are those created by Service.addPort(...), should only be visible to the instance
+ * of the service that did the addPort. However, for backwards compatibility, this flag can be used
+ * to enable the sharing of dynamic ports across all services on an AxisConfiguration based on the key
+ * (PortQName, BindingId, EndpointAddress).
+ *
+ * The default setting of this property is null, which is interpreted as "false", which will scope the
+ * visibility of dynamic ports to the instance of the service that did the addPort().
+ */
+ public static final String SHARE_DYNAMIC_PORTS_ACROSS_SERVICES = "jaxws.share.dynamic.ports.enable";
+
+
}
Modified: axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java?rev=1156372&r1=1156371&r2=1156372&view=diff
==============================================================================
--- axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java (original)
+++ axis/axis2/java/core/branches/1_6/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java Wed Aug 10 21:17:15 2011
@@ -146,6 +146,14 @@ public class ServiceDescriptionImpl
// RUNTIME INFORMATION
Map<String, ServiceRuntimeDescription> runtimeDescMap =
new ConcurrentHashMap<String, ServiceRuntimeDescription>();
+
+ /**
+ * Property representing a collection of endpointDescription instances for dynamic ports
+ * which are shared across all services on an AxisConfig. Note that this behavior is incorrect; dynamic
+ * ports should only be visible to the instance of the service that created them. However, the sharing
+ * across services is maintained for backwards compatibility.
+ * @deprecated
+ */
private static final String JAXWS_DYNAMIC_ENDPOINTS = "jaxws.dynamic.endpoints";
/**
@@ -491,7 +499,7 @@ public class ServiceDescriptionImpl
Messages.getMessage("serviceDescriptionImplAddPortErr"));
}
- endpointDescription = createEndpointDescriptionImpl(sei, portQName, bindingId, endpointAddress);
+ endpointDescription = getDynamicEndpointDescriptionImpl(sei, portQName, bindingId, endpointAddress);
addDynamicEndpointDescriptionImpl(endpointDescription, serviceDelegateKey);
} else {
@@ -596,19 +604,104 @@ public class ServiceDescriptionImpl
return endpointDescription;
}
- private EndpointDescriptionImpl createEndpointDescriptionImpl(Class sei, QName portQName, String bindingId, String endpointAddress) {
+ /**
+ * Find or create an EndpointDescription instance for a dynamic port. Dynamic ports should be scoped to
+ * the instance of the service that created them, so the method getDynamicEndpointDescriptionImpl should
+ * have find one if it already exists. However, logic was introduced (in Apache Axis2 revision 664411) that
+ * also scoped dynamic ports to a configuration context based on port name, binding ID, and endpointAddress.
+ * Although that logic is incorrect, it is maintained for backwards compatability based on the setting of
+ * a property.
+ *
+ * @param sei
+ * @param portQName
+ * @param bindingId
+ * @param endpointAddress
+ * @return
+ */
+ private EndpointDescriptionImpl getDynamicEndpointDescriptionImpl(Class sei, QName portQName, String bindingId, String endpointAddress) {
if (log.isDebugEnabled()) {
log.debug("Calling createEndpointDescriptionImpl : ("
+ portQName + "," + bindingId + "," + endpointAddress + ")");
}
EndpointDescriptionImpl endpointDescription = null;
+ SharedDynamicEndpointEntry sharedDynamicEndpointEntry = null;
+ boolean areDynamicPortsShared = isShareDynamicPortsAcrossServicesEnabled();
+ if (areDynamicPortsShared) {
+ // If ports are being shared, see if there's already one in the cache. Note that this will
+ // always return an Entry value, but the endpoint in it may be null if one wasn't found.
+ sharedDynamicEndpointEntry = findSharedDynamicEndpoint(portQName, bindingId, endpointAddress);
+ endpointDescription = sharedDynamicEndpointEntry.endpointDescription;
+ }
+
+ boolean endpointCreated = false;
+ if(endpointDescription == null) {
+ endpointDescription = new EndpointDescriptionImpl(sei, portQName, true, this);
+ endpointCreated = true;
+ }
+ if (areDynamicPortsShared && endpointCreated) {
+ // If ports are being shared and a new endpoint was created, then it needs to be
+ // added to the cache. Note that the other values in the entry (the cache hashmap and
+ // the key) were set when we looked for the entry above.
+ sharedDynamicEndpointEntry.endpointDescription = endpointDescription;
+ cacheSharedDynamicPointEndpoint(sharedDynamicEndpointEntry);
+ }
+ return endpointDescription;
+ }
+
+ /**
+ * Add the EndpointDescriptionImpl representing the dynamic port to the cache of ports shared across
+ * services.
+ * @param sharedDynamicEndpointEntry Contains the EndpointDescriptionImpl instance and the key
+ * associated with to be added to the cache, which is also contained in the entry.
+ */
+ private void cacheSharedDynamicPointEndpoint(SharedDynamicEndpointEntry sharedDynamicEndpointEntry) {
+
+ HashMap cachedDescriptions = sharedDynamicEndpointEntry.cachedDescriptions;
+ String key = sharedDynamicEndpointEntry.key;
+ EndpointDescriptionImpl endpointDescription = sharedDynamicEndpointEntry.endpointDescription;
+
+ synchronized(cachedDescriptions) {
+ if (log.isDebugEnabled()) {
+ log.debug("Calling cachedDescriptions.put : ("
+ + key.toString() + ") : size - " + cachedDescriptions.size());
+ }
+ cachedDescriptions.put(key.toString(), new WeakReference(endpointDescription));
+ }
+ }
+
+ /**
+ * Look for an existing shared endpointDescriptionImpl instance corresponding to a dynamic port based on
+ * a key of(portQname, bindingId, endpointAddress). Note that sharing dynamic ports across services is
+ * disable by default, and must be enabled via a property. Dynamic ports, by default, should only be
+ * visible to the instance of the service that added them.
+ *
+ * Note that a SharedDynamicEntry will be returned whether or not an existing EndpointDescriptionImpl
+ * is found. If one is not found, then one needs to be created and then added to the cache. The information
+ * in the returned SharedDynamicEntry can be used to add it.
+ *
+ * @see #isShareDynamicPortsAcrossServicesEnabled()
+ * @see #cacheSharedDynamicPointEndpoint(SharedDynamicEndpointEntry)
+ * @see SharedDynamicEndpointEntry
+ * @see #getDynamicEndpointDescriptionImpl(QName, Object)
+ *
+ * @param portQName
+ * @param bindingId
+ * @param endpointAddress
+ * @return A non-null SharedDynamicEndpointEntry is always returned. The key and cachedDescriptions
+ * variables will always be set. If an existing endpoint is found, then endpointDescription will be non-null.
+ */
+ private SharedDynamicEndpointEntry findSharedDynamicEndpoint(QName portQName,
+ String bindingId, String endpointAddress) {
+
+ SharedDynamicEndpointEntry returnDynamicEntry = new SharedDynamicEndpointEntry();
+ EndpointDescriptionImpl sharedDynamicEndpoint = null;
+
AxisConfiguration configuration = configContext.getAxisConfiguration();
if (log.isDebugEnabled()) {
log.debug("looking for " + JAXWS_DYNAMIC_ENDPOINTS + " in AxisConfiguration : " + configuration);
}
Parameter parameter = configuration.getParameter(JAXWS_DYNAMIC_ENDPOINTS);
- HashMap cachedDescriptions = (HashMap)
- ((parameter == null) ? null : parameter.getValue());
+ HashMap cachedDescriptions = (HashMap)((parameter == null) ? null : parameter.getValue());
if(cachedDescriptions == null) {
cachedDescriptions = new HashMap();
try {
@@ -622,10 +715,10 @@ public class ServiceDescriptionImpl
} else {
if (log.isDebugEnabled()) {
log.debug("found old jaxws.dynamic.endpoints cache in AxisConfiguration (" + cachedDescriptions + ") with size : ("
- + cachedDescriptions.size() + ")");
+ + cachedDescriptions.size() + ")");
}
}
-
+
StringBuffer key = new StringBuffer();
key.append(portQName == null ? "NULL" : portQName.toString());
key.append(':');
@@ -635,27 +728,50 @@ public class ServiceDescriptionImpl
synchronized(cachedDescriptions) {
WeakReference ref = (WeakReference) cachedDescriptions.get(key.toString());
if (ref != null) {
- endpointDescription = (EndpointDescriptionImpl) ref.get();
- }
- }
- if(endpointDescription == null) {
- endpointDescription = new EndpointDescriptionImpl(sei, portQName, true, this);
- synchronized(cachedDescriptions) {
+ sharedDynamicEndpoint = (EndpointDescriptionImpl) ref.get();
if (log.isDebugEnabled()) {
- log.debug("Calling cachedDescriptions.put : ("
- + key.toString() + ") : size - " + cachedDescriptions.size());
+ log.debug("found old entry for endpointDescription in jaxws.dynamic.endpoints cache : ("
+ + cachedDescriptions.size() + ")");
}
- cachedDescriptions.put(key.toString(), new WeakReference(endpointDescription));
}
- } else {
- if (log.isDebugEnabled()) {
- log.debug("found old entry for endpointDescription in jaxws.dynamic.endpoints cache : ("
- + cachedDescriptions.size() + ")");
+ }
+
+ returnDynamicEntry.cachedDescriptions = cachedDescriptions;
+ returnDynamicEntry.key = key.toString();
+ returnDynamicEntry.endpointDescription = sharedDynamicEndpoint;
+
+ return returnDynamicEntry;
+ }
+
+ /**
+ * Answer if dynamic ports are to be shared across services. The default value is FALSE, but it
+ * can be configured by an AxisConfig property. Note that this can only be set via a config property
+ * and not via a request context property since the setting affects multiple services.
+ *
+ * @return true if dynamic ports are to be shared across services, false otherwise.
+ */
+ private boolean isShareDynamicPortsAcrossServicesEnabled() {
+ boolean resolutionEnabled = false;
+
+ // See if an AxisConfig property enables the sharing of dynamic ports
+ String flagValue = null;
+ AxisConfiguration axisConfig = getAxisConfigContext().getAxisConfiguration();
+ Parameter parameter = axisConfig.getParameter(MDQConstants.SHARE_DYNAMIC_PORTS_ACROSS_SERVICES);
+ if (parameter != null) {
+ flagValue = (String) parameter.getValue();
+ }
+
+ // If the property was set, check the value.
+ if (flagValue != null) {
+ if ("false".equalsIgnoreCase(flagValue)) {
+ resolutionEnabled = false;
+ } else if ("true".equalsIgnoreCase(flagValue)) {
+ resolutionEnabled = true;
}
}
- return endpointDescription;
+ return resolutionEnabled;
}
-
+
/**
* This method will get all properties that have been set on the DescriptionBuilderComposite
* instance. If the DBC represents an implementation class that references an SEI, the
@@ -3039,4 +3155,13 @@ public class ServiceDescriptionImpl
return responses;
}
+ /**
+ * Entry returned from looking for an endpointDescriptionImpl for a shared dynamic port, or to be used
+ * to add one that was created to the cache.
+ */
+ class SharedDynamicEndpointEntry {
+ String key;
+ EndpointDescriptionImpl endpointDescription;
+ HashMap cachedDescriptions;
+ }
}
Modified: axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java?rev=1156372&r1=1156371&r2=1156372&view=diff
==============================================================================
--- axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java (original)
+++ axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java Wed Aug 10 21:17:15 2011
@@ -26,9 +26,12 @@ import org.apache.axiom.om.impl.OMMultip
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.impl.dom.soap11.SOAP11Factory;
import org.apache.axiom.soap.impl.dom.soap12.SOAP12Factory;
+import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.saaj.util.SAAJUtil;
import org.apache.axis2.transport.http.HTTPConstants;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.ParseException;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
@@ -73,13 +76,13 @@ public class SOAPMessageImpl extends SOA
String contentType = null;
String tmpContentType = "";
if (mimeHeaders != null) {
- String contentTypes[] = mimeHeaders.getHeader(HTTPConstants.CONTENT_TYPE);
+ String contentTypes[] = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
if (contentTypes != null && contentTypes.length > 0) {
tmpContentType = contentTypes[0];
contentType = SAAJUtil.normalizeContentType(tmpContentType);
}
}
- if ("multipart/related".equals(contentType)) {
+ if (HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED.equals(contentType)) {
try {
Attachments attachments =
new Attachments(inputstream, tmpContentType, false, "", "");
@@ -88,7 +91,7 @@ public class SOAPMessageImpl extends SOA
// parts of the SOAP message package. We need to reconstruct them from
// the available information.
MimeHeaders soapPartHeaders = new MimeHeaders();
- soapPartHeaders.addHeader(HTTPConstants.CONTENT_TYPE,
+ soapPartHeaders.addHeader(HTTPConstants.HEADER_CONTENT_TYPE,
attachments.getSOAPPartContentType());
String soapPartContentId = attachments.getSOAPPartContentID();
soapPartHeaders.addHeader("Content-ID", "<" + soapPartContentId + ">");
@@ -164,6 +167,7 @@ public class SOAPMessageImpl extends SOA
*/
public void removeAllAttachments() {
attachmentParts.clear();
+ saveRequired = true;
}
/**
@@ -223,7 +227,8 @@ public class SOAPMessageImpl extends SOA
public void addAttachmentPart(AttachmentPart attachmentPart) {
if (attachmentPart != null) {
attachmentParts.add(attachmentPart);
- mimeHeaders.setHeader(HTTPConstants.CONTENT_TYPE, "multipart/related");
+ mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, "multipart/related");
+ saveRequired = true;
}
}
@@ -267,8 +272,70 @@ public class SOAPMessageImpl extends SOA
* @throws SOAPException if there was a problem saving changes to this message.
*/
public void saveChanges() throws SOAPException {
+ try {
+ String contentTypeValue = getSingleHeaderValue(HTTPConstants.HEADER_CONTENT_TYPE);
+ ContentType contentType = null;
+ if (isEmptyString(contentTypeValue)) {
+ if (attachmentParts.size() > 0) {
+ contentTypeValue = HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED;
+ } else {
+ contentTypeValue = getBaseType();
+ }
+ }
+ contentType = new ContentType(contentTypeValue);
+
+ //Use configures the baseType with multipart/related while no attachment exists or all the attachments are removed
+ if(contentType.getBaseType().equals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED) && attachmentParts.size() == 0) {
+ contentType = new ContentType(getBaseType());
+ }
+
+ //If it is of multipart/related, initialize those required values in the content-type, including boundary etc.
+ if (contentType.getBaseType().equals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED)) {
+
+ //Configure boundary
+ String boundaryParam = contentType.getParameter("boundary");
+ if (isEmptyString(boundaryParam)) {
+ contentType.setParameter("boundary", UIDGenerator.generateMimeBoundary());
+ }
+
+ //Configure start content id, always get it from soapPart in case it is changed
+ String soapPartContentId = soapPart.getContentId();
+ if (isEmptyString(soapPartContentId)) {
+ soapPartContentId = "<" + UIDGenerator.generateContentId() + ">";
+ soapPart.setContentId(soapPartContentId);
+ }
+ contentType.setParameter("start", soapPartContentId);
+
+ //Configure contentId for each attachments
+ for(AttachmentPart attachmentPart : attachmentParts) {
+ if(isEmptyString(attachmentPart.getContentId())) {
+ attachmentPart.setContentId("<" + UIDGenerator.generateContentId() + ">");
+ }
+ }
+
+ //Configure type
+ contentType.setParameter("type", getBaseType());
+
+ //Configure charset
+ String soapPartContentTypeValue = getSingleHeaderValue(soapPart.getMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ ContentType soapPartContentType = null;
+ if (isEmptyString(soapPartContentTypeValue)) {
+ soapPartContentType = new ContentType(soapPartContentTypeValue);
+ } else {
+ soapPartContentType = new ContentType(getBaseType());
+ }
+ setCharsetParameter(soapPartContentType);
+ } else {
+ //Configure charset
+ setCharsetParameter(contentType);
+ }
+
+ mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType.toString());
+ } catch (ParseException e) {
+ throw new SOAPException("Invalid Content Type Field in the Mime Message", e);
+ }
+
saveRequired = false;
- // TODO not sure of the implementation
}
public void setSaveRequired() {
@@ -299,23 +366,45 @@ public class SOAPMessageImpl extends SOA
* @throws IOException if an I/O error occurs
*/
public void writeTo(OutputStream out) throws SOAPException, IOException {
- try {
+ try {
+ saveChanges();
OMOutputFormat format = new OMOutputFormat();
String enc = (String)getProperty(CHARACTER_SET_ENCODING);
format.setCharSetEncoding(enc != null ? enc : OMOutputFormat.DEFAULT_CHAR_SET_ENCODING);
String writeXmlDecl = (String)getProperty(WRITE_XML_DECLARATION);
if (writeXmlDecl == null || writeXmlDecl.equals("false")) {
-
//SAAJ default case doesn't send XML decl
format.setIgnoreXMLDeclaration(true);
}
-
- SOAPEnvelope envelope = ((SOAPEnvelopeImpl)soapPart.getEnvelope()).getOMEnvelope();
+
+ SOAPEnvelope envelope = ((SOAPEnvelopeImpl) soapPart.getEnvelope()).getOMEnvelope();
if (attachmentParts.isEmpty()) {
envelope.serialize(out, format);
} else {
- format.setSOAP11(((SOAPEnvelopeImpl)soapPart.getEnvelope()).getOMFactory()
- instanceof SOAP11Factory);
+ ContentType contentType = new ContentType(getSingleHeaderValue(HTTPConstants.HEADER_CONTENT_TYPE));
+ String boundary = contentType.getParameter("boundary");
+ if(isEmptyString(boundary)) {
+ boundary = UIDGenerator.generateMimeBoundary();
+ contentType.setParameter("boundary", boundary);
+ }
+ format.setMimeBoundary(boundary);
+
+ String rootContentId = soapPart.getContentId();
+ if(isEmptyString(rootContentId)) {
+ rootContentId = "<" + UIDGenerator.generateContentId() + ">";
+ soapPart.setContentId(rootContentId);
+ }
+ contentType.setParameter("start", rootContentId);
+ if ((rootContentId.indexOf("<") > -1) & (rootContentId.indexOf(">") > -1)) {
+ rootContentId = rootContentId.substring(1, (rootContentId.length() - 1));
+ }
+ format.setRootContentId(rootContentId);
+
+ format.setSOAP11(((SOAPEnvelopeImpl) soapPart.getEnvelope()).getOMFactory() instanceof SOAP11Factory);
+
+ //Double save the content-type in case anything is updated
+ mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType.toString());
+
OMMultipartWriter mpw = new OMMultipartWriter(out, format);
OutputStream rootPartOutputStream = mpw.writeRootPart();
envelope.serialize(rootPartOutputStream);
@@ -325,7 +414,8 @@ public class SOAPMessageImpl extends SOA
}
mpw.complete();
}
- saveChanges();
+
+ saveRequired = true;
} catch (Exception e) {
throw new SOAPException(e);
}
@@ -453,6 +543,7 @@ public class SOAPMessageImpl extends SOA
}
attachmentParts.clear();
this.attachmentParts = newAttachmentParts;
+ saveRequired = true;
}
/**
@@ -502,4 +593,45 @@ public class SOAPMessageImpl extends SOA
}
}
}
+
+ private boolean isEmptyString(String value) {
+ return value == null || value.length() == 0;
+ }
+
+ private String getSingleHeaderValue(String[] values) {
+ return values != null && values.length > 0 ? values[0] : null;
+ }
+
+ private String getSingleHeaderValue(String name) {
+ String[] values = mimeHeaders.getHeader(name);
+ if (values == null || values.length == 0) {
+ return null;
+ } else {
+ return values[0];
+ }
+ }
+
+ private String getBaseType() throws SOAPException {
+ boolean isSOAP12 = ((SOAPEnvelopeImpl) soapPart.getEnvelope()).getOMFactory() instanceof SOAP12Factory;
+ return isSOAP12 ? HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML : HTTPConstants.MEDIA_TYPE_TEXT_XML;
+ }
+
+ /**
+ * If the charset is configured by CHARACTER_SET_ENCODING, set it in the contentPart always.
+ * If it has already been configured in the contentType, leave it there.
+ * UTF-8 is used as the default value.
+ * @param contentType
+ * @throws SOAPException
+ */
+ private void setCharsetParameter(ContentType contentType) throws SOAPException{
+ String charset = (String)getProperty(CHARACTER_SET_ENCODING);
+ if (!isEmptyString(charset)) {
+ contentType.setParameter("charset", charset);
+ } else {
+ charset = contentType.getParameter("charset");
+ if(isEmptyString(charset)) {
+ contentType.setParameter("charset", "UTF-8");
+ }
+ }
+ }
}
Modified: axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java?rev=1156372&r1=1156371&r2=1156372&view=diff
==============================================================================
--- axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java (original)
+++ axis/axis2/java/core/branches/1_6/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java Wed Aug 10 21:17:15 2011
@@ -89,7 +89,7 @@ public class SOAPPartImpl extends SOAPPa
SOAPEnvelopeImpl soapEnvelope) {
//setMimeHeader(HTTPConstants.HEADER_CONTENT_ID, IDGenerator.generateID());
//setMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE, "text/xml");
- this.mimeHeaders = parentSoapMsg.getMimeHeaders();
+ this.mimeHeaders = SAAJUtil.copyMimeHeaders(parentSoapMsg.getMimeHeaders());
soapMessage = parentSoapMsg;
envelope = soapEnvelope;
document = soapEnvelope.getOwnerDocument();
@@ -122,7 +122,7 @@ public class SOAPPartImpl extends SOAPPa
this.mimeHeaders.addHeader("Content-ID", IDGenerator.generateID());
this.mimeHeaders.addHeader("content-type", HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML);
} else {
- String contentTypes[] = mimeHeaders.getHeader(HTTPConstants.CONTENT_TYPE);
+ String contentTypes[] = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
if (contentTypes != null && contentTypes.length > 0) {
try {
contentType = new ContentType(contentTypes[0]);
Modified: axis/axis2/java/core/branches/1_6/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/branches/1_6/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java?rev=1156372&r1=1156371&r2=1156372&view=diff
==============================================================================
--- axis/axis2/java/core/branches/1_6/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java (original)
+++ axis/axis2/java/core/branches/1_6/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java Wed Aug 10 21:17:15 2011
@@ -21,11 +21,13 @@ package org.apache.axis2.saaj;
import junit.framework.Assert;
import org.apache.axis2.saaj.util.SAAJDataSource;
+import org.apache.axis2.transport.http.HTTPConstants;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.activation.DataHandler;
+import javax.mail.internet.ContentType;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
@@ -45,6 +47,8 @@ import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.stream.StreamSource;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -187,8 +191,7 @@ public class SOAPMessageTest extends Ass
}
}
- // TODO: check why this fails with Sun's SAAJ implementation
- @Test
+ @Validated @Test
public void testGetContent() {
try {
MessageFactory fac = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
@@ -201,7 +204,7 @@ public class SOAPMessageTest extends Ass
AttachmentPart ap;
InputStream inputStream = TestUtils.getTestFile("attach.xml");
- ap = msg.createAttachmentPart(inputStream, "text/xml");
+ ap = msg.createAttachmentPart(new StreamSource(inputStream), "text/xml");
DataHandler dh =
new DataHandler(new SAAJDataSource(inputStream, 1000, "text/xml", true));
@@ -229,6 +232,67 @@ public class SOAPMessageTest extends Ass
}
}
+ @Validated @Test
+ public void testContentTypeGeneration() throws Exception{
+ MessageFactory fac = MessageFactory.newInstance();
+ SOAPMessage msg = fac.createMessage();
+ InputStream inputStream = TestUtils.getTestFile("attach.xml");
+ AttachmentPart ap = msg.createAttachmentPart(new StreamSource(inputStream), "text/xml");
+ msg.addAttachmentPart(ap);
+ msg.saveChanges();
+ assertNotNull(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ String contentTypeValue = msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0];
+ ContentType contentType = new ContentType(contentTypeValue);
+ assertNotNull("boundary parameter should exist in the content-type header", contentType.getParameter("boundary"));
+ //start parameter is not checked, due to it is optional parameter, and seems RI will not add this value
+ //assertNotNull("start parameter should exist in the content-type header", contentType.getParameter("start"));
+ assertNotNull("type parameter should exist in the content-type header", contentType.getParameter("type"));
+ assertEquals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED, contentType.getBaseType());
+ }
+
+ @Validated @Test
+ public void testCreateMessageWithMimeHeaders() throws Exception{
+ MessageFactory fac = MessageFactory.newInstance();
+ SOAPMessage msg = fac.createMessage();
+ InputStream inputStream = TestUtils.getTestFile("attach.xml");
+ AttachmentPart ap = msg.createAttachmentPart(new StreamSource(inputStream), "text/xml");
+ msg.addAttachmentPart(ap);
+ msg.saveChanges();
+ ContentType contentType = new ContentType(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ msg.writeTo(out);
+ SOAPMessage msg2 = fac.createMessage(msg.getMimeHeaders(), new ByteArrayInputStream(out.toByteArray()));
+ msg2.saveChanges();
+ ContentType contentType2 = new ContentType(msg2.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+
+ assertEquals(contentType.getBaseType(), contentType2.getBaseType());
+ assertEquals(contentType.getParameter("boundary"), contentType2.getParameter("boundary"));
+ assertEquals(contentType.getParameter("type"), contentType2.getParameter("type"));
+ //start parameter is not checked, due to it is an optional parameter, and seems RI will not add this value
+ //assertEquals(contentType.getParameter("start"), contentType2.getParameter("start"));
+ }
+
+ @Validated @Test
+ public void testContentTypeUpdateWithAttachmentChanges() throws Exception{
+ MessageFactory fac = MessageFactory.newInstance();
+ SOAPMessage msg = fac.createMessage();
+ InputStream inputStream = TestUtils.getTestFile("attach.xml");
+ AttachmentPart ap = msg.createAttachmentPart(new StreamSource(inputStream), "text/xml");
+ msg.addAttachmentPart(ap);
+ msg.saveChanges();
+
+ assertNotNull(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ ContentType contentType = new ContentType(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+ assertEquals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED, contentType.getBaseType());
+
+ msg.removeAllAttachments();
+ msg.saveChanges();
+
+ assertNotNull(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ contentType = new ContentType(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+ assertEquals("text/xml", contentType.getBaseType());
+ }
private StringBuffer copyToBuffer(InputStream inputStream) {
if (inputStream == null) {