You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by ro...@apache.org on 2010/07/22 20:56:55 UTC

svn commit: r966803 - in /incubator/wink/trunk: wink-client-apache-httpclient/src/main/java/org/apache/wink/client/internal/handlers/ wink-client/src/main/java/org/apache/wink/client/ wink-client/src/main/java/org/apache/wink/client/handlers/ wink-clie...

Author: rott
Date: Thu Jul 22 18:56:55 2010
New Revision: 966803

URL: http://svn.apache.org/viewvc?rev=966803&view=rev
Log:
WINK-305: improve SSL configuration options to allow properties file config

Modified:
    incubator/wink/trunk/wink-client-apache-httpclient/src/main/java/org/apache/wink/client/internal/handlers/ApacheHttpClientConnectionHandler.java
    incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/ClientConfig.java
    incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/handlers/BasicAuthSecurityHandler.java
    incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/internal/handlers/HttpURLConnectionHandler.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/AbstractMetadataCollector.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollector.java
    incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollectorTest.java
    incubator/wink/trunk/wink-server/pom.xml
    incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/DeploymentConfiguration.java
    incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestFilter.java

Modified: incubator/wink/trunk/wink-client-apache-httpclient/src/main/java/org/apache/wink/client/internal/handlers/ApacheHttpClientConnectionHandler.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client-apache-httpclient/src/main/java/org/apache/wink/client/internal/handlers/ApacheHttpClientConnectionHandler.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-client-apache-httpclient/src/main/java/org/apache/wink/client/internal/handlers/ApacheHttpClientConnectionHandler.java (original)
+++ incubator/wink/trunk/wink-client-apache-httpclient/src/main/java/org/apache/wink/client/internal/handlers/ApacheHttpClientConnectionHandler.java Thu Jul 22 18:56:55 2010
@@ -24,8 +24,15 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
 import java.util.List;
 
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.http.Header;
@@ -38,6 +45,9 @@ import org.apache.http.client.methods.Ht
 import org.apache.http.client.methods.HttpRequestBase;
 import org.apache.http.client.params.ClientPNames;
 import org.apache.http.conn.params.ConnRoutePNames;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.params.BasicHttpParams;
 import org.apache.http.params.CoreConnectionPNames;
@@ -74,7 +84,7 @@ public class ApacheHttpClientConnectionH
     }
 
     private HttpResponse processRequest(ClientRequest request, HandlerContext context)
-        throws IOException {
+        throws IOException, KeyManagementException, NoSuchAlgorithmException {
         HttpClient client = openConnection(request);
         // TODO: move this functionality to the base class
         NonCloseableOutputStream ncos = new NonCloseableOutputStream();
@@ -123,7 +133,7 @@ public class ApacheHttpClientConnectionH
         return httpRequest;
     }
 
-    private HttpClient openConnection(ClientRequest request) {
+    private HttpClient openConnection(ClientRequest request) throws NoSuchAlgorithmException, KeyManagementException {
         if (this.httpclient != null) {
             return this.httpclient;
         }
@@ -145,7 +155,33 @@ public class ApacheHttpClientConnectionH
             params.setParameter(ConnRoutePNames.DEFAULT_PROXY, new HttpHost(config.getProxyHost(),
                                                                             config.getProxyPort()));
         }
+
         HttpClient httpclient = new DefaultHttpClient(params);
+
+        if (config.getBypassHostnameVerification()) {
+            SSLContext sslcontext = SSLContext.getInstance("TLS");
+            sslcontext.init(null, null, null);
+
+            SSLSocketFactory sf = new SSLSocketFactory(sslcontext);
+            sf.setHostnameVerifier(new X509HostnameVerifier() {
+
+                public boolean verify(String hostname, SSLSession session) {
+                    return true;
+                }
+
+                public void verify(String host, String[] cns, String[] subjectAlts)
+                    throws SSLException {
+                }
+
+                public void verify(String host, X509Certificate cert) throws SSLException {
+                }
+
+                public void verify(String host, SSLSocket ssl) throws IOException {
+                }
+            });
+            httpclient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", sf,
+                                                                                      443));
+        }
         return httpclient;
     }
 

Modified: incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/ClientConfig.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/ClientConfig.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/ClientConfig.java (original)
+++ incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/ClientConfig.java Thu Jul 22 18:56:55 2010
@@ -61,6 +61,7 @@ public class ClientConfig implements Clo
     private boolean                   modifiable;
     private boolean                   isAcceptHeaderAutoSet;
     private boolean                   loadWinkApplications               = true;
+    private boolean                   bypassHostnameVerification         = false;
 
     private static final String       WINK_CLIENT_CONNECTTIMEOUT         =
                                                                              "wink.client.connectTimeout"; //$NON-NLS-1$
