You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wink.apache.org by "Snitkovsky, Martin" <ma...@hp.com> on 2009/07/14 06:28:07 UTC

RE: svn commit: r793330 - in /incubator/wink/trunk: ./ wink-client/ wink-client/src/test/java/org/apache/wink/client/ wink-client/wink-apache-client/ wink-client/wink-apache-client/.settings/ wink-client/wink-apache-client/src/ wink-client/wink-apache-...

Jason , thanks for your comments.
I will apply all your recommendations and move wink-apache-client to the level of wink-client.

-- martin

-----Original Message-----
From: Jason Dillon [mailto:jason.dillon@gmail.com] On Behalf Of Jason Dillon
Sent: Monday, July 13, 2009 7:35 AM
To: wink-dev@incubator.apache.org
Subject: Re: svn commit: r793330 - in /incubator/wink/trunk: ./ wink-client/ wink-client/src/test/java/org/apache/wink/client/ wink-client/wink-apache-client/ wink-client/wink-apache-client/.settings/ wink-client/wink-apache-client/src/ wink-client/wink-apache-...

I have a few issues with this change.

First (those eclipse files, but I see those were removed later, thx).

Second, this is not really following maven standards for grouping
modules.  The module was added as a sub-directory of the wink-client
module, which produces a jar file (its packaging is not pom). While
this will build, it is not intuitive for folks that are familiar with
standard maven build layout.

The general practice and standard is that only modules which have
packaging of type pom can contain sub-modules, and that (except in
more complex cases of bootstrapping or integration testing) a module's
parent is always ../pom.xml.

This change violates both of those.

I suggest moving wink-client/wink-apache-client to the top-level (peer
to wink-client) to fix the problem in the short-term.  Longer-term if
the wink-client is going to support plugins or extensions of a sort,
then a wink-client-plugins module should be created to organize them
there, or alternatively, making wink-client a packaging = pom, then
move what is now the wink-client jar to something like wink-client/
wink-client-core.

And some minor issues, there is no header license on the pom.xml.  The
pom.xml is formatted using tabs.  And there are no javadocs on these
classes.  I'd really like to get folks into the habit of at least
putting a class javadoc on to everything, with a terse (or verbose)
description... and nothing silly like:

/**
  * This is the Foo class
  */
public class Foo
{
...
}

Adding even the most basic description of what a class is actually for/
doing will greatly help new users/developers get started faster
groking the codebase.

--jason


On Jul 12, 2009, at 6:03 PM, martins@apache.org wrote:

