You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by mi...@apache.org on 2008/10/01 02:39:57 UTC

svn commit: r700646 - in /ode/branches/APACHE_ODE_1.X: axis2-war/src/test/java/org/apache/ode/axis2/ axis2-war/src/test/resources/TestEndpointProperties/ axis2/src/main/java/org/apache/ode/axis2/httpbinding/

Author: midon
Date: Tue Sep 30 17:39:57 2008
New Revision: 700646

URL: http://svn.apache.org/viewvc?rev=700646&view=rev
Log:
Support Basic/Digest auth for external services

Added:
    ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/EndpointConfigurationTest.java
    ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/jetty-realm.properties
Removed:
    ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/EndpointPropertiesTest.java
Modified:
    ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/JettyWrapper.java
    ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/Echo.wsdl
    ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/test-endpoint-properties.bpel
    ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
    ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java

Added: ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/EndpointConfigurationTest.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/EndpointConfigurationTest.java?rev=700646&view=auto
==============================================================================
--- ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/EndpointConfigurationTest.java (added)
+++ ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/EndpointConfigurationTest.java Tue Sep 30 17:39:57 2008
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ode.axis2;
+
+import junit.framework.TestCase;
+import org.apache.ode.axis2.JettyWrapper;
+import org.mortbay.jetty.handler.ContextHandler;
+import org.mortbay.jetty.handler.HandlerList;
+import org.mortbay.jetty.security.Constraint;
+import org.mortbay.jetty.security.ConstraintMapping;
+import org.mortbay.jetty.security.SecurityHandler;
+import org.mortbay.jetty.security.HashUserRealm;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ *
+ *
+ */
+public class EndpointConfigurationTest extends Axis2TestBase {
+
+
+    public void testEndpointProperties() throws Exception {
+        executeProcess();
+    }
+
+    protected void executeProcess() throws Exception {
+        executeProcess(null);
+    }
+
+    protected void executeProcess(ContextHandler handler) throws Exception {
+        JettyWrapper jettyWrapper = new JettyWrapper(handler);
+        jettyWrapper.start();
+
+        try {
+            String bundleName = "TestEndpointProperties";
+            if (server.isDeployed(bundleName)) server.undeployProcess(bundleName);
+            server.deployProcess(bundleName);
+            try {
+                String response = server.sendRequestFile("http://localhost:8080/processes/helloWorld",
+                        bundleName, "testRequest.soap");
+                assertTrue(response.contains("helloResponse") && response.contains("OK!!!"));
+            } finally {
+                server.undeployProcess(bundleName);
+            }
+        } finally {
+            jettyWrapper.stop();
+        }
+    }
+
+    /**
+     * Redo the exact same test but with Basic Authentication activated on the external service
+     * @throws Exception
+     */
+    public void testHttpAuthentication() throws Exception {
+        ContextHandler securedEchoContext;
+        {
+            Constraint constraint = new Constraint();
+            constraint.setName(Constraint.__BASIC_AUTH);
+            constraint.setRoles(new String[]{"user"});
+            constraint.setAuthenticate(true);
+
+            ConstraintMapping cm = new ConstraintMapping();
+            cm.setConstraint(constraint);
+            cm.setPathSpec("/*");
+
+            SecurityHandler sh = new SecurityHandler();
+            sh.setUserRealm(new HashUserRealm("MyRealm", getClass().getResource("/TestEndpointProperties/jetty-realm.properties").toURI().toString()));
+            sh.setConstraintMappings(new ConstraintMapping[]{cm});
+
+            securedEchoContext = new ContextHandler();
+            securedEchoContext.setContextPath("/EchoService");
+
+            HandlerList hc = new HandlerList();
+            hc.addHandler(sh);
+            hc.addHandler(new JettyWrapper.EchoServiceHandler());
+            securedEchoContext.addHandler(hc);
+        }
+        executeProcess(securedEchoContext);
+    }
+
+
+}

Modified: ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/JettyWrapper.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/JettyWrapper.java?rev=700646&r1=700645&r2=700646&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/JettyWrapper.java (original)
+++ ode/branches/APACHE_ODE_1.X/axis2-war/src/test/java/org/apache/ode/axis2/JettyWrapper.java Tue Sep 30 17:39:57 2008
@@ -22,9 +22,14 @@
 import org.mortbay.jetty.handler.AbstractHandler;
 import org.mortbay.jetty.handler.ContextHandler;
 import org.mortbay.jetty.handler.ContextHandlerCollection;
+import org.mortbay.jetty.handler.HandlerList;
 import org.mortbay.jetty.Server;
 import org.mortbay.jetty.Handler;
 import org.mortbay.jetty.Request;