@@ -483,4 +484,24 @@ public class ClientConfig implements Clo
         this.properties = properties;
     }
 
+    /**
+     * Get whether or not hostname verification will be bypassed for SSL
+     * certificates.
+     * 
+     * @return Whether or not hostname verification will be bypassed for SSL
+     *         certificates
+     */
+    public boolean getBypassHostnameVerification() {
+        return bypassHostnameVerification;
+    }
+
+    /**
+     * Set whether or not hostname verification to bypass hostname verification
+     * for SSL certificates. Default value is false.
+     * 
+     * @param bypassHostnameVerification true to bypass hostname verification
+     */
+    public void setBypassHostnameVerification(boolean bypassHostnameVerification) {
+        this.bypassHostnameVerification = bypassHostnameVerification;
+    }
 }

Modified: incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/handlers/BasicAuthSecurityHandler.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/handlers/BasicAuthSecurityHandler.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/handlers/BasicAuthSecurityHandler.java (original)
+++ incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/handlers/BasicAuthSecurityHandler.java Thu Jul 22 18:56:55 2010
@@ -19,9 +19,11 @@
  */
 package org.apache.wink.client.handlers;
 
-import javax.ws.rs.core.HttpHeaders;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
 
-import org.apache.commons.codec.binary.Base64;
 import org.apache.wink.client.ClientAuthenticationException;
 import org.apache.wink.client.ClientRequest;
 import org.apache.wink.client.ClientResponse;
@@ -35,24 +37,24 @@ import org.slf4j.LoggerFactory;
  * <code>
  * Usage:<br/>
  * ClientConfig config = new ClientConfig();<br/>
- * BasicAuthSecurityHandler basicAuth = new BasicAuthSecurityHandler();<br/>
- * basicAuth.setUserName("user1");<br/>
- * basicAuth.setPassword("password2");<br/>
- * config.handlers(basicAuth);<br/>
+ * config.handlers(new BasicAuthSecurityHandler());<br/>
  * // create the rest client instance<br/>
  * RestClient client = new RestClient(config);<br/>
  * // create the resource instance to interact with Resource<br/>
- * resource = client.resource("https://localhost:8080/path/to/resource");<br/>
+ * resource = client.resource("http://localhost:8080/path/to/resource");<br/>
  * </code>
  */
 public class BasicAuthSecurityHandler implements ClientHandler {
 
-    private static Logger   logger          =
-                                                LoggerFactory
-                                                    .getLogger(BasicAuthSecurityHandler.class);
-
-    private volatile String handlerUsername = null;
-    private volatile String handlerPassword = null;
+    private static Logger    logger          =
+                                                 LoggerFactory
+                                                     .getLogger(BasicAuthSecurityHandler.class);
+
+    final static String      PROPS_FILE_NAME = "wink.client.props";                             //$NON-NLS-1$
+    private Properties       clientProps     = null;
+    private volatile boolean propsLoaded     = false;
+    private volatile String  handlerUsername = null;
+    private volatile String  handlerPassword = null;
 
     /**
      * Sets the username to use.
@@ -92,11 +94,32 @@ public class BasicAuthSecurityHandler im
             logger.trace("Status code was not 401 so no need to re-issue request."); //$NON-NLS-1$
             return response;
         } else {
-            String userid = handlerUsername;
-            String password = handlerPassword;
+            // read user id and password from a property
+            // as a start we use java a command line property
+            String userid = System.getProperty("user"); //$NON-NLS-1$
+            String password = System.getProperty("password"); //$NON-NLS-1$
             if (logger.isTraceEnabled()) {
-                logger.trace("The 'username' property was set to: {}", userid); //$NON-NLS-1$
-                logger.trace("Was the 'password' property set: {}", password != null); //$NON-NLS-1$
+                logger.trace("The 'user' system property was set to: {}", userid); //$NON-NLS-1$
+                logger.trace("The 'password' system property was set: {}", password != null); //$NON-NLS-1$
+            }
+
+            if (userid == null || userid.equals("") || password == null || password.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
+                // see if we can load credentials from a properties file
+                String propsFileDir = System.getProperty("wink.client.props.dir"); //$NON-NLS-1$
+                logger
+                    .trace("Could NOT get userid and password from system properties so attempting to look at properties file in {}", propsFileDir); //$NON-NLS-1$
+                if (propsFileDir != null && !propsFileDir.equals("")) { //$NON-NLS-1$
+                    if (!propsLoaded) {
+                        clientProps = loadProps(propsFileDir + File.separator + PROPS_FILE_NAME);
+                    }
+                    userid = clientProps.getProperty("user"); //$NON-NLS-1$
+                    password = clientProps.getProperty("password"); //$NON-NLS-1$
+                } else {
+                    logger
+                        .trace("Could NOT find properties file so checking variables assigned to handler itself", propsFileDir); //$NON-NLS-1$
+                    userid = handlerUsername;
+                    password = handlerPassword;
+                }
             }
 
             if (!(userid == null || userid.equals("") || password == null || password.equals(""))) { //$NON-NLS-1$ //$NON-NLS-2$
@@ -104,10 +127,11 @@ public class BasicAuthSecurityHandler im
                 // we have a user credential
                 String credential = userid + ":" + password; //$NON-NLS-1$
                 byte[] credBytes = credential.getBytes();
-                byte[] encodedCredBytes = Base64.encodeBase64(credBytes, false);
+                byte[] encodedCredBytes =
+                    org.apache.commons.codec.binary.Base64.encodeBase64(credBytes, false);
                 // id and password needs to be base64 encoded
                 String credEncodedString = "Basic " + new String(encodedCredBytes); //$NON-NLS-1$
-                request.getHeaders().putSingle(HttpHeaders.AUTHORIZATION, credEncodedString);
+                request.getHeaders().putSingle("Authorization", credEncodedString); //$NON-NLS-1$
                 logger.trace("Issuing request again with Authorization header"); //$NON-NLS-1$
                 response = context.doChain(request);
                 if (response.getStatusCode() == 401) {
@@ -129,5 +153,35 @@ public class BasicAuthSecurityHandler im
         } // end if block
     } // end handle
 
+    /**
+     * Loads a properties file that contains user basic authentication
+     * credential.
+     * 
+     * @param propsFileName
+     * @return a Properties object
+     */
+    private synchronized Properties loadProps(String propsFileName) {
+        Properties props = null;
+        FileInputStream fis = null;
+        try {
+            File propsFile = new File(propsFileName);
+            props = new Properties();
+            fis = new FileInputStream(propsFile);
+            props.load(fis);
+            propsLoaded = true;
+        } catch (IOException e) {
+            props = null;
+        } finally {
+            try {
+                if (fis != null) {
+                    fis.close();
+                }
+            } catch (IOException e) {
+                /* do nothing */
+            }
+        }
+        return props;
+    } // end loadProps
+
 } // end class SecurityHandler
 

