Rover12421's Blog

The End.

修改Apache XmlRpc支持HttpClient 4.1.3

xmlrpc-client-3.1.3_rs

        好不容易找到了解决XmlRpc支持自定义HttpClient的方法,结果发现支持的是3.x的。HtppClient 3.x已经不被推荐使用了。HttpClient更新到4.x之后同之前的结构有很大的区别,修改起来还是很痛苦的。花了一天时间,终于改好了。

        修改的文件只有两个:XmlRpcCommonsTransport.java 和 XmlRpcCommonsTransportFactory.java 。主要的修改在 XmlRpcCommonsTransport.java 中。代码我贴上来了。可以用来作为 HttpClient 从3.x升级到4.x的参考。

/
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.xmlrpc.client;

import java.io.BufferedOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.auth.params.AuthPNames;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcRequest;
import org.apache.xmlrpc.common.XmlRpcStreamConfig;
import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
import org.apache.xmlrpc.util.HttpUtil;
import org.apache.xmlrpc.util.XmlRpcIOException;
import org.xml.sax.SAXException;

/ An HTTP transport factory, which is based on the Jakarta Commons
HTTP Client.
/
public class XmlRpcCommonsTransport extends XmlRpcHttpTransport {
    /

     * Maximum number of allowed redirects.
     */
    private static final int MAX_REDIRECT_ATTEMPTS = 100;

    protected final DefaultHttpClient client;
    private static final String userAgent = USER_AGENT + “ (Jakarta Commons httpclient Transport)”;
    //protected PostMethod method;
    protected  HttpPost method;
    protected  HttpResponse response;
    private int contentLength = -1;
    private XmlRpcHttpClientConfig config;     