+import org.mortbay.jetty.security.ConstraintMapping;
+import org.mortbay.jetty.security.Constraint;
+import org.mortbay.jetty.security.SecurityHandler;
+import org.mortbay.jetty.security.HashUserRealm;
 import org.apache.ode.utils.DOMUtils;
 import org.apache.ode.utils.StreamUtils;
 import org.apache.commons.lang.StringUtils;
@@ -41,20 +46,14 @@
 import java.util.Enumeration;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
 
 /**
  * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
  */
 public class JettyWrapper {
 
-    static List REQUEST_HEADERS = new ArrayList();
-
-    static {
-        REQUEST_HEADERS.add("");
-    }
-
     protected Server server;
-    private ContextHandlerCollection handlerColl;
 
     public JettyWrapper() throws Exception {
         this(7070);
@@ -62,6 +61,18 @@
 
     public JettyWrapper(int port) throws Exception {
         server = new Server(port);
+        addDefaultHandlers();
+    }
+
+
+    public JettyWrapper(ContextHandler handler) {
+        server = new Server(7070);
+        if(handler!=null) server.addHandler(handler);
+        else addDefaultHandlers();
+    }
+
+
+    private void addDefaultHandlers() {
         ContextHandler arithmeticsContext = new ContextHandler();
         arithmeticsContext.setContextPath("/HttpBindingTest/ArithmeticsService");
         arithmeticsContext.setHandler(new ArithmeticsServiceHandler());
@@ -74,7 +85,7 @@
         echoContext.setContextPath("/EchoService");
         echoContext.setHandler(new EchoServiceHandler());
 
-        handlerColl = new ContextHandlerCollection();
+        ContextHandlerCollection handlerColl = new ContextHandlerCollection();
         Handler[] handlers = {arithmeticsContext, blogContext, echoContext};
         handlerColl.setHandlers(handlers);
 
@@ -82,20 +93,18 @@
     }
 
     public void start() throws Exception {
-        if (!server.isStarted())
-            server.start();
+        server.start();
     }
 
     public void stop() throws Exception {
         server.stop();
     }
 
-    private class EchoServiceHandler extends AbstractHandler {
-
+    static public class EchoServiceHandler extends AbstractHandler {
 
         public void handle(String s, HttpServletRequest request, HttpServletResponse response, int i) throws IOException, ServletException {
             String method = request.getMethod();
-            if (StringUtils.isNotEmpty(request.getParameter("ping"))) {
+            if (request.getParameter("ping")!=null) {
                 response.setStatus(200);
                 response.getOutputStream().println("Yep, I'm here!");
             } else {

Modified: ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/Echo.wsdl
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/Echo.wsdl?rev=700646&r1=700645&r2=700646&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/Echo.wsdl (original)
+++ ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/Echo.wsdl Tue Sep 30 17:39:57 2008
@@ -9,7 +9,19 @@
         xmlns:odex="http://www.apache.org/ode/type/extension/http"
         targetNamespace="http://ode/bpel/test/properties">
 
-
+    <wsdl:types>
+        <xsd:schema xmlns:ns="http://ode/bpel/test/properties" attributeFormDefault="qualified"
+                    elementFormDefault="unqualified" targetNamespace="http://ode/bpel/test/properties">
+
+            <xsd:element name="credentials">
+                <xsd:complexType>
+                    <xsd:attribute name="scheme" type="xsd:string" default="server-decide"/>
+                    <xsd:attribute name="username" type="xsd:string"/>
+                    <xsd:attribute name="password" type="xsd:string"/>
+                </xsd:complexType>
+            </xsd:element>
+        </xsd:schema>
+    </wsdl:types>
     <!--
     The goal of this test is to make sure endpoint properties are properly passed around.
     Endpoint properties might be set with property files matching *.endpoint.
@@ -33,6 +45,7 @@
         <wsdl:part name="header_BC" type="xsd:string"/>
         <wsdl:part name="header_AA" type="xsd:string"/>
         <wsdl:part name="header_BB" type="xsd:string"/>
+        <wsdl:part name="WWW-Authenticate" element="credentials"/>
     </wsdl:message>
 
 
@@ -49,9 +62,9 @@
             <odex:binding verb="GET"/>
             <wsdl:input>
                 <http:urlReplacement/>
-                <odex:header name="header_A"  part="header_A" />
-                <odex:header name="header_B"  part="header_B" />
-                <odex:header name="header_C"  part="header_C" />
+                <odex:header name="header_A" part="header_A"/>
+                <odex:header name="header_B" part="header_B"/>
+                <odex:header name="header_C" part="header_C"/>
                 <odex:header name="header_ABC" part="header_ABC"/>
                 <odex:header name="header_AB" part="header_AB"/>
                 <odex:header name="header_AC" part="header_AC"/>
@@ -60,9 +73,9 @@
                 <odex:header name="header_BB" part="header_BB"/>
             </wsdl:input>
             <wsdl:output>
-                <odex:header name="header_A"  part="header_A" />
-                <odex:header name="header_B"  part="header_B" />
-                <odex:header name="header_C"  part="header_C" />
+                <odex:header name="header_A" part="header_A"/>
+                <odex:header name="header_B" part="header_B"/>
+                <odex:header name="header_C" part="header_C"/>
                 <odex:header name="header_ABC" part="header_ABC"/>
                 <odex:header name="header_AB" part="header_AB"/>
                 <odex:header name="header_AC" part="header_AC"/>

Added: ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/jetty-realm.properties
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/jetty-realm.properties?rev=700646&view=auto
==============================================================================
--- ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/jetty-realm.properties (added)
+++ ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/jetty-realm.properties Tue Sep 30 17:39:57 2008
@@ -0,0 +1,3 @@
+
+#username=password, role, role, ...
+superuser=topsecret, user

Modified: ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/test-endpoint-properties.bpel
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/test-endpoint-properties.bpel?rev=700646&r1=700645&r2=700646&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/test-endpoint-properties.bpel (original)
+++ ode/branches/APACHE_ODE_1.X/axis2-war/src/test/resources/TestEndpointProperties/test-endpoint-properties.bpel Tue Sep 30 17:39:57 2008
@@ -68,6 +68,11 @@
 
         <!-- Assign all header parts -->
         <assign>
+
+            <copy>
+                <from><literal><credentials username="superuser" password="topsecret"/></literal></from>
+                <to>$reqMsg.WWW-Authenticate</to>
+            </copy>
             <!-- header_A will be set through a property file in the global config dir -->
             <!-- header_B will be set through a property file in the deployment unit dir -->
 

Modified: ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java?rev=700646&r1=700645&r2=700646&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java (original)
+++ ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java Tue Sep 30 17:39:57 2008
@@ -149,8 +149,10 @@
             // create a client
             HttpClient client = new HttpClient(connections);
 
+
             // configure the client (proxy, security, etc)
-            HttpHelper.configure(client, method.getURI(), params);
+            Element authenticatePart = DOMUtils.findChildByName(odeMex.getRequest().getMessage(), new QName(null, "WWW-Authenticate"));
+            HttpHelper.configure(client, method.getURI(), authenticatePart, params);
 
             // this callable encapsulates the http method execution and the process of the response
             final Callable executionCallable;

Modified: ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java?rev=700646&r1=700645&r2=700646&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java (original)
+++ ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java Tue Sep 30 17:39:57 2008
@@ -29,6 +29,8 @@
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
 import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
 import org.apache.commons.httpclient.methods.StringRequestEntity;
 import org.apache.commons.httpclient.params.HttpParams;
@@ -40,9 +42,11 @@
 import org.apache.ode.utils.DOMUtils;
 import org.apache.ode.utils.http.HttpUtils;
 import static org.apache.ode.utils.http.StatusCode.*;
+import org.apache.ode.bpel.iapi.Message;
 import org.w3c.dom.Element;
 import org.w3c.dom.Document;
 
+import javax.xml.namespace.QName;
 import java.io.IOException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -52,9 +56,9 @@
 
     private static final Log log = LogFactory.getLog(HttpHelper.class);
 
-    public static void configure(HttpClient client, URI targetURI, HttpParams params) throws URIException {
-        if (log.isDebugEnabled()) log.debug("Configuring http client...");
 
+    public static void configure(HttpClient client, URI targetURI, Element authPart, HttpParams params) throws URIException {
+        if (log.isDebugEnabled()) log.debug("Configuring http client...");
 
         /* Do not forget to wire params so that endpoint properties are passed around
            Down the road, when the request will be executed, the hierarchy of parameters will be the following:
@@ -68,7 +72,6 @@
         // Actually HttpClient *appends* default headers while we want them to be ignored if the process assign them 
         client.getParams().setParameter(HostParams.DEFAULT_HEADERS, Collections.EMPTY_LIST);
 
-
         // proxy configuration
         if (ProxyConf.isProxyEnabled(params, targetURI.getHost())) {
             if (log.isDebugEnabled()) log.debug("ProxyConf");
@@ -78,8 +81,39 @@
         // security
         // ...
 
-
-
+        // authentication
+        /*
+        We're expecting the following element:
+        <xs:complexType name="credentialType">
+            <xs:attribute name="scheme" type="xs:string" default="server-decide" />
+            <xs:attribute name="username" type="xs:string" />
+            <xs:attribute name="password" type="xs:string" />
+        </xs:complexType>
+        <xs:element type="rest_connector:credentialType" name="credentials" />
+         */
+        if (authPart != null) {
+            // the part must be defined with an element, so take the fist child
+            Element credentialsElement = DOMUtils.getFirstChildElement(authPart);
+            if (credentialsElement != null && credentialsElement.getAttributes().getLength() != 0) {
+                String scheme = DOMUtils.getAttribute(credentialsElement, "scheme");
+                String username = DOMUtils.getAttribute(credentialsElement, "username");
+                String password = DOMUtils.getAttribute(credentialsElement, "password");
+
+                if (scheme != null
+                        && !"server-decides".equalsIgnoreCase(scheme)
+                        && !"basic".equalsIgnoreCase(scheme)
+                        && !"digest".equalsIgnoreCase(scheme)) {
+                    throw new IllegalArgumentException("Unknown Authentication scheme: [" + scheme + "] Accepted values are: Basic, Digest, Server-Decides");
+                } else {
+                    if(log.isDebugEnabled()) log.debug("credentials provided");
+                    client.getState().setCredentials(
+                            new AuthScope(targetURI.getHost(), targetURI.getPort(), AuthScope.ANY_REALM, scheme),
+                            new UsernamePasswordCredentials(username, password));
+                    // save one round trip if basic
+                    client.getParams().setAuthenticationPreemptive("basic".equalsIgnoreCase(scheme));
+                }
+            }
+        }
     }
 
     /**
@@ -90,11 +124,15 @@
      * @throws HttpException
      * @see #statusLineToElement(org.w3c.dom.Document, org.apache.commons.httpclient.StatusLine)
      */
-    public static Element statusLineToElement(String statusLine) throws HttpException {
+    public static Element statusLineToElement
+            (String
+                    statusLine) throws HttpException {
         return statusLineToElement(new StatusLine(statusLine));
     }
 
-    public static Element statusLineToElement(StatusLine statusLine) {
+    public static Element statusLineToElement
+            (StatusLine
+                    statusLine) {
         return statusLineToElement(DOMUtils.newDocument(), statusLine);
     }
 
@@ -111,7 +149,10 @@
      * @param doc        - the document to use to create new nodes
      * @return an Element
      */
-    public static Element statusLineToElement(Document doc, StatusLine statusLine) {
+    public static Element statusLineToElement
+            (Document
+                    doc, StatusLine
+                    statusLine) {
         Element statusLineEl = doc.createElementNS(null, "Status-Line");
         Element versionEl = doc.createElementNS(null, "HTTP-Version");
         Element codeEl = doc.createElementNS(null, "Status-Code");
@@ -142,7 +183,9 @@
      * @return
      * @throws IOException
      */
-    public static Element prepareDetailsElement(HttpMethod method) {
+    public static Element prepareDetailsElement
+            (HttpMethod
+                    method) {
         Header h = method.getResponseHeader("Content-Type");
         String receivedType = h != null ? h.getValue() : null;
         boolean bodyIsXml = receivedType != null && HttpUtils.isXml(receivedType);
@@ -209,7 +252,9 @@
      * @param header
      * @return the string properly ready to be used as an HTTP header field-content
      */
-    public static String replaceCRLFwithLWS(String header) {
+    public static String replaceCRLFwithLWS
+            (String
+                    header) {
         Matcher m = NON_LWS_PATTERN.matcher(header);
         StringBuffer sb = new StringBuffer(header.length());
         while (m.find()) {
@@ -220,7 +265,9 @@
         return sb.toString();
     }
 
-    public static String requestToString(HttpMethod m) {
+    public static String requestToString
+            (HttpMethod
+                    m) {
         StringBuilder sb = new StringBuilder(256);
         try {
             sb.append("HTTP Request Details: \n").append(m.getName()).append(" ").append(m.getURI());
@@ -251,7 +298,9 @@
         return sb.toString();
     }
 
-    public static String responseToString(HttpMethod m) {
+    public static String responseToString
+            (HttpMethod
+                    m) {
         StringBuilder sb = new StringBuilder(256);
         try {
             sb.append("HTTP Response Details: \n").append(m.getName()).append(" ").append(m.getURI());
@@ -283,11 +332,12 @@
     }
 
     /**
-     *
      * @param s, the status code to test, must be in [400, 600[
      * @return 1 if fault, -1 if failure, 0 if undetermined
      */
-    public static int isFaultOrFailure(int s) {
+    public static int isFaultOrFailure
+            (
+                    int s) {
         if (s < 400 || s >= 600) {
             throw new IllegalArgumentException("Status-Code must be in interval [400;600[");
         }