Author: chris.laprun(a)jboss.com
Date: 2010-08-12 10:20:29 -0400 (Thu, 12 Aug 2010)
New Revision: 3812
Added:
components/wsrp/trunk/consumer/src/test/java/org/gatein/wsrp/consumer/services/
components/wsrp/trunk/consumer/src/test/java/org/gatein/wsrp/consumer/services/SOAPServiceFactoryTestCase.java
Modified:
components/wsrp/trunk/consumer/pom.xml
components/wsrp/trunk/consumer/src/main/java/org/gatein/wsrp/services/SOAPServiceFactory.java
Log:
- GTNWSRP-56: Parse WSDL before building the service as we might encounter semi-random
service name, rendering impossible
to create the service client for sure using the de-facto standard name. There are still
some cases that we don't support.
Modified: components/wsrp/trunk/consumer/pom.xml
===================================================================
--- components/wsrp/trunk/consumer/pom.xml 2010-08-12 12:29:15 UTC (rev 3811)
+++ components/wsrp/trunk/consumer/pom.xml 2010-08-12 14:20:29 UTC (rev 3812)
@@ -83,6 +83,11 @@
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</dependency>
+ <dependency>
+ <groupId>wsdl4j</groupId>
+ <artifactId>wsdl4j</artifactId>
+ <version>1.6.2</version>
+ </dependency>
<dependency>
<groupId>org.gatein.wsrp</groupId>
Modified:
components/wsrp/trunk/consumer/src/main/java/org/gatein/wsrp/services/SOAPServiceFactory.java
===================================================================
---
components/wsrp/trunk/consumer/src/main/java/org/gatein/wsrp/services/SOAPServiceFactory.java 2010-08-12
12:29:15 UTC (rev 3811)
+++
components/wsrp/trunk/consumer/src/main/java/org/gatein/wsrp/services/SOAPServiceFactory.java 2010-08-12
14:20:29 UTC (rev 3812)
@@ -43,11 +43,17 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.wsdl.Definition;
+import javax.wsdl.Port;
+import javax.wsdl.WSDLException;
+import javax.wsdl.factory.WSDLFactory;
+import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import java.net.MalformedURLException;
import java.net.URI;
+import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -64,9 +70,9 @@
private boolean isV2 = false;
private static final String WSRP_V1_URN =
"urn:oasis:names:tc:wsrp:v1:wsdl";
- private final static QName V1_SERVICE = new QName(WSRP_V1_URN,
"WSRPService");
+ private static final String WSRP_V1_BINDING =
"urn:oasis:names:tc:wsrp:v1:bind";
private static final String WSRP_V2_URN =
"urn:oasis:names:tc:wsrp:v2:wsdl";
- private final static QName V2_SERVICE = new QName(WSRP_V2_URN,
"WSRPService");
+ private static final String WSRP_V2_BINDING =
"urn:oasis:names:tc:wsrp:v2:bind";
private Map<Class, Object> services = new ConcurrentHashMap<Class,
Object>();
private String markupURL;
@@ -219,13 +225,17 @@
try
{
ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(wsdlDefinitionURL,
"WSDL URL", "SOAPServiceFactory");
- URI wsdlURL = new URI(wsdlDefinitionURL);
+ URL wsdlURL = new URI(wsdlDefinitionURL).toURL();
+ WSDLInfo wsdlInfo = new WSDLInfo(wsdlDefinitionURL);
+
// try to get v2 of service if possible, first
+ QName wsrp2 = wsdlInfo.getWSRP2ServiceQName();
+ QName wsrp1 = wsdlInfo.getWSRP1ServiceQName();
Service service;
- try
+ if (wsrp2 != null)
{
- service = Service.create(wsdlURL.toURL(), V2_SERVICE);
+ service = Service.create(wsdlURL, wsrp2);
WSRPV2MarkupPortType markupPortType =
service.getPort(WSRPV2MarkupPortType.class);
services.put(WSRPV2MarkupPortType.class, markupPortType);
@@ -247,40 +257,34 @@
setAvailable(true);
isV2 = true;
}
- catch (IllegalArgumentException e)
+ else if (wsrp1 != null)
{
- // if exception message contains both URNs, then it should mean that we only
have V1 service, so get that
- // todo: we could allow user to choose what happens here instead of
proceeding automatically...
- String message = e.getMessage();
- if (message.contains(WSRP_V1_URN) && message.contains(WSRP_V2_URN))
- {
- service = Service.create(wsdlURL.toURL(), V1_SERVICE);
+ service = Service.create(wsdlURL, wsrp1);
- WSRPV1MarkupPortType markupPortType =
service.getPort(WSRPV1MarkupPortType.class);
- services.put(WSRPV1MarkupPortType.class, markupPortType);
- markupURL =
(String)((BindingProvider)markupPortType).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
+ WSRPV1MarkupPortType markupPortType =
service.getPort(WSRPV1MarkupPortType.class);
+ services.put(WSRPV1MarkupPortType.class, markupPortType);
+ markupURL =
(String)((BindingProvider)markupPortType).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
- WSRPV1ServiceDescriptionPortType sdPort =
service.getPort(WSRPV1ServiceDescriptionPortType.class);
- services.put(WSRPV1ServiceDescriptionPortType.class, sdPort);
- serviceDescriptionURL =
(String)((BindingProvider)sdPort).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
+ WSRPV1ServiceDescriptionPortType sdPort =
service.getPort(WSRPV1ServiceDescriptionPortType.class);
+ services.put(WSRPV1ServiceDescriptionPortType.class, sdPort);
+ serviceDescriptionURL =
(String)((BindingProvider)sdPort).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
- WSRPV1PortletManagementPortType managementPortType =
service.getPort(WSRPV1PortletManagementPortType.class);
- services.put(WSRPV1PortletManagementPortType.class, managementPortType);
- portletManagementURL =
(String)((BindingProvider)managementPortType).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
+ WSRPV1PortletManagementPortType managementPortType =
service.getPort(WSRPV1PortletManagementPortType.class);
+ services.put(WSRPV1PortletManagementPortType.class, managementPortType);
+ portletManagementURL =
(String)((BindingProvider)managementPortType).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
- WSRPV1RegistrationPortType registrationPortType =
service.getPort(WSRPV1RegistrationPortType.class);
- services.put(WSRPV1RegistrationPortType.class, registrationPortType);
- registrationURL =
(String)((BindingProvider)registrationPortType).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
+ WSRPV1RegistrationPortType registrationPortType =
service.getPort(WSRPV1RegistrationPortType.class);
+ services.put(WSRPV1RegistrationPortType.class, registrationPortType);
+ registrationURL =
(String)((BindingProvider)registrationPortType).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
- setFailed(false);
- setAvailable(true);
- isV2 = false;
- }
- else
- {
- throw new IllegalArgumentException("Couldn't find any WSRP
service in specified WSDL: " + wsdlDefinitionURL);
- }
+ setFailed(false);
+ setAvailable(true);
+ isV2 = false;
}
+ else
+ {
+ throw new IllegalArgumentException("Couldn't find any WSRP service
in specified WSDL: " + wsdlDefinitionURL);
+ }
}
catch (MalformedURLException e)
{
@@ -351,4 +355,95 @@
return new V1RegistrationService(port);
}
}
+
+ protected class WSDLInfo
+ {
+ private final QName wsrp2ServiceQName;
+ private final QName wsrp1ServiceQName;
+
+ public WSDLInfo(String wsdlURL) throws WSDLException
+ {
+ WSDLFactory wsdlFactory = WSDLFactory.newInstance();
+ WSDLReader wsdlReader = wsdlFactory.newWSDLReader();
+
+ wsdlReader.setFeature("javax.wsdl.verbose", false);
+ wsdlReader.setFeature("javax.wsdl.importDocuments", false);
+
+ Definition definition = wsdlReader.readWSDL(wsdlURL);
+ Map<QName, javax.wsdl.Service> services = definition.getServices();
+ int serviceNb = services.size();
+ if (serviceNb > 2)
+ {
+ throw new WSDLException(WSDLException.OTHER_ERROR,
+ "The specified WSDL contains more than 2 services definitions when we
expected at most 2: one for WSRP 1 and one for WSRP 2.");
+ }
+
+ QName wsrp1 = null, wsrp2 = null;
+ for (QName name : services.keySet())
+ {
+ String ns = name.getNamespaceURI();
+ javax.wsdl.Service service = services.get(name);
+
+ // if the namespace is using one of the WSRP-defined ones, we have a
potential candidate
+ if (WSRP_V1_URN.equals(ns) || WSRP_V2_URN.equals(ns))
+ {
+ // but we need to check that the port namespaces to really know which
version of the service we've found
+ // this is needed for
http://www.netunitysoftware.com/wsrp2interop/WsrpProducer.asmx?Operation=...
+ // where the WSRP1 service name has the WSRP2 global target namespace so
we need more processing :(
+ Map<String, Port> ports = service.getPorts();
+ String bindingNSURI = null;
+ for (Port port : ports.values())
+ {
+ String newBindingNS = port.getBinding().getQName().getNamespaceURI();
+ if (bindingNSURI != null &&
!bindingNSURI.equals(newBindingNS))
+ {
+ throw new WSDLException(WSDLException.OTHER_ERROR,
"Inconsistend NS in port bindings. Aborting.");
+ }
+ bindingNSURI = newBindingNS;
+ }
+ if (WSRP_V1_BINDING.equals(bindingNSURI))
+ {
+ wsrp1 = checkPotentialServiceName(wsrp1, name, ns);
+ }
+ else if (WSRP_V2_BINDING.equals(bindingNSURI))
+ {
+ wsrp2 = checkPotentialServiceName(wsrp2, name, ns);
+ }
+ }
+ else
+ {
+ log.debug("Unknown service namespace: " + ns);
+ }
+ }
+
+ wsrp2ServiceQName = wsrp2;
+ wsrp1ServiceQName = wsrp1;
+
+ if (wsrp1 == null && wsrp2 == null)
+ {
+ throw new WSDLException(WSDLException.INVALID_WSDL,
+ "Found no service definition with WSRP specification
namespaces.");
+ }
+ }
+
+ public QName getWSRP2ServiceQName()
+ {
+ return wsrp2ServiceQName;
+ }
+
+ public QName getWSRP1ServiceQName()
+ {
+ return wsrp1ServiceQName;
+ }
+
+ private QName checkPotentialServiceName(QName potentiallyExisting, QName candidate,
String namespace) throws WSDLException
+ {
+ if (potentiallyExisting != null)
+ {
+ throw new WSDLException(WSDLException.OTHER_ERROR, "Found 2 different
services using the "
+ + namespace + " namespace. Cannot decide which one to use for service
so aborting.");
+ }
+ return candidate;
+ }
+ }
}
Added:
components/wsrp/trunk/consumer/src/test/java/org/gatein/wsrp/consumer/services/SOAPServiceFactoryTestCase.java
===================================================================
---
components/wsrp/trunk/consumer/src/test/java/org/gatein/wsrp/consumer/services/SOAPServiceFactoryTestCase.java
(rev 0)
+++
components/wsrp/trunk/consumer/src/test/java/org/gatein/wsrp/consumer/services/SOAPServiceFactoryTestCase.java 2010-08-12
14:20:29 UTC (rev 3812)
@@ -0,0 +1,96 @@
+/*
+ * JBoss, a division of Red Hat
+ * Copyright 2010, Red Hat Middleware, LLC, and individual
+ * contributors as indicated by the @authors tag. See the
+ * copyright.txt in the distribution for a full listing of
+ * individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.wsrp.consumer.services;
+
+import junit.framework.TestCase;
+import org.gatein.wsrp.services.SOAPServiceFactory;
+import org.oasis.wsrp.v1.WSRPV1MarkupPortType;
+import org.oasis.wsrp.v1.WSRPV1PortletManagementPortType;
+import org.oasis.wsrp.v1.WSRPV1RegistrationPortType;
+import org.oasis.wsrp.v1.WSRPV1ServiceDescriptionPortType;
+import org.oasis.wsrp.v2.WSRPV2MarkupPortType;
+import org.oasis.wsrp.v2.WSRPV2PortletManagementPortType;
+import org.oasis.wsrp.v2.WSRPV2RegistrationPortType;
+import org.oasis.wsrp.v2.WSRPV2ServiceDescriptionPortType;
+
+import javax.wsdl.WSDLException;
+
+/**
+ * @author <a href="mailto:chris.laprun@jboss.com">Chris
Laprun</a>
+ * @version $Revision$
+ */
+public class SOAPServiceFactoryTestCase extends TestCase
+{
+ private SOAPServiceFactory factory;
+ public static final Class[] WSRP2_PORT_TYPES = new Class[]{WSRPV2MarkupPortType.class,
WSRPV2ServiceDescriptionPortType.class, WSRPV2PortletManagementPortType.class,
WSRPV2RegistrationPortType.class};
+ public static final Class[] WSRP1_PORT_TYPES = new Class[]{WSRPV1MarkupPortType.class,
WSRPV1ServiceDescriptionPortType.class, WSRPV1PortletManagementPortType.class,
WSRPV1RegistrationPortType.class};
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ factory = new SOAPServiceFactory();
+ }
+
+ public void testSimpleV2Service() throws Exception
+ {
+
factory.setWsdlDefinitionURL("http://www.netunitysoftware.com/wsrp2i...;
+ checkPorts(WSRP2_PORT_TYPES);
+ }
+
+ public void testSimpleV1Service() throws Exception
+ {
+
factory.setWsdlDefinitionURL("http://www.netunitysoftware.com/wsrp2i...;
+ checkPorts(WSRP1_PORT_TYPES);
+ }
+
+ public void testBothServices() throws Exception
+ {
+
factory.setWsdlDefinitionURL("http://www.netunitysoftware.com/wsrp2i...;
+ checkPorts(WSRP2_PORT_TYPES);
+ }
+
+ public void testDefaultDotNetWSDLCompositeService() throws Exception
+ {
+
factory.setWsdlDefinitionURL("http://www.netunitysoftware.com/wsrp2i...;
+ try
+ {
+ checkPorts(WSRP2_PORT_TYPES);
+ fail();
+ }
+ catch (Exception e)
+ {
+ assertTrue(e instanceof WSDLException);
+ WSDLException wsdlEx = (WSDLException)e;
+ assertEquals(WSDLException.INVALID_WSDL, wsdlEx.getFaultCode());
+ }
+ }
+
+ private void checkPorts(Class[] ports) throws Exception
+ {
+ for (Class portClass : ports)
+ {
+ assertNotNull(factory.getService(portClass));
+ }
+ }
+}