Modified: incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/internal/handlers/HttpURLConnectionHandler.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/internal/handlers/HttpURLConnectionHandler.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/internal/handlers/HttpURLConnectionHandler.java (original)
+++ incubator/wink/trunk/wink-client/src/main/java/org/apache/wink/client/internal/handlers/HttpURLConnectionHandler.java Thu Jul 22 18:56:55 2010
@@ -29,6 +29,9 @@ import java.net.Proxy;
 import java.net.URL;
 import java.util.List;
 
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
@@ -39,9 +42,13 @@ import org.apache.wink.client.ClientResp
 import org.apache.wink.client.handlers.HandlerContext;
 import org.apache.wink.client.internal.ClientUtils;
 import org.apache.wink.common.internal.WinkConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class HttpURLConnectionHandler extends AbstractConnectionHandler {
 
+    private static final Logger logger = LoggerFactory.getLogger(HttpURLConnectionHandler.class);
+
     public ClientResponse handle(ClientRequest request, HandlerContext context) throws Exception {
         try {
             HttpURLConnection connection = processRequest(request, context);
@@ -58,7 +65,28 @@ public class HttpURLConnectionHandler ex
         NonCloseableOutputStream ncos = new NonCloseableOutputStream();
         OutputStream os = ncos;
         processRequestHeaders(request, connection);
-        connection.connect();
+        HostnameVerifier hv = null;
+        boolean bypassHostnameVerification =
+            ((ClientConfig)request.getAttribute(WinkConfiguration.class))
+                .getBypassHostnameVerification() && (connection instanceof HttpsURLConnection);
+        if (bypassHostnameVerification) {
+            HttpsURLConnection https = ((HttpsURLConnection)connection);
+            hv = https.getHostnameVerifier();
+            https.setHostnameVerifier(new HostnameVerifier() {
+                public boolean verify(String urlHostName, SSLSession session) {
+                    logger.trace("Bypassing hostname verification: URL host is " + urlHostName
+                        + ", SSLSession host is "
+                        + session.getPeerHost());
+                    return true;
+                }
+            });
+        }
+        try {
+            connection.connect();
+        } finally {
+            if (bypassHostnameVerification)
+                ((HttpsURLConnection)connection).setHostnameVerifier(hv);
+        }
         if (request.getEntity() != null) {
             ncos.setOutputStream(connection.getOutputStream());
             os = adaptOutputStream(ncos, request, context.getOutputStreamAdapters());

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/AbstractMetadataCollector.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/AbstractMetadataCollector.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/AbstractMetadataCollector.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/AbstractMetadataCollector.java Thu Jul 22 18:56:55 2010
@@ -59,7 +59,7 @@ public abstract class AbstractMetadataCo
         List<Injectable> injectableFields = metadata.getInjectableFields();
 
         // add fields
-        while (resourceClass != Object.class) {
+        while (resourceClass != Object.class && resourceClass != null) {
             for (Field field : resourceClass.getDeclaredFields()) {
                 Type fieldType = field.getGenericType();
                 Injectable injectable = parseAccessibleObject(field, fieldType);

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollector.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollector.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollector.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollector.java Thu Jul 22 18:56:55 2010
@@ -53,6 +53,10 @@ public class ProviderMetadataCollector e
             return false;
         }
 
+        if (cls.getAnnotation(Provider.class) != null) {
+            return true;
+        }
+        
         if (Modifier.isInterface(cls.getModifiers()) || Modifier.isAbstract(cls.getModifiers())) {
             if (logger.isWarnEnabled()) {
                 logger.warn(Messages.getMessage("providerIsInterfaceOrAbstract", cls)); //$NON-NLS-1$
@@ -60,10 +64,6 @@ public class ProviderMetadataCollector e
             return false;
         }
 
-        if (cls.getAnnotation(Provider.class) != null) {
-            return true;
-        }
-
         Class<?> declaringClass = cls;
 
         while (declaringClass != null && !declaringClass.equals(Object.class)) {

Modified: incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollectorTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollectorTest.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollectorTest.java (original)
+++ incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/registry/metadata/ProviderMetadataCollectorTest.java Thu Jul 22 18:56:55 2010
@@ -74,9 +74,9 @@ public class ProviderMetadataCollectorTe
     public void testIsProvider() {
         assertFalse(ProviderMetadataCollector.isProvider(Interface.class));
         assertFalse(ProviderMetadataCollector.isProvider(Class.class));
-        assertFalse(ProviderMetadataCollector.isProvider(ProviderInterface.class));
+        assertTrue(ProviderMetadataCollector.isProvider(ProviderInterface.class));
         assertTrue(ProviderMetadataCollector.isProvider(ProviderInterfaceImpl.class));
-        assertFalse(ProviderMetadataCollector.isProvider(AbstractProvider.class));
+        assertTrue(ProviderMetadataCollector.isProvider(AbstractProvider.class));
         assertTrue(ProviderMetadataCollector.isProvider(ProviderBaseClass.class));
         assertTrue(ProviderMetadataCollector.isProvider(ProviderStandalone.class));
     }

Modified: incubator/wink/trunk/wink-server/pom.xml
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/pom.xml?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/pom.xml (original)
+++ incubator/wink/trunk/wink-server/pom.xml Thu Jul 22 18:56:55 2010
@@ -106,6 +106,12 @@
             <version>2.5.1</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.jmock</groupId>
+            <artifactId>jmock-legacy</artifactId>
+            <version>2.5.1</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/DeploymentConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/DeploymentConfiguration.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/DeploymentConfiguration.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/DeploymentConfiguration.java Thu Jul 22 18:56:55 2010
@@ -97,9 +97,9 @@ public class DeploymentConfiguration imp
     private static final String       VALIDATE_LOCATION_HEADER            =
                                                                               "wink.validateLocationHeader";                 //$NON-NLS-1$
     private static final String       DEFAULT_RESPONSE_CHARSET            =
-                                                                              "wink.response.defaultCharset";                // $NON-NLS-1$ //$NON-NLS-1$
+                                                                              "wink.response.defaultCharset";                // $NON-NLS-1$
     private static final String       USE_ACCEPT_CHARSET                  =
-                                                                              "wink.response.useAcceptCharset";              // $NON-NLS-1$ //$NON-NLS-1$
+                                                                              "wink.response.useAcceptCharset";              // $NON-NLS-1$
     // handler chains
     private RequestHandlersChain      requestHandlersChain;
     private ResponseHandlersChain     responseHandlersChain;

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestFilter.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestFilter.java?rev=966803&r1=966802&r2=966803&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestFilter.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestFilter.java Thu Jul 22 18:56:55 2010
@@ -150,7 +150,7 @@ public class RestFilter implements Filte
                 return filterConfig.getServletContext();
             }
 
-            public Enumeration<?> getInitParameterNames() {
+            public Enumeration getInitParameterNames() {
                 return filterConfig.getInitParameterNames();
             }