    /* Creates a new instance.
     * @param pFactory The factory, which created this transport.
    
/
    public XmlRpcCommonsTransport(XmlRpcCommonsTransportFactory pFactory) {
        super(pFactory.getClient(), userAgent);
        DefaultHttpClient httpClient = pFactory.getHttpClient();
        if (httpClient == null) {
            httpClient = newHttpClient();
        }
        client = httpClient;
     }

    protected void setContentLength(int pLength) {
        contentLength = pLength;
    }

    protected DefaultHttpClient newHttpClient() {
        return new DefaultHttpClient();
    }

    protected void initHttpHeaders(XmlRpcRequest pRequest) throws XmlRpcClientException {
        config = (XmlRpcHttpClientConfig) pRequest.getConfig();
        method = newPostMethod(config);
        super.initHttpHeaders(pRequest);
       
//        if (config.getConnectionTimeout() != 0)
//            client.getHttpConnectionManager().getParams().setConnectionTimeout(config.getConnectionTimeout());
        if (config.getConnectionTimeout() != ) {
            //设置连接超时时间
            HttpParams params = client.getParams();
            HttpConnectionParams.setConnectionTimeout(params, config.getConnectionTimeout());           
        }
       
       
//        if (config.getReplyTimeout() != 0)
//            client.getHttpConnectionManager().getParams().setSoTimeout(config.getReplyTimeout());
        if (config.getReplyTimeout() != ) {
            //设置读数据超时时间
            HttpParams params = client.getParams();
            HttpConnectionParams.setSoTimeout(params, config.getReplyTimeout());
        }
       
        //method.getParams().setVersion(HttpVersion.HTTP_1_1);
        //设置HTTP协议版本号
        HttpParams params = client.getParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    }

    protected HttpPost newPostMethod(XmlRpcHttpClientConfig pConfig) {
        return new HttpPost(pConfig.getServerURL().toString());
    }

    protected void setRequestHeader(String pHeader, String pValue) {
        //method.setRequestHeader(new Header(pHeader, pValue));
        method.setHeader(pHeader, pValue);
    }

    protected boolean isResponseGzipCompressed() {
        //Header h = method.getResponseHeader( “Content-Encoding” );
        Header h = response.getFirstHeader( “Content-Encoding” );
        if (h == null) {
            return false;
        } else {
            return HttpUtil.isUsingGzipEncoding(h.getValue());
        }
    }

    protected InputStream getInputStream() throws XmlRpcException {
        try {
            //checkStatus(method);
            checkStatus(response);
            HttpEntity entity =response.getEntity();
            if (entity != null) {
                return entity.getContent();
            }
            else
            {
                return null;
            }
            //return method.getResponseBodyAsStream();
//        } catch (HttpException e) {
//            throw new XmlRpcClientException(“Error in HTTP transport: ” + e.getMessage(), e);
        } catch (IOException e) {
            throw new XmlRpcClientException(“I/O error in server communication: ” + e.getMessage(), e);
        }
    }

    protected void setCredentials(XmlRpcHttpClientConfig pConfig) throws XmlRpcClientException {
        String userName = pConfig.getBasicUserName();
        if (userName != null) {
            String enc = pConfig.getBasicEncoding();
            if (enc == null) {
                enc = XmlRpcStreamConfig.UTF8_ENCODING;
            }
           
//            client.getParams().setParameter(HttpMethodParams.CREDENTIAL_CHARSET, enc);
            client.getParams().setParameter(AuthPNames.CREDENTIAL_CHARSET, enc);
           
            Credentials creds = new UsernamePasswordCredentials(userName, pConfig.getBasicPassword());
            AuthScope scope = new AuthScope(null, AuthScope.ANY_PORT, null, AuthScope.ANY_SCHEME);
           
//            client.getState().setCredentials(scope, creds);
            client.getCredentialsProvider().setCredentials(scope, creds);
           
//            client.getParams().setAuthenticationPreemptive(true);
            try {
                method.addHeader(new BasicScheme().authenticate(creds, method));
            } catch (AuthenticationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    protected void close() throws XmlRpcClientException {
        //method.releaseConnection();
       
    }

    protected boolean isResponseGzipCompressed(XmlRpcStreamRequestConfig pConfig) {
        //Header h = method.getResponseHeader( “Content-Encoding” );
        Header h = response.getFirstHeader( “Content-Encoding” );
        if (h == null) {
            return false;
        } else {
            return HttpUtil.isUsingGzipEncoding(h.getValue());
        }
    }

    protected boolean isRedirectRequired() {
//        switch (method.getStatusCode()) {
        switch (response.getStatusLine().getStatusCode()) {
            case HttpStatus.SC_MOVED_TEMPORARILY:
            case HttpStatus.SC_MOVED_PERMANENTLY:
            case HttpStatus.SC_SEE_OTHER:
            case HttpStatus.SC_TEMPORARY_REDIRECT:
                return true;
            default:
                return false;
        }
    }

    protected void resetClientForRedirect()
            throws XmlRpcException {
        //get the location header to find out where to redirect to
        //Header locationHeader = method.getResponseHeader(“location”);
        Header locationHeader = response.getFirstHeader(“location”);
        if (locationHeader == null) {
            throw new XmlRpcException(“Invalid redirect: Missing location header”);
        }
        String location = locationHeader.getValue();

        URI redirectUri = null;
//        URI currentUri = null;
//        try {
//            currentUri = method.getURI();           
//            String charset = currentUri.getProtocolCharset();
//            redirectUri = new URI(location, true, charset);
//            method.setURI(redirectUri);
//        } catch (URIException ex) {
//            throw new XmlRpcException(ex.getMessage(), ex);
//        }
       
        //重定向URI
        try {
            redirectUri = new URI(location);
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        method.setURI(redirectUri);

        //And finally invalidate the actual authentication scheme
        //method.getHostAuthState().invalidate();       
        try {
            EntityUtils.consume(response.getEntity());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    protected void writeRequest(final ReqWriter pWriter) throws XmlRpcException {
       
        HttpEntity entity = new HttpEntity(){

            @Override
            public void writeTo(OutputStream pOut) throws IOException {
                // TODO Auto-generated method stub
                try {
                    / Make sure, that the socket is not closed by replacing it with our
                     * own BufferedOutputStream.
                    
/
                    OutputStream ostream;
                    if (isUsingByteArrayOutput(config)) {
                        // No need to buffer the output.
                        ostream = new FilterOutputStream(pOut){
                            public void close() throws IOException {
                                flush();
                            }
                        };
                    } else {
                        ostream = new BufferedOutputStream(pOut){
                            public void close() throws IOException {
                                flush();
                            }
                        };
                    }
                    pWriter.write(ostream);
                } catch (XmlRpcException e) {
                    throw new XmlRpcIOException(e);
                } catch (SAXException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            @Override
            public void consumeContent() throws IOException {
                // TODO Auto-generated method stub
               
            }

            @Override
            public InputStream getContent() throws IOException,
                    IllegalStateException {
                // TODO Auto-generated method stub
                return null;
            }

            @Override
            public Header getContentEncoding() {
                // TODO Auto-generated method stub
                return null;
            }

            @Override
            public long getContentLength() {
                // TODO Auto-generated method stub
                return contentLength;
            }

            @Override
            public Header getContentType() {
                // TODO Auto-generated method stub
                return new BasicHeader(HTTP.CONTENT_TYPE, “text/xml”);
            }

            @Override
            public boolean isChunked() {
                // TODO Auto-generated method stub
                return false;
            }

            @Override
            public boolean isRepeatable() {
                // TODO Auto-generated method stub
                return true;
            }

            @Override
            public boolean isStreaming() {
                // TODO Auto-generated method stub
                return false;
            }
        };
       
       
        method.setEntity(entity);
               
//        method.setRequestEntity(new RequestEntity(){
//            public boolean isRepeatable() { return true; }
//            public void writeRequest(OutputStream pOut) throws IOException {
//                try {
//                    / Make sure, that the socket is not closed by replacing it with our
//                     * own BufferedOutputStream.
//                    
/
//                    OutputStream ostream;
//                    if (isUsingByteArrayOutput(config)) {
//                        // No need to buffer the output.
//                        ostream = new FilterOutputStream(pOut){
//                            public void close() throws IOException {
//                                flush();
//                            }
//                        };
//                    } else {
//                        ostream = new BufferedOutputStream(pOut){
//                            public void close() throws IOException {
//                                flush();
//                            }
//                        };
//                    }
//                    pWriter.write(ostream);
//                } catch (XmlRpcException e) {
//                    throw new XmlRpcIOException(e);
//                } catch (SAXException e) {
//                    throw new XmlRpcIOException(e);
//                }
//            }
//            public long getContentLength() { return contentLength; }
//            public String getContentType() { return “text/xml”; }
//        });
       
        try {
            int redirectAttempts = ;
            for (;;) {
                response = client.execute(method);
                if (!isRedirectRequired()) {
                    break;
                }
                if (redirectAttempts++ > MAX_REDIRECT_ATTEMPTS) {
                    throw new XmlRpcException(“Too many redirects.”);
                }
                resetClientForRedirect();
            }
        } catch (XmlRpcIOException e) {
            Throwable t = e.getLinkedException();
            if (t instanceof XmlRpcException) {
                throw (XmlRpcException) t;
            } else {
                throw new XmlRpcException(“Unexpected exception: ” + t.getMessage(), t);
            }
        } catch (IOException e) {
            throw new XmlRpcException(“I/O error while communicating with HTTP server: ” + e.getMessage(), e);
        }
    }
   
    /*
     * Check the status of the HTTP request and throw an XmlRpcHttpTransportException if it
     * indicates that there is an error.
     * @param pResponse the method that has been executed
     * @throws XmlRpcHttpTransportException if the status of the method indicates that there is an error.
    
/
    //private void checkStatus(HttpMethod pMethod) throws XmlRpcHttpTransportException {
    private void checkStatus(HttpResponse pResponse) throws XmlRpcHttpTransportException {
//        final int status = pMethod.getStatusCode();
        final int status = pResponse.getStatusLine().getStatusCode();
       
        // All status codes except SC_OK are handled as errors. Perhaps some should require special handling (e.g., SC_UNAUTHORIZED)
        if (status < 200  ||  status > 299) {
            //throw new XmlRpcHttpTransportException(status, pMethod.getStatusText());
            throw new XmlRpcHttpTransportException(status, pResponse.getStatusLine().getReasonPhrase());
        }
    }
}

修改好的xmlrpc-client-3.1.3.jar我已经贴上来了。哈哈,你知道在哪吗?就是本文章开头的内涵图。保存下来试试用winrar打开看看吧。

Comments