> Author: martins
> Date: Sun Jul 12 11:03:42 2009
> New Revision: 793330
>
> URL: http://svn.apache.org/viewvc?rev=793330&view=rev
> Log:
> [WINK-39] -  Wink client - add support for Apache Http Client.
> Wink client integrates with new version of Apache Http Client 4.0 http://hc.apache.org/httpcomponents-client/index.html
>
> Added:
>    incubator/wink/trunk/wink-client/wink-apache-client/   (with props)
>    incubator/wink/trunk/wink-client/wink-apache-client/.settings/
>    incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.jdt.core.prefs
>    incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.wst.common.component
>    incubator/wink/trunk/wink-client/wink-apache-client/pom.xml
>    incubator/wink/trunk/wink-client/wink-apache-client/src/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/apache/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/apache/wink/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/apache/wink/client/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/apache/wink/client/ApacheHttpClientConfig.java
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/apache/wink/client/internal/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/apache/wink/client/internal/handlers/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/
> org/apache/wink/client/internal/handlers/
> ApacheHttpClientConnectionHandler.java
>    incubator/wink/trunk/wink-client/wink-apache-client/src/test/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/test/java/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/test/java/
> org/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/test/java/
> org/apache/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/test/java/
> org/apache/wink/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/test/java/
> org/apache/wink/client/
>    incubator/wink/trunk/wink-client/wink-apache-client/src/test/java/
> org/apache/wink/client/ApacheClientTest.java
>    incubator/wink/trunk/wink-client/wink-apache-httpclient-support/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/src/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/java/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/java/com/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/java/com/hp/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/java/com/hp/symphony/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/java/com/hp/symphony/client/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/java/com/hp/symphony/client/internal/
>    incubator/wink/trunk/wink-client/wink-client-apache-httpclient/
> src/main/java/com/hp/symphony/client/internal/handlers/
>    incubator/wink/trunk/wink-component-test-support/src/main/java/
> org/apache/wink/client/
>    incubator/wink/trunk/wink-component-test-support/src/main/java/
> org/apache/wink/client/BaseTest.java
>      - copied unchanged from r790025, incubator/wink/trunk/wink-
> client/src/test/java/org/apache/wink/client/BaseTest.java
>    incubator/wink/trunk/wink-component-test-support/src/main/java/
> org/apache/wink/client/MockHttpServer.java
>      - copied, changed from r790025, incubator/wink/trunk/wink-
> client/src/test/java/org/apache/wink/client/MockHttpServer.java
> Removed:
>    incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/
> client/BaseTest.java
>    incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/
> client/MockHttpServer.java
> Modified:
>    incubator/wink/trunk/pom.xml
>    incubator/wink/trunk/wink-client/pom.xml
>
> Modified: incubator/wink/trunk/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/pom.xml?rev=793330&r1=793329&r2=793330&view=diff
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/pom.xml (original)
> +++ incubator/wink/trunk/pom.xml Sun Jul 12 11:03:42 2009
> @@ -46,6 +46,7 @@
>         <module>wink-common</module>
>         <module>wink-server</module>
>         <module>wink-client</module>
> +        <module>wink-client/wink-apache-client</module>
>         <module>wink-spring-support</module>
>         <module>wink-webdav</module>
>         <module>wink-examples</module>
>
> Modified: incubator/wink/trunk/wink-client/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/pom.xml?rev=793330&r1=793329&r2=793330&view=diff
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/pom.xml (original)
> +++ incubator/wink/trunk/wink-client/pom.xml Sun Jul 12 11:03:42 2009
> @@ -70,5 +70,10 @@
>             <groupId>javax.activation</groupId>
>             <artifactId>activation</artifactId>
>         </dependency>
> +        <dependency>
> +                     <groupId>org.apache.wink</groupId>
> +                     <artifactId>wink-component-test-support</artifactId>
> +                     <scope>test</scope>
> +             </dependency>
>     </dependencies>
> </project>
>
> Propchange: incubator/wink/trunk/wink-client/wink-apache-client/
> ------------------------------------------------------------------------------
> --- svn:ignore (added)
> +++ svn:ignore Sun Jul 12 11:03:42 2009
> @@ -0,0 +1,3 @@
> +target
> +.classpath
> +.project
>
> Added: incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.jdt.core.prefs
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/wink-apache-client/.settings/org.eclipse.jdt.core.prefs?rev=793330&view=auto
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.jdt.core.prefs (added)
> +++ incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.jdt.core.prefs Sun Jul 12 11:03:42 2009
> @@ -0,0 +1,5 @@
> +#Sun Jul 12 10:21:25 IDT 2009
> +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
> +eclipse.preferences.version=1
> +org.eclipse.jdt.core.compiler.source=1.5
> +org.eclipse.jdt.core.compiler.compliance=1.5
>
> Added: incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.wst.common.component
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/wink-apache-client/.settings/org.eclipse.wst.common.component?rev=793330&view=auto
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.wst.common.component (added)
> +++ incubator/wink/trunk/wink-client/wink-apache-client/.settings/
> org.eclipse.wst.common.component Sun Jul 12 11:03:42 2009
> @@ -0,0 +1,6 @@
> +<project-modules id="moduleCoreId" project-version="1.5.0">
> +  <wb-module deploy-name="wink-apache-client">
> +    <wb-resource deploy-path="/" source-path="src/main/java"/>
> +    <wb-resource deploy-path="/" source-path="target/maven-shared-
> archive-resources"/>
> +  </wb-module>
> +</project-modules>
> \ No newline at end of file
>
> Added: incubator/wink/trunk/wink-client/wink-apache-client/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/wink-apache-client/pom.xml?rev=793330&view=auto
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/wink-apache-client/pom.xml
> (added)
> +++ incubator/wink/trunk/wink-client/wink-apache-client/pom.xml Sun
> Jul 12 11:03:42 2009
> @@ -0,0 +1,39 @@
> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
> "
> +     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd
> ">
> +     <modelVersion>4.0.0</modelVersion>
> +     <groupId>org.apache.wink</groupId>
> +     <artifactId>wink-apache-client</artifactId>
> +     <packaging>jar</packaging>
> +     <version>0.1-SNAPSHOT</version>
> +     <name>Wink Client :: Apache Http Client Support</name>
> +     <parent>
> +             <groupId>org.apache.wink</groupId>
> +             <artifactId>wink</artifactId>
> +             <version>0.1-SNAPSHOT</version>
> +             <relativePath>../../pom.xml</relativePath>
> +     </parent>
> +     <dependencies>
> +        <dependency>
> +            <groupId>org.apache.wink</groupId>
> +            <artifactId>wink-client</artifactId>
> +        </dependency>
> +             <dependency>
> +                     <groupId>junit</groupId>
> +                     <artifactId>junit</artifactId>
> +             </dependency>
> +             <dependency>
> +                     <groupId>junit</groupId>
> +                     <artifactId>junit</artifactId>
> +             </dependency>
> +             <dependency>
> +                     <groupId>org.apache.httpcomponents</groupId>
> +                     <artifactId>httpclient</artifactId>
> +                     <version>4.0-beta2</version>
> +             </dependency>
> +             <dependency>
> +                     <groupId>org.apache.wink</groupId>
> +                     <artifactId>wink-component-test-support</artifactId>
> +                     <scope>test</scope>
> +             </dependency>
> +     </dependencies>
> +</project>
>
> Added: incubator/wink/trunk/wink-client/wink-apache-client/src/main/
> java/org/apache/wink/client/ApacheHttpClientConfig.java
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/org/apache/wink/client/ApacheHttpClientConfig.java?rev=793330&view=auto
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/wink-apache-client/src/main/
> java/org/apache/wink/client/ApacheHttpClientConfig.java (added)
> +++ incubator/wink/trunk/wink-client/wink-apache-client/src/main/
> java/org/apache/wink/client/ApacheHttpClientConfig.java Sun Jul 12
> 11:03:42 2009
> @@ -0,0 +1,46 @@
> +/
> *******************************************************************************
> + * 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.wink.client;
> +
> +import org.apache.http.client.HttpClient;
> +
> +import org.apache.wink.client.ClientConfig;
> +import org.apache.wink.client.handlers.ConnectionHandler;
> +import
> org
> .apache
> .wink.client.internal.handlers.ApacheHttpClientConnectionHandler;
> +
> +public class ApacheHttpClientConfig extends ClientConfig {
> +
> +    private HttpClient client;
> +
> +    public ApacheHttpClientConfig() {
> +        client = null;
> +    }
> +
> +    public ApacheHttpClientConfig(HttpClient client) {
> +        this.client = client;
> +    }
> +
> +    @Override
> +    protected ConnectionHandler getConnectionHandler() {
> +        return new ApacheHttpClientConnectionHandler(client);
> +    }
> +
> +}
>
> Added: incubator/wink/trunk/wink-client/wink-apache-client/src/main/
> java/org/apache/wink/client/internal/handlers/
> ApacheHttpClientConnectionHandler.java
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/wink-apache-client/src/main/java/org/apache/wink/client/internal/handlers/ApacheHttpClientConnectionHandler.java?rev=793330&view=auto
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/wink-apache-client/src/main/
> java/org/apache/wink/client/internal/handlers/
> ApacheHttpClientConnectionHandler.java (added)
> +++ incubator/wink/trunk/wink-client/wink-apache-client/src/main/
> java/org/apache/wink/client/internal/handlers/
> ApacheHttpClientConnectionHandler.java Sun Jul 12 11:03:42 2009
> @@ -0,0 +1,272 @@
> +/
> *******************************************************************************
> + * 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.wink.client.internal.handlers;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.io.OutputStream;
> +import java.net.URI;
> +import java.util.List;
> +
> +import javax.ws.rs.core.MultivaluedMap;
> +
> +import org.apache.http.Header;
> +import org.apache.http.HttpEntity;
> +import org.apache.http.HttpHost;
> +import org.apache.http.HttpResponse;
> +import org.apache.http.StatusLine;
> +import org.apache.http.client.HttpClient;
> +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
> +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.impl.client.DefaultHttpClient;
> +import org.apache.http.params.BasicHttpParams;
> +import org.apache.http.params.CoreConnectionPNames;
> +import org.apache.wink.client.ClientConfig;
> +import org.apache.wink.client.ClientRequest;
> +import org.apache.wink.client.ClientResponse;
> +import org.apache.wink.client.handlers.HandlerContext;
> +
> +public class ApacheHttpClientConnectionHandler extends
> AbstractConnectionHandler {
> +
> +    private HttpClient httpclient;
> +
> +    public ApacheHttpClientConnectionHandler() {
> +        httpclient = null;
> +    }
> +
> +    public ApacheHttpClientConnectionHandler(HttpClient httpclient) {
> +        this.httpclient = httpclient;
> +    }
> +
> +    public ClientResponse handle(ClientRequest request,
> HandlerContext context) throws Exception {
> +        try {
> +            HttpResponse response = processRequest(request, context);
> +            return processResponse(request, context, response);
> +        } catch (Exception e) {
> +            throw new RuntimeException(e);
> +        }
> +    }
> +
> +    private HttpResponse processRequest(ClientRequest request,
> HandlerContext context) throws IOException {
> +        HttpClient client = openConnection(request);
> +        // TODO: move this functionality to the base class
> +        NonCloseableOutputStream ncos = new
> NonCloseableOutputStream();
> +        OutputStream os = ncos;
> +
> +        EntityWriter entityWriter = null;
> +        if (request.getEntity() != null) {
> +            os = adaptOutputStream(ncos, request,
> context.getOutputStreamAdapters());
> +            // prepare the entity that will write our entity
> +            entityWriter = new EntityWriter(this, request, os, ncos);
> +        }
> +
> +        HttpRequestBase entityRequest = setupHttpRequest(request,
> client, entityWriter);
> +
> +        return client.execute(entityRequest);
> +    }
> +
> +    private HttpRequestBase setupHttpRequest(ClientRequest request,
> HttpClient client, EntityWriter entityWriter) {
> +        URI uri = request.getURI();
> +        String method = request.getMethod();
> +        HttpRequestBase httpRequest = null;
> +        if (entityWriter == null) {
> +            GenericHttpRequestBase entityRequest = new
> GenericHttpRequestBase(method);
> +            httpRequest = entityRequest;
> +        } else {
> +            // create a new request with the specified method
> +            HttpEntityEnclosingRequestBase entityRequest = new
> GenericHttpEntityEnclosingRequestBase(method);
> +            entityRequest.setEntity(entityWriter);
> +            httpRequest = entityRequest;
> +        }
> +        // set the uri
> +        httpRequest.setURI(uri);
> +        // add all headers
> +        MultivaluedMap<String,String> headers = request.getHeaders();
> +        for (String header : headers.keySet()) {
> +            List<String> values = headers.get(header);
> +            for (String value : values) {
> +                if (value != null) {
> +                    httpRequest.addHeader(header, value);
> +                }
> +            }
> +        }
> +        return httpRequest;
> +    }
> +
> +    private HttpClient openConnection(ClientRequest request) {
> +        if (this.httpclient != null) {
> +            return this.httpclient;
> +        }
> +
> +        ClientConfig config =
> request.getAttribute(ClientConfig.class);
> +        BasicHttpParams params = new BasicHttpParams();
> +
> params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
> Integer.valueOf(config.getConnectTimeout()));
> +        params.setParameter(CoreConnectionPNames.SO_TIMEOUT,
> Integer.valueOf(config.getReadTimeout()));
> +        params.setParameter(ClientPNames.HANDLE_REDIRECTS,
> Boolean.valueOf(config.isFollowRedirects()));
> +        if (config.isFollowRedirects()) {
> +
> params.setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS,
> Boolean.TRUE);
> +        }
> +        // setup proxy
> +        if (config.getProxyHost() != null) {
> +            params.setParameter(ConnRoutePNames.DEFAULT_PROXY, new
> HttpHost(config.getProxyHost(), config.getProxyPort()));
> +        }
> +        HttpClient httpclient = new DefaultHttpClient(params);
> +        return httpclient;
> +    }
> +
> +    private ClientResponse processResponse(ClientRequest request,
> HandlerContext context, HttpResponse httpResponse) throws
> IllegalStateException, IOException {
> +        ClientResponse response = createResponse(request,
> httpResponse);
> +        InputStream is = httpResponse.getEntity().getContent();
> +        is = adaptInputStream(is, response,
> context.getInputStreamAdapters());
> +        response.setEntity(is);
> +        return response;
> +    }
> +
> +    private ClientResponse createResponse(ClientRequest request,
> HttpResponse httpResponse) {
> +        ClientResponse response = new ClientResponseImpl();
> +        StatusLine statusLine = httpResponse.getStatusLine();
> +        response.setStatusCode(statusLine.getStatusCode());
> +        response.setMessage(statusLine.getReasonPhrase());
> +        response.getAttributes().putAll(request.getAttributes());
> +        processResponseHeaders(response, httpResponse);
> +        return response;
> +    }
> +
> +    private void processResponseHeaders(ClientResponse response,
> HttpResponse httpResponse) {
> +        Header[] allHeaders = httpResponse.getAllHeaders();
> +        for (Header header : allHeaders) {
> +            response.getHeaders().add(header.getName(),
> header.getValue());
> +        }
> +    }
> +
> +    private static class GenericHttpRequestBase extends
> HttpRequestBase {
> +        private String method;
> +        public GenericHttpRequestBase(String method) {
> +            this.method = method;
> +        }
> +        @Override
> +        public String getMethod() {
> +            return method;
> +        }
> +    }
> +
> +    private static class GenericHttpEntityEnclosingRequestBase
> extends HttpEntityEnclosingRequestBase {
> +        private String method;
> +        public GenericHttpEntityEnclosingRequestBase(String method) {
> +            this.method = method;
> +        }
> +        @Override
> +        public String getMethod() {
> +            return method;
> +        }
> +    }
> +
> +    // TODO: move this class to the base class
> +    private static class NonCloseableOutputStream extends
> OutputStream {
> +        OutputStream os;
> +
> +        public NonCloseableOutputStream() {
> +        }
> +
> +        public void setOutputStream(OutputStream os) {
> +            this.os = os;
> +        }
> +
> +        @Override
> +        public void close() throws IOException {
> +            // do nothing
> +        }
> +
> +        @Override
> +        public void flush() throws IOException {
> +            os.flush();
> +        }
> +
> +        @Override
> +        public void write(byte[] b, int off, int len) throws
> IOException {
> +            os.write(b, off, len);
> +        }
> +
> +        @Override
> +        public void write(byte[] b) throws IOException {
> +            os.write(b);
> +        }
> +
> +        @Override
> +        public void write(int b) throws IOException {
> +            os.write(b);
> +        }
> +    }
> +
> +    private static class EntityWriter implements HttpEntity {
> +
> +        private ApacheHttpClientConnectionHandler
> apacheHttpClientHandler;
> +        private ClientRequest request;
> +        private OutputStream adaptedOutputStream;
> +        private NonCloseableOutputStream ncos;
> +
> +        public EntityWriter(ApacheHttpClientConnectionHandler
> apacheHttpClientHandler, ClientRequest request, OutputStream
> adaptedOutputStream, NonCloseableOutputStream ncos) {
> +            this.apacheHttpClientHandler = apacheHttpClientHandler;
> +            this.request = request;
> +            this.adaptedOutputStream = adaptedOutputStream;
> +            this.ncos = ncos;
> +        }
> +
> +        public void consumeContent() throws IOException {
> +        }
> +
> +        public InputStream getContent() throws IOException,
> IllegalStateException {
> +            return null;
> +        }
> +
> +        public Header getContentEncoding() {
> +            return null;
> +        }
> +
> +        public long getContentLength() {
> +            return -1;
> +        }
> +
> +        public Header getContentType() {
> +            return null;
> +        }
> +
> +        public boolean isChunked() {
> +            return true;
> +        }
> +
> +        public boolean isRepeatable() {
> +            return true;
> +        }
> +
> +        public boolean isStreaming() {
> +            return true;
> +        }
> +
> +        public void writeTo(OutputStream os) throws IOException {
> +            ncos.setOutputStream(os);
> +            apacheHttpClientHandler.writeEntity(request,
> adaptedOutputStream);
> +        }
> +
> +    }
> +}
>
> Added: incubator/wink/trunk/wink-client/wink-apache-client/src/test/
> java/org/apache/wink/client/ApacheClientTest.java
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/wink-apache-client/src/test/java/org/apache/wink/client/ApacheClientTest.java?rev=793330&view=auto
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/wink-apache-client/src/test/
> java/org/apache/wink/client/ApacheClientTest.java (added)
> +++ incubator/wink/trunk/wink-client/wink-apache-client/src/test/
> java/org/apache/wink/client/ApacheClientTest.java Sun Jul 12
> 11:03:42 2009
> @@ -0,0 +1,236 @@
> +/
> *******************************************************************************
> + * 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.wink.client;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.io.OutputStream;
> +import java.lang.annotation.Annotation;
> +import java.lang.reflect.ParameterizedType;
> +import java.lang.reflect.Type;
> +import java.text.MessageFormat;
> +import java.util.HashSet;
> +import java.util.Set;
> +
> +import javax.ws.rs.WebApplicationException;
> +import javax.ws.rs.core.Application;
> +import javax.ws.rs.core.MediaType;
> +import javax.ws.rs.core.MultivaluedMap;
> +import javax.ws.rs.ext.MessageBodyReader;
> +import javax.ws.rs.ext.MessageBodyWriter;
> +import javax.ws.rs.ext.Provider;
> +
> +import org.apache.wink.common.utils.ProviderUtils;
> +
> +
> +public class ApacheClientTest extends BaseTest {
> +
> +    public static class TestGenerics<T> {
> +        private T t;
> +
> +        public TestGenerics() {
> +        }
> +
> +        public T getT() {
> +            return t;
> +        }
> +
> +        public void setT(T t) {
> +            this.t = t;
> +        }
> +    }
> +
> +    @Provider
> +    public static class TestGenericsProvider implements
> MessageBodyWriter<TestGenerics<String>>,
> MessageBodyReader<TestGenerics<String>> {
> +
> +        public long getSize(TestGenerics<String> t, Class<?> type,
> Type genericType, Annotation[] annotations,
> +                MediaType mediaType) {
> +            return t.getT().length();
> +        }
> +
> +        public boolean isWriteable(Class<?> type, Type genericType,
> Annotation[] annotations, MediaType mediaType) {
> +            return isTestGenericsString(type, genericType);
> +        }
> +
> +        private boolean isTestGenericsString(Class<?> type, Type
> genericType) {
> +            return type.equals(TestGenerics.class) && genericType
> instanceof ParameterizedType &&
> +
> ((ParameterizedType)genericType).getActualTypeArguments()
> [0].equals(String.class);
> +        }
> +
> +        public void writeTo(TestGenerics<String> t, Class<?> type,
> Type genericType, Annotation[] annotations,
> +                MediaType mediaType, MultivaluedMap<String,Object>
> httpHeaders, OutputStream entityStream)
> +                throws IOException, WebApplicationException {
> +            String string = t.getT();
> +            ProviderUtils.writeToStream(string, entityStream,
> mediaType);
> +        }
> +
> +        public boolean isReadable(Class<?> type, Type genericType,
> Annotation[] annotations, MediaType mediaType) {
> +            return isTestGenericsString(type, genericType);
> +        }
> +
> +        public TestGenerics<String>
> readFrom(Class<TestGenerics<String>> type, Type genericType,
> +                Annotation[] annotations, MediaType mediaType,
> MultivaluedMap<String,String> httpHeaders,
> +                InputStream entityStream) throws IOException,
> WebApplicationException {
> +            TestGenerics<String> tg = new TestGenerics<String>();
> +            String string =
> ProviderUtils.readFromStreamAsString(entityStream, mediaType);
> +            tg.setT(string);
> +            return tg;
> +        }
> +    }
> +
> +    private RestClient getRestClient() {
> +        return new RestClient(new
> ApacheHttpClientConfig().applications(new Application() {
> +            @Override
> +            public Set<Class<?>> getClasses() {
> +                Set<Class<?>> set = new HashSet<Class<?>>();
> +                set.add(TestGenericsProvider.class);
> +                return set;
> +            }
> +
> +        }));
> +    }
> +
> +    public void testResourceGet() {
> +        server.setMockResponseCode(200);
> +        RestClient client = getRestClient();
> +        Resource resource = client.resource(serviceURL);
> +
> +        String string = resource.get(String.class);
> +        assertEquals(RECEIVED_MESSAGE, string);
> +
> +        // do get with response
> +        ClientResponse clientResponse = resource.get();
> +        assertEquals(RECEIVED_MESSAGE,
> clientResponse.getEntity(String.class));
> +
> +        // test generic entity
> +        TestGenerics<String> tg = resource.get(new
> EntityType<TestGenerics<String>>(){});
> +        assertEquals(RECEIVED_MESSAGE, tg.getT());
> +    }
> +
> +    public void testResourcePut() throws IOException {
> +        server.setMockResponseCode(200);
> +        RestClient client = getRestClient();
> +        Resource resource = client.resource(serviceURL + "/
> testResourcePut");
> +        String response = resource.contentType("text/
> plain").accept("text/plain").put(String.class, SENT_MESSAGE);
> +        assertEquals(RECEIVED_MESSAGE, response);
> +        assertEquals(SENT_MESSAGE,
> server.getRequestContentAsString());
> +
> +        // do put with response
> +        ClientResponse clientResponse = resource.put(SENT_MESSAGE);
> +        assertEquals(RECEIVED_MESSAGE,
> clientResponse.getEntity(String.class));
> +
> +        // test generic entity
> +        TestGenerics<String> tg = resource.put(new
> EntityType<TestGenerics<String>>(){}, SENT_MESSAGE);
> +        assertEquals(RECEIVED_MESSAGE, tg.getT());
> +
> +    }
> +
> +    public void testResourcePost() throws IOException {
> +        server.setMockResponseCode(200);
> +        RestClient client = getRestClient();
> +        Resource resource = client.resource(serviceURL + "/
> testResourcePost");
> +        String response = resource.contentType("text/
> plain").accept("text/plain").post(String.class, SENT_MESSAGE);
> +        assertEquals(RECEIVED_MESSAGE, response);
> +        assertEquals(SENT_MESSAGE,
> server.getRequestContentAsString());
> +
> +        // do post with response
> +        ClientResponse clientResponse = resource.post(SENT_MESSAGE);
> +        assertEquals(RECEIVED_MESSAGE,
> clientResponse.getEntity(String.class));
> +
> +        // test generic entity
> +        TestGenerics<String> tg = resource.post(new
> EntityType<TestGenerics<String>>(){}, SENT_MESSAGE);
> +        assertEquals(RECEIVED_MESSAGE, tg.getT());
> +}
> +
> +    public void testResourceDelete() {
> +        server.setMockResponseCode(200);
> +        RestClient client = getRestClient();
> +        Resource resource = client.resource(serviceURL);
> +        String response =
> resource.accept(MediaType.TEXT_PLAIN_TYPE).delete(String.class);
> +        assertEquals(RECEIVED_MESSAGE, response);
> +
> +        // do delete with response
> +        ClientResponse clientResponse = resource.delete();
> +        assertEquals(RECEIVED_MESSAGE,
> clientResponse.getEntity(String.class));
> +
> +        // test generic entity
> +        TestGenerics<String> tg = resource.delete(new
> EntityType<TestGenerics<String>>(){});
> +        assertEquals(RECEIVED_MESSAGE, tg.getT());
> +    }
> +
> +    public void testInvoke() {
> +        server.setMockResponseCode(200);
> +        RestClient client = getRestClient();
> +        Resource resource = client.resource(serviceURL);
> +
> +        String string = resource.invoke("GET", String.class, null);
> +        assertEquals(RECEIVED_MESSAGE, string);
> +
> +        // test generic entity
> +        TestGenerics<String> tg = resource.invoke("GET", new
> EntityType<TestGenerics<String>>(){}, null);
> +        assertEquals(RECEIVED_MESSAGE, tg.getT());
> +    }
> +
> +    public void testHttpErrorNoResponse() throws IOException {
> +        server.setMockResponseCode(400);
> +        RestClient client = getRestClient();
> +        Resource resource = client.resource(serviceURL);
> +        try {
> +            resource.accept("text/plain").invoke("GET",
> String.class, null);
> +            fail("ClientWebException must be thrown");
> +        } catch (ClientWebException e) {
> +            assertTrue(e.getResponse().getStatusCode() == 400);
> +        }
> +    }
> +
> +    public void testHttpErrorWithResponse() throws IOException {
> +        server.setMockResponseCode(400);
> +        RestClient client = getRestClient();
> +        Resource resource = client.resource(serviceURL);
> +        try {
> +            ClientResponse res = resource.accept("text/plain").get();
> +            assertTrue(res.getStatusCode() == 400);
> +        } catch (Exception e) {
> +            fail("Exception must not be thrown");
> +        }
> +    }
> +
> +    public void testResponseCharset() throws IOException {
> +
> +        MockHttpServer server = new MockHttpServer(34567);
> +        server.setMockResponseCode(200);
> +        server.setMockResponseContent("REQUEST".getBytes("UTF-16"));
> +        server.setMockResponseContentType("text/plain;
> charset=UTF-16");
> +
> +        server.startServer();
> +        try {
> +            RestClient client = getRestClient();
> +            Resource resource =
> client.resource(MessageFormat.format(SERVICE_URL, String
> +                    .valueOf(server.getServerPort())));
> +            String response =
> resource.accept(MediaType.TEXT_PLAIN_TYPE).get(String.class);
> +            assertEquals("REQUEST", response);
> +
> +        } finally {
> +            server.stopServer();
> +        }
> +    }
> +}
>
> Copied: incubator/wink/trunk/wink-component-test-support/src/main/
> java/org/apache/wink/client/MockHttpServer.java (from r790025,
> incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/
> client/MockHttpServer.java)
> URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-component-test-support/src/main/java/org/apache/wink/client/MockHttpServer.java?p2=incubator/wink/trunk/wink-component-test-support/src/main/java/org/apache/wink/client/MockHttpServer.java&p1=incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/client/MockHttpServer.java&r1=790025&r2=793330&rev=793330&view=diff
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/
> client/MockHttpServer.java (original)
> +++ incubator/wink/trunk/wink-component-test-support/src/main/java/
> org/apache/wink/client/MockHttpServer.java Sun Jul 12 11:03:42 2009
> @@ -36,6 +36,8 @@
>
> import javax.net.ServerSocketFactory;
> import javax.net.ssl.SSLServerSocketFactory;
> +import javax.ws.rs.core.Response;
> +import javax.ws.rs.core.Response.Status;
>
> public class MockHttpServer extends Thread {
>
> @@ -354,7 +356,12 @@
>
>             OutputStream sos = socket.getOutputStream();
>             BufferedOutputStream os = new BufferedOutputStream(sos);
> -            os.write(("HTTP/1.1 " +
> org
> .apache
> .wink
> .common
> .http.HttpStatus.valueOf(mockResponseCode).toString()).getBytes());
> +            String reason = "";
> +            Status statusCode =
> Response.Status.fromStatusCode(mockResponseCode);
> +            if(statusCode !=null){
> +                reason = statusCode.toString();
> +            }
> +            os.write(("HTTP/1.1 " + mockResponseCode + " " +
> reason).getBytes());
>             os.write(NEW_LINE);
>             processResponseHeaders(os);
>             processResponseContent(os);
>
>