merged from HEAD

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/branches/common/common-gcore-stubs/1.0@77433 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
fabio.simeoni 2013-07-01 13:50:17 +00:00
parent bf45dfc898
commit 719f80c0dd
17 changed files with 420 additions and 132 deletions

View File

@ -1,5 +1,9 @@
<ReleaseNotes>
<Changeset component="${build.finalName}" date="2013-01-11">
<Changeset component="common-gcore-stubs-1.0.0" date="2013-01-11">
<Change>First Release</Change>
</Changeset>
<Changeset component="${build.finalName}" date="2013-07-01">
<Change>Modular handler discovery and delegation</Change>
<Change>Fix: WSDL cache now releases the lock it acquires when clearing</Change>
</Changeset>
</ReleaseNotes>

View File

@ -8,7 +8,7 @@
</parent>
<groupId>org.gcube.core</groupId>
<artifactId>common-gcore-stubs</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
<name>GCore Stubs</name>
<description>JAXWS Stub Support for gCore Service</description>
@ -59,7 +59,7 @@
<dependency>
<groupId>org.gcube.tools</groupId>
<artifactId>my-container</artifactId>
<version>1.0.0</version>
<version>2.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
@ -67,7 +67,7 @@
<dependency>
<groupId>org.gcube.tools</groupId>
<artifactId>my-container</artifactId>
<version>1.0.0</version>
<version>2.0.0-SNAPSHOT</version>
<type>tar.gz</type>
<classifier>distro</classifier>
<scope>test</scope>

View File

@ -1,127 +0,0 @@
package org.gcube.common.clients.stubs.jaxws;
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.scope.api.ScopeProvider;
/**
* A {@link SOAPHandler} that adds gCube headers to outgoing calls.
*
* @author Fabio Simeoni
*
*/
public class GCoreJAXWSHandler implements SOAPHandler<SOAPMessageContext> {
/** Namespace of scope-related headers */
public static final String SCOPE_NS = "http://gcube-system.org/namespaces/scope";
/** Name of the scope call header. */
public static final String SCOPE_HEADER_NAME = "scope";
public static final QName SCOPE_QNAME = new QName(SCOPE_NS,SCOPE_HEADER_NAME);
/** Name of the service class call header. */
public static final String SERVICECLASS_HEADER_NAME = "serviceClass";
public static final QName SERVICECLASS_QNAME = new QName(SCOPE_NS,SERVICECLASS_HEADER_NAME);
/** Name of the service name call header. */
public static final String SERVICENAME_HEADER_NAME = "serviceName";
public static final QName SERVICENAME_QNAME = new QName(SCOPE_NS,SERVICENAME_HEADER_NAME);
/** Name of the scope call header. */
public static final String CALLER_HEADER_NAME = "caller";
/** Namespace of scope-related headers */
public static final String CALLER_NS = "http://gcube-system.org/namespaces/caller";
public static final QName CALLER_QNAME = new QName(CALLER_NS,CALLER_HEADER_NAME);
private final GCoreService<?> target;
GCoreJAXWSHandler(GCoreService<?> target) {
this.target=target;
}
public boolean handleMessage(SOAPMessageContext context) {
Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound)
try {
SOAPHeader header = context.getMessage().getSOAPPart().getEnvelope().getHeader();
if (header == null)
header = context.getMessage().getSOAPPart().getEnvelope().addHeader();
addCurrentScope(header);
addTargetServiceCoordinates(header);
addClientIdentity(header);
correctWSAddressingHeader(header);
} catch (Exception e) {
throw new RuntimeException("cannot configure outgoing message", e);
}
return true;
};
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext context) {
return true;
}
public void close(MessageContext context) {}
//helper
private void addClientIdentity(SOAPHeader header) throws Exception {
addHeader(header,CALLER_QNAME, target.clientId());
}
//helper
private void addTargetServiceCoordinates(SOAPHeader header) throws Exception {
addHeader(header,SERVICECLASS_QNAME, target.gcubeClass());
addHeader(header,SERVICENAME_QNAME, target.gcubeName());
}
//helper
private void addCurrentScope(SOAPHeader header) throws Exception {
String scope = ScopeProvider.instance.get();
if (scope==null)
throw new IllegalStateException("no scope is defined for this call");
addHeader(header,SCOPE_QNAME, scope);
}
//helper: adapts ws-addressing headers to member submission's. brutal but there is no support for member submission in
//jdk 1.6
private void correctWSAddressingHeader(SOAPHeader header) throws Exception {
Iterator<?> it = header.examineAllHeaderElements();
while (it.hasNext()) {
SOAPHeaderElement e = (SOAPHeaderElement) it.next();
if (e.getElementQName().getNamespaceURI().equals("http://www.w3.org/2005/08/addressing")) {
e.detachNode();
addHeader(header,new QName("http://schemas.xmlsoap.org/ws/2004/03/addressing",e.getElementQName().getLocalPart()), e.getTextContent());
}
}
}
// helper
private void addHeader(SOAPHeader header,QName name, String value) throws Exception {
header.addHeaderElement(name).addTextNode(value);
}
}

View File

@ -35,8 +35,9 @@ class StubCache {
//obtain a lock for current key
Lock nameLock = lockFor(name);
nameLock.lock();
try {
cache.remove(name);
}
finally {

View File

@ -18,6 +18,7 @@ import javax.xml.ws.soap.AddressingFeature;
import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;
import org.gcube.common.clients.stubs.jaxws.StubFactoryDSL.AtClause;
import org.gcube.common.clients.stubs.jaxws.handlers.GCoreJAXWSHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -0,0 +1,36 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
/**
* Adapter implementation of {@link CallHandler} for selective implementations (handle only outgoing calls, or only responses).
*
* @author Fabio Simeoni
*
*/
public class AbstractHandler implements CallHandler {
@Override
public void handleRequest(GCoreService<?> target, SOAPHeader header, SOAPMessageContext context) throws Exception {
}
@Override
public void handleResponse(GCoreService<?> target, SOAPMessageContext context) throws Exception {
}
/**
* Helper to set an element on the SOAP header of the outgoing call
* @param header the SOAP header
* @param name the name the element's name
* @param value the element's value
* @throws SOAPException if the element cannot be added to the header
*/
protected final void addHeader(SOAPHeader header,QName name, String value) throws SOAPException {
header.addHeaderElement(name).addTextNode(value);
}
}

View File

@ -0,0 +1,32 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
/**
* Handles outgoing calls and their responses.
*
* @author Fabio Simeoni
*
*/
public interface CallHandler {
/**
* Handles an outgoing call.
* @param target information about the target service
* @param header the SOAP header of the call
* @param context the JAX-WS call context
* @throws Exception if the call cannot be handled
*/
void handleRequest(GCoreService<?> target,SOAPHeader header,SOAPMessageContext context) throws Exception;
/**
* Handles the response to a call.
* @param target information about the target service
* @param context the JAX-WS call context
* @throws Exception if the response cannot be handled
*/
void handleResponse(GCoreService<?> target,SOAPMessageContext context) throws Exception;
}

View File

@ -0,0 +1,29 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
/**
* A {@link CallHandler} that sets client identification on outgoing calls.
*
* @author Fabio Simeoni
*
*/
public class ClientInfoHandler extends AbstractHandler {
/** Name of the scope call header. */
public static final String CALLER_HEADER_NAME = "caller";
/** Namespace of scope-related headers */
public static final String CALLER_NS = "http://gcube-system.org/namespaces/caller";
public static final QName CALLER_QNAME = new QName(CALLER_NS,CALLER_HEADER_NAME);
@Override
public void handleRequest(GCoreService<?> target, SOAPHeader header, SOAPMessageContext context) throws Exception {
addHeader(header,CALLER_QNAME, target.clientId());
}
}

View File

@ -0,0 +1,69 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
/**
* A {@link SOAPHandler} that adds gCube headers to outgoing calls.
*
* @author Fabio Simeoni
*
*/
public class GCoreJAXWSHandler implements SOAPHandler<SOAPMessageContext> {
private final GCoreService<?> target;
public GCoreJAXWSHandler(GCoreService<?> target) {
this.target = target;
}
public boolean handleMessage(SOAPMessageContext context) {
Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound)
try {
SOAPHeader header = context.getMessage().getSOAPPart().getEnvelope().getHeader();
if (header == null)
header = context.getMessage().getSOAPPart().getEnvelope().addHeader();
for (CallHandler handler : HandlerRegistry.handlers())
handler.handleRequest(target, header, context);
} catch (Exception e) {
throw new RuntimeException("cannot configure outgoing message", e);
}
else
try {
for (CallHandler handler : HandlerRegistry.handlers())
handler.handleResponse(target, context);
} catch (Exception e) {
throw new RuntimeException("cannot configure outgoing message", e);
}
return true;
};
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext context) {
return true;
}
public void close(MessageContext context) {
}
}

View File

@ -0,0 +1,45 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Discovers available {@link CallHandler}s.
*
* @author Fabio Simeoni
*
*/
public class HandlerRegistry {
private final static Logger log = LoggerFactory.getLogger(HandlerRegistry.class);
private final static List<CallHandler> handlers = new ArrayList<CallHandler>();
static {
ServiceLoader<CallHandler> loader = ServiceLoader.load(CallHandler.class);
Iterator<CallHandler> it = loader.iterator();
while (it.hasNext())
try {
CallHandler handler = it.next();
log.info("loaded call handler {}",handler);
handlers.add(handler);
}
catch(Error e) {
log.error("could not load call handler",e);
}
}
/**
* Returns the discovered {@link CallHandler}s.
* @return the handlers
*/
public static List<CallHandler> handlers() {
return handlers;
}
}

View File

@ -0,0 +1,33 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
/**
* A {@link CallHandler} that transforms WS-Addressing information in outgoing calls into MemberSubmission form.
* @author Fabio Simeoni
*
*/
public class LegacyWSAddressingHandler extends AbstractHandler {
//helper: adapts ws-addressing headers to member submission's. brutal but there is no support for member submission in
//jdk 1.6
@Override
public void handleRequest(GCoreService<?> target, SOAPHeader header, SOAPMessageContext context) throws Exception {
Iterator<?> it = header.examineAllHeaderElements();
while (it.hasNext()) {
SOAPHeaderElement e = (SOAPHeaderElement) it.next();
if (e.getElementQName().getNamespaceURI().equals("http://www.w3.org/2005/08/addressing")) {
e.detachNode();
addHeader(header,new QName("http://schemas.xmlsoap.org/ws/2004/03/addressing",e.getElementQName().getLocalPart()), e.getTextContent());
}
}
}
}

View File

@ -0,0 +1,31 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
import org.gcube.common.scope.api.ScopeProvider;
/**
* A {@link CallHandler} that sets the current scope on outgoing calls.
* @author Fabio Simeoni
*
*/
public class ScopeHandler extends AbstractHandler {
/** Namespace of scope-related headers */
public static final String SCOPE_NS = "http://gcube-system.org/namespaces/scope";
/** Name of the scope call header. */
public static final String SCOPE_HEADER_NAME = "scope";
public static final QName SCOPE_QNAME = new QName(SCOPE_NS,SCOPE_HEADER_NAME);
@Override
public void handleRequest(GCoreService<?> target, SOAPHeader header, SOAPMessageContext context) throws Exception {
String scope = ScopeProvider.instance.get();
if (scope==null)
throw new IllegalStateException("no scope is defined for this call");
addHeader(header,SCOPE_QNAME, scope);
}
}

View File

@ -0,0 +1,33 @@
package org.gcube.common.clients.stubs.jaxws.handlers;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
/**
* A {@link CallHandler} that sets the coordinates of the target service on outgoing calls.
*
* @author Fabio Simeoni
*
*/
public class TargetServiceHandler extends AbstractHandler {
/** Namespace of scope-related headers */
private static final String SCOPE_NS = "http://gcube-system.org/namespaces/scope";
/** Name of the service class call header. */
private static final String SERVICECLASS_HEADER_NAME = "serviceClass";
private static final QName SERVICECLASS_QNAME = new QName(SCOPE_NS,SERVICECLASS_HEADER_NAME);
/** Name of the service name call header. */
private static final String SERVICENAME_HEADER_NAME = "serviceName";
private static final QName SERVICENAME_QNAME = new QName(SCOPE_NS,SERVICENAME_HEADER_NAME);
@Override
public void handleRequest(GCoreService<?> target, SOAPHeader header, SOAPMessageContext context) throws Exception {
addHeader(header,SERVICECLASS_QNAME, target.gcubeClass());
addHeader(header,SERVICENAME_QNAME, target.gcubeName());
}
}

View File

@ -0,0 +1,4 @@
org.gcube.common.clients.stubs.jaxws.handlers.ScopeHandler
org.gcube.common.clients.stubs.jaxws.handlers.TargetServiceHandler
org.gcube.common.clients.stubs.jaxws.handlers.ClientInfoHandler
org.gcube.common.clients.stubs.jaxws.handlers.LegacyWSAddressingHandler

View File

@ -0,0 +1,55 @@
package org.acme;
import static org.acme.jaxws.stubs.StatelessStub.*;
import static org.gcube.common.clients.stubs.jaxws.StubFactory.*;
import static org.junit.Assert.*;
import java.net.URI;
import org.acme.jaxws.stubs.StatelessStub;
import org.gcube.common.clients.stubs.jaxws.handlers.HandlerRegistry;
import org.gcube.common.mycontainer.Deployment;
import org.gcube.common.mycontainer.Gar;
import org.gcube.common.mycontainer.MyContainerTestRunner;
import org.gcube.common.scope.api.ScopeProvider;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(MyContainerTestRunner.class)
public class ConfigTest {
@Deployment
static Gar testservice = new Gar("test-service").addConfigurations("src/test/resources/test-service/etc").addInterfaces("src/test/resources/test-service/wsdl");
static StatelessStub stub;
@BeforeClass
public static void setup() {
ScopeProvider.instance.set("/gcube/devsec");
stub = stubFor(stateless).at(URI.create("http://localhost:9999/wsrf/services/acme/service/stateless"));
}
@Test
public void handlerTest() {
TestHandler handler = new TestHandler();
assertTrue(HandlerRegistry.handlers().contains(handler));
String input = "input";
String output = stub.foo(input);
assertEquals(input, output);
handler.called=true;
assertTrue(HandlerRegistry.handlers().contains(handler));
}
}

View File

@ -0,0 +1,41 @@
package org.acme;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.gcube.common.clients.stubs.jaxws.GCoreService;
import org.gcube.common.clients.stubs.jaxws.handlers.AbstractHandler;
public class TestHandler extends AbstractHandler {
public boolean called=false;
@Override
public void handleRequest(GCoreService<?> target, SOAPHeader header, SOAPMessageContext context) throws Exception {
called=true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (called ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TestHandler other = (TestHandler) obj;
if (called != other.called)
return false;
return true;
}
}