pt 1 in reviving the android build (copied from pm 28a1, wish me luck)

This commit is contained in:
wuggy 2026-04-08 15:43:25 -07:00
commit d7788a6d6d
4249 changed files with 468189 additions and 0 deletions

View file

@ -0,0 +1,49 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.auth.AuthScheme;
/**
* Abstract {@link AuthScheme} cache. Initialized {@link AuthScheme} objects
* from this cache can be used to preemptively authenticate against known
* hosts.
*
* @since 4.1
*/
public interface AuthCache {
void put(HttpHost host, AuthScheme authScheme);
AuthScheme get(HttpHost host);
void remove(HttpHost host);
void clear();
}

View file

@ -0,0 +1,101 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.util.Map;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.auth.AuthScheme;
import ch.boye.httpclientandroidlib.auth.AuthenticationException;
import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
/**
* A handler for determining if an HTTP response represents an authentication
* challenge that was sent back to the client as a result of authentication
* failure.
* <p>
* Implementations of this interface must be thread-safe. Access to shared
* data must be synchronized as methods of this interface may be executed
* from multiple threads.
*
* @since 4.0
*
* @deprecated (4.2) use {@link AuthenticationStrategy}
*/
@Deprecated
public interface AuthenticationHandler {
/**
* Determines if the given HTTP response response represents
* an authentication challenge that was sent back as a result
* of authentication failure
* @param response HTTP response.
* @param context HTTP context.
* @return <code>true</code> if user authentication is required,
* <code>false</code> otherwise.
*/
boolean isAuthenticationRequested(
HttpResponse response,
HttpContext context);
/**
* Extracts from the given HTTP response a collection of authentication
* challenges, each of which represents an authentication scheme supported
* by the authentication host.
*
* @param response HTTP response.
* @param context HTTP context.
* @return a collection of challenges keyed by names of corresponding
* authentication schemes.
* @throws MalformedChallengeException if one of the authentication
* challenges is not valid or malformed.
*/
Map<String, Header> getChallenges(
HttpResponse response,
HttpContext context) throws MalformedChallengeException;
/**
* Selects one authentication challenge out of all available and
* creates and generates {@link AuthScheme} instance capable of
* processing that challenge.
* @param challenges collection of challenges.
* @param response HTTP response.
* @param context HTTP context.
* @return authentication scheme to use for authentication.
* @throws AuthenticationException if an authentication scheme
* could not be selected.
*/
AuthScheme selectScheme(
Map<String, Header> challenges,
HttpResponse response,
HttpContext context) throws AuthenticationException;
}

View file

@ -0,0 +1,130 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.util.Map;
import java.util.Queue;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.auth.AuthOption;
import ch.boye.httpclientandroidlib.auth.AuthScheme;
import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
/**
* A handler for determining if an HTTP response represents an authentication challenge that was
* sent back to the client as a result of authentication failure.
* <p>
* Implementations of this interface must be thread-safe. Access to shared data must be
* synchronized as methods of this interface may be executed from multiple threads.
*
* @since 4.2
*/
public interface AuthenticationStrategy {
/**
* Determines if the given HTTP response response represents
* an authentication challenge that was sent back as a result
* of authentication failure.
*
* @param authhost authentication host.
* @param response HTTP response.
* @param context HTTP context.
* @return <code>true</code> if user authentication is required,
* <code>false</code> otherwise.
*/
boolean isAuthenticationRequested(
HttpHost authhost,
HttpResponse response,
HttpContext context);
/**
* Extracts from the given HTTP response a collection of authentication
* challenges, each of which represents an authentication scheme supported
* by the authentication host.
*
* @param authhost authentication host.
* @param response HTTP response.
* @param context HTTP context.
* @return a collection of challenges keyed by names of corresponding
* authentication schemes.
* @throws MalformedChallengeException if one of the authentication
* challenges is not valid or malformed.
*/
Map<String, Header> getChallenges(
HttpHost authhost,
HttpResponse response,
HttpContext context) throws MalformedChallengeException;
/**
* Selects one authentication challenge out of all available and
* creates and generates {@link AuthOption} instance capable of
* processing that challenge.
*
* @param challenges collection of challenges.
* @param authhost authentication host.
* @param response HTTP response.
* @param context HTTP context.
* @return authentication auth schemes that can be used for authentication. Can be empty.
* @throws MalformedChallengeException if one of the authentication
* challenges is not valid or malformed.
*/
Queue<AuthOption> select(
Map<String, Header> challenges,
HttpHost authhost,
HttpResponse response,
HttpContext context) throws MalformedChallengeException;
/**
* Callback invoked in case of successful authentication.
*
* @param authhost authentication host.
* @param authScheme authentication scheme used.
* @param context HTTP context.
*/
void authSucceeded(
HttpHost authhost,
AuthScheme authScheme,
HttpContext context);
/**
* Callback invoked in case of unsuccessful authentication.
*
* @param authhost authentication host.
* @param authScheme authentication scheme used.
* @param context HTTP context.
*/
void authFailed(
HttpHost authhost,
AuthScheme authScheme,
HttpContext context);
}

View file

@ -0,0 +1,54 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
/**
* Represents a controller that dynamically adjusts the size
* of an available connection pool based on feedback from
* using the connections.
*
* @since 4.2
*
*/
public interface BackoffManager {
/**
* Called when we have decided that the result of
* using a connection should be interpreted as a
* backoff signal.
*/
public void backOff(HttpRoute route);
/**
* Called when we have determined that the result of
* using a connection has succeeded and that we may
* probe for more connections.
*/
public void probe(HttpRoute route);
}

View file

@ -0,0 +1,68 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Signals a circular redirect
*
*
* @since 4.0
*/
@Immutable
public class CircularRedirectException extends RedirectException {
private static final long serialVersionUID = 6830063487001091803L;
/**
* Creates a new CircularRedirectException with a <tt>null</tt> detail message.
*/
public CircularRedirectException() {
super();
}
/**
* Creates a new CircularRedirectException with the specified detail message.
*
* @param message The exception detail message
*/
public CircularRedirectException(final String message) {
super(message);
}
/**
* Creates a new CircularRedirectException with the specified detail message and cause.
*
* @param message the exception detail message
* @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
* if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
*/
public CircularRedirectException(final String message, final Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,61 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.io.IOException;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Signals an error in the HTTP protocol.
*
* @since 4.0
*/
@Immutable
public class ClientProtocolException extends IOException {
private static final long serialVersionUID = -5596590843227115865L;
public ClientProtocolException() {
super();
}
public ClientProtocolException(final String s) {
super(s);
}
public ClientProtocolException(final Throwable cause) {
initCause(cause);
}
public ClientProtocolException(final String message, final Throwable cause) {
super(message);
initCause(cause);
}
}

View file

@ -0,0 +1,64 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.HttpResponse;
/**
* When managing a dynamic number of connections for a given route, this
* strategy assesses whether a given request execution outcome should
* result in a backoff signal or not, based on either examining the
* <code>Throwable</code> that resulted or by examining the resulting
* response (e.g. for its status code).
*
* @since 4.2
*
*/
public interface ConnectionBackoffStrategy {
/**
* Determines whether seeing the given <code>Throwable</code> as
* a result of request execution should result in a backoff
* signal.
* @param t the <code>Throwable</code> that happened
* @return <code>true</code> if a backoff signal should be
* given
*/
boolean shouldBackoff(Throwable t);
/**
* Determines whether receiving the given {@link HttpResponse} as
* a result of request execution should result in a backoff
* signal. Implementations MUST restrict themselves to examining
* the response header and MUST NOT consume any of the response
* body, if any.
* @param resp the <code>HttpResponse</code> that was received
* @return <code>true</code> if a backoff signal should be
* given
*/
boolean shouldBackoff(HttpResponse resp);
}

View file

@ -0,0 +1,71 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.util.Date;
import java.util.List;
import ch.boye.httpclientandroidlib.cookie.Cookie;
/**
* This interface represents an abstract store for {@link Cookie}
* objects.
*
* @since 4.0
*/
public interface CookieStore {
/**
* Adds an {@link Cookie}, replacing any existing equivalent cookies.
* If the given cookie has already expired it will not be added, but existing
* values will still be removed.
*
* @param cookie the {@link Cookie cookie} to be added
*/
void addCookie(Cookie cookie);
/**
* Returns all cookies contained in this store.
*
* @return all cookies
*/
List<Cookie> getCookies();
/**
* Removes all of {@link Cookie}s in this store that have expired by
* the specified {@link java.util.Date}.
*
* @return true if any cookies were purged.
*/
boolean clearExpired(Date date);
/**
* Clears all cookies.
*/
void clear();
}

View file

@ -0,0 +1,71 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.auth.AuthScope;
import ch.boye.httpclientandroidlib.auth.Credentials;
/**
* Abstract credentials provider that maintains a collection of user
* credentials.
* <p>
* Implementations of this interface must be thread-safe. Access to shared
* data must be synchronized as methods of this interface may be executed
* from multiple threads.
*
* @since 4.0
*/
public interface CredentialsProvider {
/**
* Sets the {@link Credentials credentials} for the given authentication
* scope. Any previous credentials for the given scope will be overwritten.
*
* @param authscope the {@link AuthScope authentication scope}
* @param credentials the authentication {@link Credentials credentials}
* for the given scope.
*
* @see #getCredentials(AuthScope)
*/
void setCredentials(AuthScope authscope, Credentials credentials);
/**
* Get the {@link Credentials credentials} for the given authentication scope.
*
* @param authscope the {@link AuthScope authentication scope}
* @return the credentials
*
* @see #setCredentials(AuthScope, Credentials)
*/
Credentials getCredentials(AuthScope authscope);
/**
* Clears all credentials.
*/
void clear();
}

View file

@ -0,0 +1,258 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
import ch.boye.httpclientandroidlib.params.HttpParams;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import java.io.IOException;
/**
* This interface represents only the most basic contract for HTTP request
* execution. It imposes no restrictions or particular details on the request
* execution process and leaves the specifics of state management,
* authentication and redirect handling up to individual implementations.
*
* @since 4.0
*/
@SuppressWarnings("deprecation")
public interface HttpClient {
/**
* Obtains the parameters for this client.
* These parameters will become defaults for all requests being
* executed with this client, and for the parameters of
* dependent objects in this client.
*
* @return the default parameters
*
* @deprecated (4.3) use
* {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
*/
@Deprecated
HttpParams getParams();
/**
* Obtains the connection manager used by this client.
*
* @return the connection manager
*
* @deprecated (4.3) use
* {@link ch.boye.httpclientandroidlib.impl.client.HttpClientBuilder}.
*/
@Deprecated
ClientConnectionManager getConnectionManager();
/**
* Executes HTTP request using the default context.
*
* @param request the request to execute
*
* @return the response to the request. This is always a final response,
* never an intermediate response with an 1xx status code.
* Whether redirects or authentication challenges will be returned
* or handled automatically depends on the implementation and
* configuration of this client.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
HttpResponse execute(HttpUriRequest request)
throws IOException, ClientProtocolException;
/**
* Executes HTTP request using the given context.
*
* @param request the request to execute
* @param context the context to use for the execution, or
* <code>null</code> to use the default context
*
* @return the response to the request. This is always a final response,
* never an intermediate response with an 1xx status code.
* Whether redirects or authentication challenges will be returned
* or handled automatically depends on the implementation and
* configuration of this client.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
HttpResponse execute(HttpUriRequest request, HttpContext context)
throws IOException, ClientProtocolException;
/**
* Executes HTTP request using the default context.
*
* @param target the target host for the request.
* Implementations may accept <code>null</code>
* if they can still determine a route, for example
* to a default target or by inspecting the request.
* @param request the request to execute
*
* @return the response to the request. This is always a final response,
* never an intermediate response with an 1xx status code.
* Whether redirects or authentication challenges will be returned
* or handled automatically depends on the implementation and
* configuration of this client.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
HttpResponse execute(HttpHost target, HttpRequest request)
throws IOException, ClientProtocolException;
/**
* Executes HTTP request using the given context.
*
* @param target the target host for the request.
* Implementations may accept <code>null</code>
* if they can still determine a route, for example
* to a default target or by inspecting the request.
* @param request the request to execute
* @param context the context to use for the execution, or
* <code>null</code> to use the default context
*
* @return the response to the request. This is always a final response,
* never an intermediate response with an 1xx status code.
* Whether redirects or authentication challenges will be returned
* or handled automatically depends on the implementation and
* configuration of this client.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
HttpResponse execute(HttpHost target, HttpRequest request,
HttpContext context)
throws IOException, ClientProtocolException;
/**
* Executes HTTP request using the default context and processes the
* response using the given response handler.
* <p/>
* Implementing classes are required to ensure that the content entity
* associated with the response is fully consumed and the underlying
* connection is released back to the connection manager automatically
* in all cases relieving individual {@link ResponseHandler}s from
* having to manage resource deallocation internally.
*
* @param request the request to execute
* @param responseHandler the response handler
*
* @return the response object as generated by the response handler.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
<T> T execute(
HttpUriRequest request,
ResponseHandler<? extends T> responseHandler)
throws IOException, ClientProtocolException;
/**
* Executes HTTP request using the given context and processes the
* response using the given response handler.
* <p/>
* Implementing classes are required to ensure that the content entity
* associated with the response is fully consumed and the underlying
* connection is released back to the connection manager automatically
* in all cases relieving individual {@link ResponseHandler}s from
* having to manage resource deallocation internally.
*
* @param request the request to execute
* @param responseHandler the response handler
* @param context the context to use for the execution, or
* <code>null</code> to use the default context
*
* @return the response object as generated by the response handler.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
<T> T execute(
HttpUriRequest request,
ResponseHandler<? extends T> responseHandler,
HttpContext context)
throws IOException, ClientProtocolException;
/**
* Executes HTTP request to the target using the default context and
* processes the response using the given response handler.
* <p/>
* Implementing classes are required to ensure that the content entity
* associated with the response is fully consumed and the underlying
* connection is released back to the connection manager automatically
* in all cases relieving individual {@link ResponseHandler}s from
* having to manage resource deallocation internally.
*
* @param target the target host for the request.
* Implementations may accept <code>null</code>
* if they can still determine a route, for example
* to a default target or by inspecting the request.
* @param request the request to execute
* @param responseHandler the response handler
*
* @return the response object as generated by the response handler.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
<T> T execute(
HttpHost target,
HttpRequest request,
ResponseHandler<? extends T> responseHandler)
throws IOException, ClientProtocolException;
/**
* Executes HTTP request to the target using the given context and
* processes the response using the given response handler.
* <p/>
* Implementing classes are required to ensure that the content entity
* associated with the response is fully consumed and the underlying
* connection is released back to the connection manager automatically
* in all cases relieving individual {@link ResponseHandler}s from
* having to manage resource deallocation internally.
*
* @param target the target host for the request.
* Implementations may accept <code>null</code>
* if they can still determine a route, for example
* to a default target or by inspecting the request.
* @param request the request to execute
* @param responseHandler the response handler
* @param context the context to use for the execution, or
* <code>null</code> to use the default context
*
* @return the response object as generated by the response handler.
* @throws IOException in case of a problem or the connection was aborted
* @throws ClientProtocolException in case of an http protocol error
*/
<T> T execute(
HttpHost target,
HttpRequest request,
ResponseHandler<? extends T> responseHandler,
HttpContext context)
throws IOException, ClientProtocolException;
}

View file

@ -0,0 +1,60 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.io.IOException;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* A handler for determining if an HttpRequest should be retried after a
* recoverable exception during execution.
* <p>
* Implementations of this interface must be thread-safe. Access to shared
* data must be synchronized as methods of this interface may be executed
* from multiple threads.
*
* @since 4.0
*/
public interface HttpRequestRetryHandler {
/**
* Determines if a method should be retried after an IOException
* occurs during execution.
*
* @param exception the exception that occurred
* @param executionCount the number of times this method has been
* unsuccessfully executed
* @param context the context for the request execution
*
* @return <code>true</code> if the method should be retried, <code>false</code>
* otherwise
*/
boolean retryRequest(IOException exception, int executionCount, HttpContext context);
}

View file

@ -0,0 +1,52 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Signals a non 2xx HTTP response.
*
* @since 4.0
*/
@Immutable
public class HttpResponseException extends ClientProtocolException {
private static final long serialVersionUID = -7186627969477257933L;
private final int statusCode;
public HttpResponseException(final int statusCode, final String s) {
super(s);
this.statusCode = statusCode;
}
public int getStatusCode() {
return this.statusCode;
}
}

View file

@ -0,0 +1,72 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.ProtocolException;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Signals failure to retry the request due to non-repeatable request
* entity.
*
*
* @since 4.0
*/
@Immutable
public class NonRepeatableRequestException extends ProtocolException {
private static final long serialVersionUID = 82685265288806048L;
/**
* Creates a new NonRepeatableEntityException with a <tt>null</tt> detail message.
*/
public NonRepeatableRequestException() {
super();
}
/**
* Creates a new NonRepeatableEntityException with the specified detail message.
*
* @param message The exception detail message
*/
public NonRepeatableRequestException(final String message) {
super(message);
}
/**
* Creates a new NonRepeatableEntityException with the specified detail message.
*
* @param message The exception detail message
* @param cause the cause
*/
public NonRepeatableRequestException(final String message, final Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,69 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.ProtocolException;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Signals violation of HTTP specification caused by an invalid redirect
*
*
* @since 4.0
*/
@Immutable
public class RedirectException extends ProtocolException {
private static final long serialVersionUID = 4418824536372559326L;
/**
* Creates a new RedirectException with a <tt>null</tt> detail message.
*/
public RedirectException() {
super();
}
/**
* Creates a new RedirectException with the specified detail message.
*
* @param message The exception detail message
*/
public RedirectException(final String message) {
super(message);
}
/**
* Creates a new RedirectException with the specified detail message and cause.
*
* @param message the exception detail message
* @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
* if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
*/
public RedirectException(final String message, final Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,77 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.net.URI;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.ProtocolException;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* A handler for determining if an HTTP request should be redirected to
* a new location in response to an HTTP response received from the target
* server.
* <p>
* Implementations of this interface must be thread-safe. Access to shared
* data must be synchronized as methods of this interface may be executed
* from multiple threads.
*
* @since 4.0
*
* @deprecated (4.1) use {@link RedirectStrategy}
*/
@Deprecated
public interface RedirectHandler {
/**
* Determines if a request should be redirected to a new location
* given the response from the target server.
*
* @param response the response received from the target server
* @param context the context for the request execution
*
* @return <code>true</code> if the request should be redirected, <code>false</code>
* otherwise
*/
boolean isRedirectRequested(HttpResponse response, HttpContext context);
/**
* Determines the location request is expected to be redirected to
* given the response from the target server and the current request
* execution context.
*
* @param response the response received from the target server
* @param context the context for the request execution
*
* @return redirect URI
*/
URI getLocationURI(HttpResponse response, HttpContext context)
throws ProtocolException;
}

View file

@ -0,0 +1,81 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.ProtocolException;
import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* A strategy for determining if an HTTP request should be redirected to
* a new location in response to an HTTP response received from the target
* server.
* <p>
* Implementations of this interface must be thread-safe. Access to shared
* data must be synchronized as methods of this interface may be executed
* from multiple threads.
*
* @since 4.1
*/
public interface RedirectStrategy {
/**
* Determines if a request should be redirected to a new location
* given the response from the target server.
*
* @param request the executed request
* @param response the response received from the target server
* @param context the context for the request execution
*
* @return <code>true</code> if the request should be redirected, <code>false</code>
* otherwise
*/
boolean isRedirected(
HttpRequest request,
HttpResponse response,
HttpContext context) throws ProtocolException;
/**
* Determines the redirect location given the response from the target
* server and the current request execution context and generates a new
* request to be sent to the location.
*
* @param request the executed request
* @param response the response received from the target server
* @param context the context for the request execution
*
* @return redirected request
*/
HttpUriRequest getRedirect(
HttpRequest request,
HttpResponse response,
HttpContext context) throws ProtocolException;
}

View file

@ -0,0 +1,77 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.io.IOException;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* A client-side request director.
* The director decides which steps are necessary to execute a request.
* It establishes connections and optionally processes redirects and
* authentication challenges. The director may therefore generate and
* send a sequence of requests in order to execute one initial request.
*
* @since 4.0
*
* @deprecated (4.3) No longer used
*/
@Deprecated
public interface RequestDirector {
/**
* Executes a request.
* <br/><b>Note:</b>
* For the time being, a new director is instantiated for each request.
* This is the same behavior as for <code>HttpMethodDirector</code>
* in HttpClient 3.
*
* @param target the target host for the request.
* Implementations may accept <code>null</code>
* if they can still determine a route, for example
* to a default target or by inspecting the request.
* @param request the request to execute
* @param context the context for executing the request
*
* @return the final response to the request.
* This is never an intermediate response with status code 1xx.
*
* @throws HttpException in case of a problem
* @throws IOException in case of an IO problem
* or if the connection was aborted
*/
HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context)
throws HttpException, IOException;
}

View file

@ -0,0 +1,54 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import java.io.IOException;
import ch.boye.httpclientandroidlib.HttpResponse;
/**
* Handler that encapsulates the process of generating a response object
* from a {@link HttpResponse}.
*
*
* @since 4.0
*/
public interface ResponseHandler<T> {
/**
* Processes an {@link HttpResponse} and returns some value
* corresponding to that response.
*
* @param response The response to process
* @return A value determined by the response
*
* @throws ClientProtocolException in case of an http protocol error
* @throws IOException in case of a problem or the connection was aborted
*/
T handleResponse(HttpResponse response) throws ClientProtocolException, IOException;
}

View file

@ -0,0 +1,60 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* Strategy interface that allows API users to plug in their own logic to
* control whether or not a retry should automatically be done, how many times
* it should be retried and so on.
*
* @since 4.2
*/
public interface ServiceUnavailableRetryStrategy {
/**
* Determines if a method should be retried given the response from the target server.
*
* @param response the response from the target server
* @param executionCount the number of times this method has been
* unsuccessfully executed
* @param context the context for the request execution
* @return <code>true</code> if the method should be retried, <code>false</code>
* otherwise
*/
boolean retryRequest(HttpResponse response, int executionCount, HttpContext context);
/**
* @return The interval between the subsequent auto-retries.
*/
long getRetryInterval();
}

View file

@ -0,0 +1,58 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* A handler for determining if the given execution context is user specific
* or not. The token object returned by this handler is expected to uniquely
* identify the current user if the context is user specific or to be
* <code>null</code> if the context does not contain any resources or details
* specific to the current user.
* <p/>
* The user token will be used to ensure that user specific resources will not
* be shared with or reused by other users.
*
* @since 4.0
*/
public interface UserTokenHandler {
/**
* The token object returned by this method is expected to uniquely
* identify the current user if the context is user specific or to be
* <code>null</code> if it is not.
*
* @param context the execution context
*
* @return user token that uniquely identifies the user or
* <code>null</null> if the context is not user specific.
*/
Object getUserToken(HttpContext context);
}

View file

@ -0,0 +1,55 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
/**
* This enumeration represents the various ways a response can be generated
* by the {@link ch.boye.httpclientandroidlib.impl.client.cache.CachingHttpClient};
* if a request is executed with an {@link ch.boye.httpclientandroidlib.protocol.HttpContext}
* then a parameter with one of these values will be registered in the
* context under the key
* {@link ch.boye.httpclientandroidlib.impl.client.cache.CachingHttpClient#CACHE_RESPONSE_STATUS}.
*/
public enum CacheResponseStatus {
/** The response was generated directly by the caching module. */
CACHE_MODULE_RESPONSE,
/** A response was generated from the cache with no requests sent
* upstream.
*/
CACHE_HIT,
/** The response came from an upstream server. */
CACHE_MISS,
/** The response was generated from the cache after validating the
* entry with the origin server.
*/
VALIDATED;
}

View file

@ -0,0 +1,81 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Records static constants for various HTTP header names.
* @since 4.1
*/
@Immutable
public class HeaderConstants {
public static final String GET_METHOD = "GET";
public static final String HEAD_METHOD = "HEAD";
public static final String OPTIONS_METHOD = "OPTIONS";
public static final String PUT_METHOD = "PUT";
public static final String DELETE_METHOD = "DELETE";
public static final String TRACE_METHOD = "TRACE";
public static final String LAST_MODIFIED = "Last-Modified";
public static final String IF_MATCH = "If-Match";
public static final String IF_RANGE = "If-Range";
public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
public static final String IF_NONE_MATCH = "If-None-Match";
public static final String PRAGMA = "Pragma";
public static final String MAX_FORWARDS = "Max-Forwards";
public static final String ETAG = "ETag";
public static final String EXPIRES = "Expires";
public static final String AGE = "Age";
public static final String VARY = "Vary";
public static final String ALLOW = "Allow";
public static final String VIA = "Via";
public static final String PUBLIC = "public";
public static final String PRIVATE = "private";
public static final String CACHE_CONTROL = "Cache-Control";
public static final String CACHE_CONTROL_NO_STORE = "no-store";
public static final String CACHE_CONTROL_NO_CACHE = "no-cache";
public static final String CACHE_CONTROL_MAX_AGE = "max-age";
public static final String CACHE_CONTROL_MAX_STALE = "max-stale";
public static final String CACHE_CONTROL_MIN_FRESH = "min-fresh";
public static final String CACHE_CONTROL_MUST_REVALIDATE = "must-revalidate";
public static final String CACHE_CONTROL_PROXY_REVALIDATE = "proxy-revalidate";
public static final String STALE_IF_ERROR = "stale-if-error";
public static final String STALE_WHILE_REVALIDATE = "stale-while-revalidate";
public static final String WARNING = "Warning";
public static final String RANGE = "Range";
public static final String CONTENT_RANGE = "Content-Range";
public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
public static final String AUTHORIZATION = "Authorization";
}

View file

@ -0,0 +1,71 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* @since 4.3
*/
@NotThreadSafe
public class HttpCacheContext extends HttpClientContext {
/**
* This is the name under which the {@link CacheResponseStatus} of a request
* (for example, whether it resulted in a cache hit) will be recorded if an
* {@link HttpContext} is provided during execution.
*/
public static final String CACHE_RESPONSE_STATUS = "http.cache.response.status";
public static HttpCacheContext adapt(final HttpContext context) {
if (context instanceof HttpCacheContext) {
return (HttpCacheContext) context;
} else {
return new HttpCacheContext(context);
}
}
public static HttpCacheContext create() {
return new HttpCacheContext(new BasicHttpContext());
}
public HttpCacheContext(final HttpContext context) {
super(context);
}
public HttpCacheContext() {
super();
}
public CacheResponseStatus getCacheResponseStatus() {
return getAttribute(CACHE_RESPONSE_STATUS, CacheResponseStatus.class);
}
}

View file

@ -0,0 +1,263 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import java.io.Serializable;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.ProtocolVersion;
import ch.boye.httpclientandroidlib.StatusLine;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.client.utils.DateUtils;
import ch.boye.httpclientandroidlib.message.HeaderGroup;
import ch.boye.httpclientandroidlib.protocol.HTTP;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Structure used to store an {@link ch.boye.httpclientandroidlib.HttpResponse} in a cache.
* Some entries can optionally depend on system resources that may require
* explicit deallocation. In such a case {@link #getResource()} should return
* a non null instance of {@link Resource} that must be deallocated by calling
* {@link Resource#dispose()} method when no longer used.
*
* @since 4.1
*/
@Immutable
public class HttpCacheEntry implements Serializable {
private static final long serialVersionUID = -6300496422359477413L;
private final Date requestDate;
private final Date responseDate;
private final StatusLine statusLine;
private final HeaderGroup responseHeaders;
private final Resource resource;
private final Map<String,String> variantMap;
private final Date date;
/**
* Create a new {@link HttpCacheEntry} with variants.
* @param requestDate
* Date/time when the request was made (Used for age
* calculations)
* @param responseDate
* Date/time that the response came back (Used for age
* calculations)
* @param statusLine
* HTTP status line from origin response
* @param responseHeaders
* Header[] from original HTTP Response
* @param resource representing origin response body
* @param variantMap describing cache entries that are variants
* of this parent entry; this maps a "variant key" (derived
* from the varying request headers) to a "cache key" (where
* in the cache storage the particular variant is located)
*/
public HttpCacheEntry(
final Date requestDate,
final Date responseDate,
final StatusLine statusLine,
final Header[] responseHeaders,
final Resource resource,
final Map<String,String> variantMap) {
super();
Args.notNull(requestDate, "Request date");
Args.notNull(responseDate, "Response date");
Args.notNull(statusLine, "Status line");
Args.notNull(responseHeaders, "Response headers");
this.requestDate = requestDate;
this.responseDate = responseDate;
this.statusLine = statusLine;
this.responseHeaders = new HeaderGroup();
this.responseHeaders.setHeaders(responseHeaders);
this.resource = resource;
this.variantMap = variantMap != null
? new HashMap<String,String>(variantMap)
: null;
this.date = parseDate();
}
/**
* Create a new {@link HttpCacheEntry}.
*
* @param requestDate
* Date/time when the request was made (Used for age
* calculations)
* @param responseDate
* Date/time that the response came back (Used for age
* calculations)
* @param statusLine
* HTTP status line from origin response
* @param responseHeaders
* Header[] from original HTTP Response
* @param resource representing origin response body
*/
public HttpCacheEntry(final Date requestDate, final Date responseDate, final StatusLine statusLine,
final Header[] responseHeaders, final Resource resource) {
this(requestDate, responseDate, statusLine, responseHeaders, resource,
new HashMap<String,String>());
}
/**
* Find the "Date" response header and parse it into a java.util.Date
* @return the Date value of the header or null if the header is not present
*/
private Date parseDate() {
final Header dateHdr = getFirstHeader(HTTP.DATE_HEADER);
if (dateHdr == null) {
return null;
}
return DateUtils.parseDate(dateHdr.getValue());
}
/**
* Returns the {@link StatusLine} from the origin
* {@link ch.boye.httpclientandroidlib.HttpResponse}.
*/
public StatusLine getStatusLine() {
return this.statusLine;
}
/**
* Returns the {@link ProtocolVersion} from the origin
* {@link ch.boye.httpclientandroidlib.HttpResponse}.
*/
public ProtocolVersion getProtocolVersion() {
return this.statusLine.getProtocolVersion();
}
/**
* Gets the reason phrase from the origin
* {@link ch.boye.httpclientandroidlib.HttpResponse}, for example, "Not Modified".
*/
public String getReasonPhrase() {
return this.statusLine.getReasonPhrase();
}
/**
* Returns the HTTP response code from the origin
* {@link ch.boye.httpclientandroidlib.HttpResponse}.
*/
public int getStatusCode() {
return this.statusLine.getStatusCode();
}
/**
* Returns the time the associated origin request was initiated by the
* caching module.
* @return {@link Date}
*/
public Date getRequestDate() {
return requestDate;
}
/**
* Returns the time the origin response was received by the caching module.
* @return {@link Date}
*/
public Date getResponseDate() {
return responseDate;
}
/**
* Returns all the headers that were on the origin response.
*/
public Header[] getAllHeaders() {
return responseHeaders.getAllHeaders();
}
/**
* Returns the first header from the origin response with the given
* name.
*/
public Header getFirstHeader(final String name) {
return responseHeaders.getFirstHeader(name);
}
/**
* Gets all the headers with the given name that were on the origin
* response.
*/
public Header[] getHeaders(final String name) {
return responseHeaders.getHeaders(name);
}
/**
* Gets the Date value of the "Date" header or null if the header is missing or cannot be
* parsed.
*
* @since 4.3
*/
public Date getDate() {
return date;
}
/**
* Returns the {@link Resource} containing the origin response body.
*/
public Resource getResource() {
return this.resource;
}
/**
* Indicates whether the origin response indicated the associated
* resource had variants (i.e. that the Vary header was set on the
* origin response).
* @return {@code true} if this cached response was a variant
*/
public boolean hasVariants() {
return getFirstHeader(HeaderConstants.VARY) != null;
}
/**
* Returns an index about where in the cache different variants for
* a given resource are stored. This maps "variant keys" to "cache keys",
* where the variant key is derived from the varying request headers,
* and the cache key is the location in the
* {@link ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage} where that
* particular variant is stored. The first variant returned is used as
* the "parent" entry to hold this index of the other variants.
*/
public Map<String, String> getVariantMap() {
return Collections.unmodifiableMap(variantMap);
}
/**
* Provides a string representation of this instance suitable for
* human consumption.
*/
@Override
public String toString() {
return "[request date=" + this.requestDate + "; response date=" + this.responseDate
+ "; statusLine=" + this.statusLine + "]";
}
}

View file

@ -0,0 +1,48 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import java.io.IOException;
/**
* Thrown if serialization or deserialization of an {@link HttpCacheEntry}
* fails.
*/
public class HttpCacheEntrySerializationException extends IOException {
private static final long serialVersionUID = 9219188365878433519L;
public HttpCacheEntrySerializationException(final String message) {
super();
}
public HttpCacheEntrySerializationException(final String message, final Throwable cause) {
super(message);
initCause(cause);
}
}

View file

@ -0,0 +1,54 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Used by some {@link HttpCacheStorage} implementations to serialize
* {@link HttpCacheEntry} instances to a byte representation before
* storage.
*/
public interface HttpCacheEntrySerializer {
/**
* Serializes the given entry to a byte representation on the
* given {@link OutputStream}.
* @throws IOException
*/
void writeTo(HttpCacheEntry entry, OutputStream os) throws IOException;
/**
* Deserializes a byte representation of a cache entry by reading
* from the given {@link InputStream}.
* @throws IOException
*/
HttpCacheEntry readFrom(InputStream is) throws IOException;
}

View file

@ -0,0 +1,58 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpResponse;
/**
* Given a particular HttpRequest, flush any cache entries that this request
* would invalidate.
*
* @since 4.3
*/
public interface HttpCacheInvalidator {
/**
* Remove cache entries from the cache that are no longer fresh or have been
* invalidated in some way.
*
* @param host
* The backend host we are talking to
* @param req
* The HttpRequest to that host
*/
void flushInvalidatedCacheEntries(HttpHost host, HttpRequest req);
/**
* Flushes entries that were invalidated by the given response received for
* the given host/request pair.
*/
void flushInvalidatedCacheEntries(HttpHost host, HttpRequest request, HttpResponse response);
}

View file

@ -0,0 +1,81 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import java.io.IOException;
/**
* New storage backends should implement this {@link HttpCacheStorage}
* interface. They can then be plugged into the existing
* {@link ch.boye.httpclientandroidlib.impl.client.cache.CachingHttpClient}
* implementation.
*
* @since 4.1
*/
public interface HttpCacheStorage {
/**
* Store a given cache entry under the given key.
* @param key where in the cache to store the entry
* @param entry cached response to store
* @throws IOException
*/
void putEntry(String key, HttpCacheEntry entry) throws IOException;
/**
* Retrieves the cache entry stored under the given key
* or null if no entry exists under that key.
* @param key cache key
* @return an {@link HttpCacheEntry} or {@code null} if no
* entry exists
* @throws IOException
*/
HttpCacheEntry getEntry(String key) throws IOException;
/**
* Deletes/invalidates/removes any cache entries currently
* stored under the given key.
* @param key
* @throws IOException
*/
void removeEntry(String key) throws IOException;
/**
* Atomically applies the given callback to update an existing cache
* entry under a given key.
* @param key indicates which entry to modify
* @param callback performs the update; see
* {@link HttpCacheUpdateCallback} for details, but roughly the
* callback expects to be handed the current entry and will return
* the new value for the entry.
* @throws IOException
* @throws HttpCacheUpdateException
*/
void updateEntry(
String key, HttpCacheUpdateCallback callback) throws IOException, HttpCacheUpdateException;
}

View file

@ -0,0 +1,52 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import java.io.IOException;
/**
* Used for atomically updating entries in a {@link HttpCacheStorage}
* implementation. The current entry (if any) is fed into an implementation
* of this interface, and the new, possibly updated entry (if any)
* should be returned.
*/
public interface HttpCacheUpdateCallback {
/**
* Returns the new cache entry that should replace an existing one.
*
* @param existing
* the cache entry currently in-place in the cache, possibly
* <code>null</code> if nonexistent
* @return the cache entry that should replace it, again,
* possibly <code>null</code> if the entry should be deleted
*
* @since 4.1
*/
HttpCacheEntry update(HttpCacheEntry existing) throws IOException;
}

View file

@ -0,0 +1,48 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
/**
* Signals that {@link HttpCacheStorage} encountered an error performing an
* update operation.
*
* @since 4.1
*/
public class HttpCacheUpdateException extends Exception {
private static final long serialVersionUID = 823573584868632876L;
public HttpCacheUpdateException(final String message) {
super(message);
}
public HttpCacheUpdateException(final String message, final Throwable cause) {
super(message);
initCause(cause);
}
}

View file

@ -0,0 +1,76 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* Used to limiting the size of an incoming response body of
* unknown size that is optimistically being read in anticipation
* of caching it.
* @since 4.1
*/
@NotThreadSafe // reached
public class InputLimit {
private final long value;
private boolean reached;
/**
* Create a limit for how many bytes of a response body to
* read.
* @param value maximum length in bytes
*/
public InputLimit(final long value) {
super();
this.value = value;
this.reached = false;
}
/**
* Returns the current maximum limit that was set on
* creation.
*/
public long getValue() {
return this.value;
}
/**
* Used to report that the limit has been reached.
*/
public void reached() {
this.reached = true;
}
/**
* Returns {@code true} if the input limit has been reached.
*/
public boolean isReached() {
return this.reached;
}
}

View file

@ -0,0 +1,60 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
/**
* Represents a disposable system resource used for handling
* cached response bodies.
*
* @since 4.1
*/
public interface Resource extends Serializable {
/**
* Returns an {@link InputStream} from which the response
* body can be read.
* @throws IOException
*/
InputStream getInputStream() throws IOException;
/**
* Returns the length in bytes of the response body.
*/
long length();
/**
* Indicates the system no longer needs to keep this
* response body and any system resources associated with
* it may be reclaimed.
*/
void dispose();
}

View file

@ -0,0 +1,67 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.cache;
import java.io.IOException;
import java.io.InputStream;
/**
* Generates {@link Resource} instances for handling cached
* HTTP response bodies.
*
* @since 4.1
*/
public interface ResourceFactory {
/**
* Creates a {@link Resource} from a given response body.
* @param requestId a unique identifier for this particular
* response body
* @param instream the original {@link InputStream}
* containing the response body of the origin HTTP response.
* @param limit maximum number of bytes to consume of the
* response body; if this limit is reached before the
* response body is fully consumed, mark the limit has
* having been reached and return a {@code Resource}
* containing the data read to that point.
* @return a {@code Resource} containing however much of
* the response body was successfully read.
* @throws IOException
*/
Resource generate(String requestId, InputStream instream, InputLimit limit) throws IOException;
/**
* Clones an existing {@link Resource}.
* @param requestId unique identifier provided to associate
* with the cloned response body.
* @param resource the original response body to clone.
* @return the {@code Resource} copy
* @throws IOException
*/
Resource copy(String requestId, Resource resource) throws IOException;
}

View file

@ -0,0 +1,78 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<!--
====================================================================
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.
====================================================================
This software consists of voluntary contributions made by many
individuals on behalf of the Apache Software Foundation. For more
information on the Apache Software Foundation, please see
<http://www.apache.org/>.
-->
</head>
<body bgcolor="white">
<p>
This package consists largely of constants and interfaces that are
necessary for building new storage backends for the
{@link org.apache.http.impl.client.cache.CachingHttpClient} or for
those clients wanting to get a little more behavioral information
out of the cache module (for example, whether a particular response
was a cache hit or not). Developers that simply want to instantiate
and make use of the caching module will be better off looking at
the {@code CachingHttpClient} documentation itself.
</p>
<p>
The classes in this package can be divided into two main groups:
reference constants and interfaces needed for storage backends. In
the former group,
{@link org.apache.http.client.cache.HeaderConstants} contains a list
of HTTP header names encoded as static fields, and the
{@link org.apache.http.client.cache.CacheResponseStatus} enumeration
values are set in an {@link org.apache.http.protocol.HttpContext} by
the {@code CachingHttpClient} to indicate how the request was
processed by the caching module itself.
</p>
<p>
New storage backends will need to implement the
{@link org.apache.http.client.cache.HttpCacheStorage}
interface; they can then be passed to one of the {@code CachingHttpClient}
constructors, which will happily make use of the new storage mechanism.
The {@link org.apache.http.client.cache.HttpCacheEntry} class shows the
datastructure for a cache entry that must be stored by the
{@code HttpCacheStorage}.
There is, in addition, the notion of a
{@link org.apache.http.client.cache.Resource} and an associated
{@link org.apache.http.client.cache.ResourceFactory}, which are used for
managing the handling of cached response bodies. The default implementation
used by the {@code CachingHttpClient} stores response bodies in memory;
alternative implementations might involve storing these in a filesystem. A new
{@code ResourceFactory} can be provided along with a {@code HttpCacheStorage}
in one of the constructors to the {@code CachingHttpClient}. Finally, some
of the additional storage backends we provide, like the
{@link org.apache.http.impl.client.cache.ehcache.EhcacheHttpCacheStorage} and
{@link org.apache.http.impl.client.cache.memcached.MemcachedHttpCacheStorage},
can be provided with different serializers for the cache entry metadata;
developers wanting to experiment with different serialization techniques
should implement the
{@link org.apache.http.client.cache.HttpCacheEntrySerializer} interface.
</p>
</body>
</html>

View file

@ -0,0 +1,71 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.config;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Standard authentication schemes supported by HttpClient.
*
* @since 4.3
*/
@Immutable
public final class AuthSchemes {
/**
* Basic authentication scheme as defined in RFC2617 (considered inherently
* insecure, but most widely supported)
*/
public static final String BASIC = "Basic";
/**
* Digest authentication scheme as defined in RFC2617.
*/
public static final String DIGEST = "Digest";
/**
* The NTLM scheme is a proprietary Microsoft Windows Authentication
* protocol (considered to be the most secure among currently supported
* authentication schemes).
*/
public static final String NTLM = "NTLM";
/**
* SPNEGO Authentication scheme.
*/
public static final String SPNEGO = "negotiate";
/**
* Kerberos Authentication scheme.
*/
public static final String KERBEROS = "Kerberos";
private AuthSchemes() {
}
}

View file

@ -0,0 +1,69 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.config;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Standard cookie specifications supported by HttpClient.
*
* @since 4.3
*/
@Immutable
public final class CookieSpecs {
/**
* The policy that provides high degree of compatibility
* with common cookie management of popular HTTP agents.
*/
public static final String BROWSER_COMPATIBILITY = "compatibility";
/**
* The Netscape cookie draft compliant policy.
*/
public static final String NETSCAPE = "netscape";
/**
* The RFC 2965 compliant policy (standard).
*/
public static final String STANDARD = "standard";
/**
* The default 'best match' policy.
*/
public static final String BEST_MATCH = "best-match";
/**
* The policy that ignores cookies.
*/
public static final String IGNORE_COOKIES = "ignoreCookies";
private CookieSpecs() {
}
}

View file

@ -0,0 +1,442 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.config;
import java.net.InetAddress;
import java.util.Collection;
import ch.boye.httpclientandroidlib.HttpHost;
public class RequestConfig implements Cloneable {
public static final RequestConfig DEFAULT = new Builder().build();
private final boolean expectContinueEnabled;
private final HttpHost proxy;
private final InetAddress localAddress;
private final boolean staleConnectionCheckEnabled;
private final String cookieSpec;
private final boolean redirectsEnabled;
private final boolean relativeRedirectsAllowed;
private final boolean circularRedirectsAllowed;
private final int maxRedirects;
private final boolean authenticationEnabled;
private final Collection<String> targetPreferredAuthSchemes;
private final Collection<String> proxyPreferredAuthSchemes;
private final int connectionRequestTimeout;
private final int connectTimeout;
private final int socketTimeout;
RequestConfig(
final boolean expectContinueEnabled,
final HttpHost proxy,
final InetAddress localAddress,
final boolean staleConnectionCheckEnabled,
final String cookieSpec,
final boolean redirectsEnabled,
final boolean relativeRedirectsAllowed,
final boolean circularRedirectsAllowed,
final int maxRedirects,
final boolean authenticationEnabled,
final Collection<String> targetPreferredAuthSchemes,
final Collection<String> proxyPreferredAuthSchemes,
final int connectionRequestTimeout,
final int connectTimeout,
final int socketTimeout) {
super();
this.expectContinueEnabled = expectContinueEnabled;
this.proxy = proxy;
this.localAddress = localAddress;
this.staleConnectionCheckEnabled = staleConnectionCheckEnabled;
this.cookieSpec = cookieSpec;
this.redirectsEnabled = redirectsEnabled;
this.relativeRedirectsAllowed = relativeRedirectsAllowed;
this.circularRedirectsAllowed = circularRedirectsAllowed;
this.maxRedirects = maxRedirects;
this.authenticationEnabled = authenticationEnabled;
this.targetPreferredAuthSchemes = targetPreferredAuthSchemes;
this.proxyPreferredAuthSchemes = proxyPreferredAuthSchemes;
this.connectionRequestTimeout = connectionRequestTimeout;
this.connectTimeout = connectTimeout;
this.socketTimeout = socketTimeout;
}
/**
* Determines whether the 'Expect: 100-Continue' handshake is enabled
* for entity enclosing methods. The purpose of the 'Expect: 100-Continue'
* handshake is to allow a client that is sending a request message with
* a request body to determine if the origin server is willing to
* accept the request (based on the request headers) before the client
* sends the request body.
* <p/>
* The use of the 'Expect: 100-continue' handshake can result in
* a noticeable performance improvement for entity enclosing requests
* (such as POST and PUT) that require the target server's
* authentication.
* <p/>
* 'Expect: 100-continue' handshake should be used with caution, as it
* may cause problems with HTTP servers and proxies that do not support
* HTTP/1.1 protocol.
* <p/>
* Default: <code>false</code>
*/
public boolean isExpectContinueEnabled() {
return expectContinueEnabled;
}
/**
* Returns HTTP proxy to be used for request execution.
* <p/>
* Default: <code>null</code>
*/
public HttpHost getProxy() {
return proxy;
}
/**
* Returns local address to be used for request execution.
* <p/>
* On machines with multiple network interfaces, this parameter
* can be used to select the network interface from which the
* connection originates.
* <p/>
* Default: <code>null</code>
*/
public InetAddress getLocalAddress() {
return localAddress;
}
/**
* Determines whether stale connection check is to be used. The stale
* connection check can cause up to 30 millisecond overhead per request and
* should be used only when appropriate. For performance critical
* operations this check should be disabled.
* <p/>
* Default: <code>true</code>
*/
public boolean isStaleConnectionCheckEnabled() {
return staleConnectionCheckEnabled;
}
/**
* Determines the name of the cookie specification to be used for HTTP state
* management.
* <p/>
* Default: <code>null</code>
*/
public String getCookieSpec() {
return cookieSpec;
}
/**
* Determines whether redirects should be handled automatically.
* <p/>
* Default: <code>true</code>
*/
public boolean isRedirectsEnabled() {
return redirectsEnabled;
}
/**
* Determines whether relative redirects should be rejected. HTTP specification
* requires the location value be an absolute URI.
* <p/>
* Default: <code>true</code>
*/
public boolean isRelativeRedirectsAllowed() {
return relativeRedirectsAllowed;
}
/**
* Determines whether circular redirects (redirects to the same location) should
* be allowed. The HTTP spec is not sufficiently clear whether circular redirects
* are permitted, therefore optionally they can be enabled
* <p/>
* Default: <code>false</code>
*/
public boolean isCircularRedirectsAllowed() {
return circularRedirectsAllowed;
}
/**
* Returns the maximum number of redirects to be followed. The limit on number
* of redirects is intended to prevent infinite loops.
* <p/>
* Default: <code>50</code>
*/
public int getMaxRedirects() {
return maxRedirects;
}
/**
* Determines whether authentication should be handled automatically.
* <p/>
* Default: <code>true</code>
*/
public boolean isAuthenticationEnabled() {
return authenticationEnabled;
}
/**
* Determines the order of preference for supported authentication schemes
* when authenticating with the target host.
* <p/>
* Default: <code>null</code>
*/
public Collection<String> getTargetPreferredAuthSchemes() {
return targetPreferredAuthSchemes;
}
/**
* Determines the order of preference for supported authentication schemes
* when authenticating with the proxy host.
* <p/>
* Default: <code>null</code>
*/
public Collection<String> getProxyPreferredAuthSchemes() {
return proxyPreferredAuthSchemes;
}
/**
* Returns the timeout in milliseconds used when requesting a connection
* from the connection manager. A timeout value of zero is interpreted
* as an infinite timeout.
* <p/>
* A timeout value of zero is interpreted as an infinite timeout.
* A negative value is interpreted as undefined (system default).
* <p/>
* Default: <code>-1</code>
*/
public int getConnectionRequestTimeout() {
return connectionRequestTimeout;
}
/**
* Determines the timeout in milliseconds until a connection is established.
* A timeout value of zero is interpreted as an infinite timeout.
* <p/>
* A timeout value of zero is interpreted as an infinite timeout.
* A negative value is interpreted as undefined (system default).
* <p/>
* Default: <code>-1</code>
*/
public int getConnectTimeout() {
return connectTimeout;
}
/**
* Defines the socket timeout (<code>SO_TIMEOUT</code>) in milliseconds,
* which is the timeout for waiting for data or, put differently,
* a maximum period inactivity between two consecutive data packets).
* <p/>
* A timeout value of zero is interpreted as an infinite timeout.
* A negative value is interpreted as undefined (system default).
* <p/>
* Default: <code>-1</code>
*/
public int getSocketTimeout() {
return socketTimeout;
}
@Override
protected RequestConfig clone() throws CloneNotSupportedException {
return (RequestConfig) super.clone();
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(", expectContinueEnabled=").append(expectContinueEnabled);
builder.append(", proxy=").append(proxy);
builder.append(", localAddress=").append(localAddress);
builder.append(", staleConnectionCheckEnabled=").append(staleConnectionCheckEnabled);
builder.append(", cookieSpec=").append(cookieSpec);
builder.append(", redirectsEnabled=").append(redirectsEnabled);
builder.append(", relativeRedirectsAllowed=").append(relativeRedirectsAllowed);
builder.append(", maxRedirects=").append(maxRedirects);
builder.append(", circularRedirectsAllowed=").append(circularRedirectsAllowed);
builder.append(", authenticationEnabled=").append(authenticationEnabled);
builder.append(", targetPreferredAuthSchemes=").append(targetPreferredAuthSchemes);
builder.append(", proxyPreferredAuthSchemes=").append(proxyPreferredAuthSchemes);
builder.append(", connectionRequestTimeout=").append(connectionRequestTimeout);
builder.append(", connectTimeout=").append(connectTimeout);
builder.append(", socketTimeout=").append(socketTimeout);
builder.append("]");
return builder.toString();
}
public static RequestConfig.Builder custom() {
return new Builder();
}
public static RequestConfig.Builder copy(final RequestConfig config) {
return new Builder()
.setExpectContinueEnabled(config.isExpectContinueEnabled())
.setProxy(config.getProxy())
.setLocalAddress(config.getLocalAddress())
.setStaleConnectionCheckEnabled(config.isStaleConnectionCheckEnabled())
.setCookieSpec(config.getCookieSpec())
.setRedirectsEnabled(config.isRedirectsEnabled())
.setRelativeRedirectsAllowed(config.isRelativeRedirectsAllowed())
.setCircularRedirectsAllowed(config.isCircularRedirectsAllowed())
.setMaxRedirects(config.getMaxRedirects())
.setAuthenticationEnabled(config.isAuthenticationEnabled())
.setTargetPreferredAuthSchemes(config.getTargetPreferredAuthSchemes())
.setProxyPreferredAuthSchemes(config.getProxyPreferredAuthSchemes())
.setConnectionRequestTimeout(config.getConnectionRequestTimeout())
.setConnectTimeout(config.getConnectTimeout())
.setSocketTimeout(config.getSocketTimeout());
}
public static class Builder {
private boolean expectContinueEnabled;
private HttpHost proxy;
private InetAddress localAddress;
private boolean staleConnectionCheckEnabled;
private String cookieSpec;
private boolean redirectsEnabled;
private boolean relativeRedirectsAllowed;
private boolean circularRedirectsAllowed;
private int maxRedirects;
private boolean authenticationEnabled;
private Collection<String> targetPreferredAuthSchemes;
private Collection<String> proxyPreferredAuthSchemes;
private int connectionRequestTimeout;
private int connectTimeout;
private int socketTimeout;
Builder() {
super();
this.staleConnectionCheckEnabled = true;
this.redirectsEnabled = true;
this.maxRedirects = 50;
this.relativeRedirectsAllowed = true;
this.authenticationEnabled = true;
this.connectionRequestTimeout = -1;
this.connectTimeout = -1;
this.socketTimeout = -1;
}
public Builder setExpectContinueEnabled(final boolean expectContinueEnabled) {
this.expectContinueEnabled = expectContinueEnabled;
return this;
}
public Builder setProxy(final HttpHost proxy) {
this.proxy = proxy;
return this;
}
public Builder setLocalAddress(final InetAddress localAddress) {
this.localAddress = localAddress;
return this;
}
public Builder setStaleConnectionCheckEnabled(final boolean staleConnectionCheckEnabled) {
this.staleConnectionCheckEnabled = staleConnectionCheckEnabled;
return this;
}
public Builder setCookieSpec(final String cookieSpec) {
this.cookieSpec = cookieSpec;
return this;
}
public Builder setRedirectsEnabled(final boolean redirectsEnabled) {
this.redirectsEnabled = redirectsEnabled;
return this;
}
public Builder setRelativeRedirectsAllowed(final boolean relativeRedirectsAllowed) {
this.relativeRedirectsAllowed = relativeRedirectsAllowed;
return this;
}
public Builder setCircularRedirectsAllowed(final boolean circularRedirectsAllowed) {
this.circularRedirectsAllowed = circularRedirectsAllowed;
return this;
}
public Builder setMaxRedirects(final int maxRedirects) {
this.maxRedirects = maxRedirects;
return this;
}
public Builder setAuthenticationEnabled(final boolean authenticationEnabled) {
this.authenticationEnabled = authenticationEnabled;
return this;
}
public Builder setTargetPreferredAuthSchemes(final Collection<String> targetPreferredAuthSchemes) {
this.targetPreferredAuthSchemes = targetPreferredAuthSchemes;
return this;
}
public Builder setProxyPreferredAuthSchemes(final Collection<String> proxyPreferredAuthSchemes) {
this.proxyPreferredAuthSchemes = proxyPreferredAuthSchemes;
return this;
}
public Builder setConnectionRequestTimeout(final int connectionRequestTimeout) {
this.connectionRequestTimeout = connectionRequestTimeout;
return this;
}
public Builder setConnectTimeout(final int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}
public Builder setSocketTimeout(final int socketTimeout) {
this.socketTimeout = socketTimeout;
return this;
}
public RequestConfig build() {
return new RequestConfig(
expectContinueEnabled,
proxy,
localAddress,
staleConnectionCheckEnabled,
cookieSpec,
redirectsEnabled,
relativeRedirectsAllowed,
circularRedirectsAllowed,
maxRedirects,
authenticationEnabled,
targetPreferredAuthSchemes,
proxyPreferredAuthSchemes,
connectionRequestTimeout,
connectTimeout,
socketTimeout);
}
}
}

View file

@ -0,0 +1,31 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
/**
* Client configuration APIs.
*/
package ch.boye.httpclientandroidlib.client.config;

View file

@ -0,0 +1,105 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Common base class for decompressing {@link HttpEntity} implementations.
*
* @since 4.1
*/
abstract class DecompressingEntity extends HttpEntityWrapper {
/**
* Default buffer size.
*/
private static final int BUFFER_SIZE = 1024 * 2;
/**
* {@link #getContent()} method must return the same {@link InputStream}
* instance when DecompressingEntity is wrapping a streaming entity.
*/
private InputStream content;
/**
* Creates a new {@link DecompressingEntity}.
*
* @param wrapped
* the non-null {@link HttpEntity} to be wrapped
*/
public DecompressingEntity(final HttpEntity wrapped) {
super(wrapped);
}
abstract InputStream decorate(final InputStream wrapped) throws IOException;
private InputStream getDecompressingStream() throws IOException {
final InputStream in = wrappedEntity.getContent();
return new LazyDecompressingInputStream(in, this);
}
/**
* {@inheritDoc}
*/
@Override
public InputStream getContent() throws IOException {
if (wrappedEntity.isStreaming()) {
if (content == null) {
content = getDecompressingStream();
}
return content;
} else {
return getDecompressingStream();
}
}
/**
* {@inheritDoc}
*/
@Override
public void writeTo(final OutputStream outstream) throws IOException {
Args.notNull(outstream, "Output stream");
final InputStream instream = getContent();
try {
final byte[] buffer = new byte[BUFFER_SIZE];
int l;
while ((l = instream.read(buffer)) != -1) {
outstream.write(buffer, 0, l);
}
} finally {
instream.close();
}
}
}

View file

@ -0,0 +1,96 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
import java.io.IOException;
import java.io.InputStream;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
/**
* {@link ch.boye.httpclientandroidlib.entity.HttpEntityWrapper} responsible for handling
* deflate Content Coded responses. In RFC2616 terms, <code>deflate</code>
* means a <code>zlib</code> stream as defined in RFC1950. Some server
* implementations have misinterpreted RFC2616 to mean that a
* <code>deflate</code> stream as defined in RFC1951 should be used
* (or maybe they did that since that's how IE behaves?). It's confusing
* that <code>deflate</code> in HTTP 1.1 means <code>zlib</code> streams
* rather than <code>deflate</code> streams. We handle both types in here,
* since that's what is seen on the internet. Moral - prefer
* <code>gzip</code>!
*
* @see GzipDecompressingEntity
*
* @since 4.1
*/
public class DeflateDecompressingEntity extends DecompressingEntity {
/**
* Creates a new {@link DeflateDecompressingEntity} which will wrap the specified
* {@link HttpEntity}.
*
* @param entity
* a non-null {@link HttpEntity} to be wrapped
*/
public DeflateDecompressingEntity(final HttpEntity entity) {
super(entity);
}
/**
* Returns the non-null InputStream that should be returned to by all requests to
* {@link #getContent()}.
*
* @return a non-null InputStream
* @throws IOException if there was a problem
*/
@Override
InputStream decorate(final InputStream wrapped) throws IOException {
return new DeflateInputStream(wrapped);
}
/**
* {@inheritDoc}
*/
@Override
public Header getContentEncoding() {
/* This HttpEntityWrapper has dealt with the Content-Encoding. */
return null;
}
/**
* {@inheritDoc}
*/
@Override
public long getContentLength() {
/* Length of inflated content is unknown. */
return -1;
}
}

View file

@ -0,0 +1,228 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
/** Deflate input stream. This class includes logic needed for various Rfc's in order
* to reasonably implement the "deflate" compression style.
*/
public class DeflateInputStream extends InputStream
{
private InputStream sourceStream;
public DeflateInputStream(final InputStream wrapped)
throws IOException
{
/*
* A zlib stream will have a header.
*
* CMF | FLG [| DICTID ] | ...compressed data | ADLER32 |
*
* * CMF is one byte.
*
* * FLG is one byte.
*
* * DICTID is four bytes, and only present if FLG.FDICT is set.
*
* Sniff the content. Does it look like a zlib stream, with a CMF, etc? c.f. RFC1950,
* section 2.2. http://tools.ietf.org/html/rfc1950#page-4
*
* We need to see if it looks like a proper zlib stream, or whether it is just a deflate
* stream. RFC2616 calls zlib streams deflate. Confusing, isn't it? That's why some servers
* implement deflate Content-Encoding using deflate streams, rather than zlib streams.
*
* We could start looking at the bytes, but to be honest, someone else has already read
* the RFCs and implemented that for us. So we'll just use the JDK libraries and exception
* handling to do this. If that proves slow, then we could potentially change this to check
* the first byte - does it look like a CMF? What about the second byte - does it look like
* a FLG, etc.
*/
/* We read a small buffer to sniff the content. */
final byte[] peeked = new byte[6];
final PushbackInputStream pushback = new PushbackInputStream(wrapped, peeked.length);
final int headerLength = pushback.read(peeked);
if (headerLength == -1) {
throw new IOException("Unable to read the response");
}
/* We try to read the first uncompressed byte. */
final byte[] dummy = new byte[1];
final Inflater inf = new Inflater();
try {
int n;
while ((n = inf.inflate(dummy)) == 0) {
if (inf.finished()) {
/* Not expecting this, so fail loudly. */
throw new IOException("Unable to read the response");
}
if (inf.needsDictionary()) {
/* Need dictionary - then it must be zlib stream with DICTID part? */
break;
}
if (inf.needsInput()) {
inf.setInput(peeked);
}
}
if (n == -1) {
throw new IOException("Unable to read the response");
}
/*
* We read something without a problem, so it's a valid zlib stream. Just need to reset
* and return an unused InputStream now.
*/
pushback.unread(peeked, 0, headerLength);
sourceStream = new DeflateStream(pushback, new Inflater());
} catch (final DataFormatException e) {
/* Presume that it's an RFC1951 deflate stream rather than RFC1950 zlib stream and try
* again. */
pushback.unread(peeked, 0, headerLength);
sourceStream = new DeflateStream(pushback, new Inflater(true));
} finally {
inf.end();
}
}
/** Read a byte.
*/
@Override
public int read()
throws IOException
{
return sourceStream.read();
}
/** Read lots of bytes.
*/
@Override
public int read(final byte[] b)
throws IOException
{
return sourceStream.read(b);
}
/** Read lots of specific bytes.
*/
@Override
public int read(final byte[] b, final int off, final int len)
throws IOException
{
return sourceStream.read(b,off,len);
}
/** Skip
*/
@Override
public long skip(final long n)
throws IOException
{
return sourceStream.skip(n);
}
/** Get available.
*/
@Override
public int available()
throws IOException
{
return sourceStream.available();
}
/** Mark.
*/
@Override
public void mark(final int readLimit)
{
sourceStream.mark(readLimit);
}
/** Reset.
*/
@Override
public void reset()
throws IOException
{
sourceStream.reset();
}
/** Check if mark is supported.
*/
@Override
public boolean markSupported()
{
return sourceStream.markSupported();
}
/** Close.
*/
@Override
public void close()
throws IOException
{
sourceStream.close();
}
static class DeflateStream extends InflaterInputStream {
private boolean closed = false;
public DeflateStream(final InputStream in, final Inflater inflater) {
super(in, inflater);
}
@Override
public void close() throws IOException {
if (closed) {
return;
}
closed = true;
inf.end();
super.close();
}
}
}

View file

@ -0,0 +1,342 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.NameValuePair;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.entity.AbstractHttpEntity;
import ch.boye.httpclientandroidlib.entity.BasicHttpEntity;
import ch.boye.httpclientandroidlib.entity.ByteArrayEntity;
import ch.boye.httpclientandroidlib.entity.ContentType;
import ch.boye.httpclientandroidlib.entity.FileEntity;
import ch.boye.httpclientandroidlib.entity.InputStreamEntity;
import ch.boye.httpclientandroidlib.entity.SerializableEntity;
import ch.boye.httpclientandroidlib.entity.StringEntity;
/**
* Builder for {@link HttpEntity} instances.
* <p/>
* Several setter methods of this builder are mutually exclusive. In case of multiple invocations
* of the following methods only the last one will have effect:
* <ul>
* <li>{@link #setText(String)}</li>
* <li>{@link #setBinary(byte[])}</li>
* <li>{@link #setStream(java.io.InputStream)}</li>
* <li>{@link #setSerializable(java.io.Serializable)}</li>
* <li>{@link #setParameters(java.util.List)}</li>
* <li>{@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}</li>
* <li>{@link #setFile(java.io.File)}</li>
* </ul>
*
* @since 4.3
*/
@NotThreadSafe
public class EntityBuilder {
private String text;
private byte[] binary;
private InputStream stream;
private List<NameValuePair> parameters;
private Serializable serializable;
private File file;
private ContentType contentType;
private String contentEncoding;
private boolean chunked;
private boolean gzipCompress;
EntityBuilder() {
super();
}
public static EntityBuilder create() {
return new EntityBuilder();
}
private void clearContent() {
this.text = null;
this.binary = null;
this.stream = null;
this.parameters = null;
this.serializable = null;
this.file = null;
}
/**
* Returns entity content as a string if set using {@link #setText(String)} method.
*/
public String getText() {
return text;
}
/**
* Sets entity content as a string. This method is mutually exclusive with
* {@link #setBinary(byte[])},
* {@link #setStream(java.io.InputStream)} ,
* {@link #setSerializable(java.io.Serializable)} ,
* {@link #setParameters(java.util.List)},
* {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
* {@link #setFile(java.io.File)} methods.
*/
public EntityBuilder setText(final String text) {
clearContent();
this.text = text;
return this;
}
/**
* Returns entity content as a byte array if set using
* {@link #setBinary(byte[])} method.
*/
public byte[] getBinary() {
return binary;
}
/**
* Sets entity content as a byte array. This method is mutually exclusive with
* {@link #setText(String)},
* {@link #setStream(java.io.InputStream)} ,
* {@link #setSerializable(java.io.Serializable)} ,
* {@link #setParameters(java.util.List)},
* {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
* {@link #setFile(java.io.File)} methods.
*/
public EntityBuilder setBinary(final byte[] binary) {
clearContent();
this.binary = binary;
return this;
}
/**
* Returns entity content as a {@link InputStream} if set using
* {@link #setStream(java.io.InputStream)} method.
*/
public InputStream getStream() {
return stream;
}
/**
* Sets entity content as a {@link InputStream}. This method is mutually exclusive with
* {@link #setText(String)},
* {@link #setBinary(byte[])},
* {@link #setSerializable(java.io.Serializable)} ,
* {@link #setParameters(java.util.List)},
* {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
* {@link #setFile(java.io.File)} methods.
*/
public EntityBuilder setStream(final InputStream stream) {
clearContent();
this.stream = stream;
return this;
}
/**
* Returns entity content as a parameter list if set using
* {@link #setParameters(java.util.List)} or
* {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)} methods.
*/
public List<NameValuePair> getParameters() {
return parameters;
}
/**
* Sets entity content as a parameter list. This method is mutually exclusive with
* {@link #setText(String)},
* {@link #setBinary(byte[])},
* {@link #setStream(java.io.InputStream)} ,
* {@link #setSerializable(java.io.Serializable)} ,
* {@link #setFile(java.io.File)} methods.
*/
public EntityBuilder setParameters(final List<NameValuePair> parameters) {
clearContent();
this.parameters = parameters;
return this;
}
/**
* Sets entity content as a parameter list. This method is mutually exclusive with
* {@link #setText(String)},
* {@link #setBinary(byte[])},
* {@link #setStream(java.io.InputStream)} ,
* {@link #setSerializable(java.io.Serializable)} ,
* {@link #setFile(java.io.File)} methods.
*/
public EntityBuilder setParameters(final NameValuePair... parameters) {
return setParameters(Arrays.asList(parameters));
}
/**
* Returns entity content as a {@link Serializable} if set using
* {@link #setSerializable(java.io.Serializable)} method.
*/
public Serializable getSerializable() {
return serializable;
}
/**
* Sets entity content as a {@link Serializable}. This method is mutually exclusive with
* {@link #setText(String)},
* {@link #setBinary(byte[])},
* {@link #setStream(java.io.InputStream)} ,
* {@link #setParameters(java.util.List)},
* {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
* {@link #setFile(java.io.File)} methods.
*/
public EntityBuilder setSerializable(final Serializable serializable) {
clearContent();
this.serializable = serializable;
return this;
}
/**
* Returns entity content as a {@link File} if set using
* {@link #setFile(java.io.File)} method.
*/
public File getFile() {
return file;
}
/**
* Sets entity content as a {@link File}. This method is mutually exclusive with
* {@link #setText(String)},
* {@link #setBinary(byte[])},
* {@link #setStream(java.io.InputStream)} ,
* {@link #setParameters(java.util.List)},
* {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
* {@link #setSerializable(java.io.Serializable)} methods.
*/
public EntityBuilder setFile(final File file) {
clearContent();
this.file = file;
return this;
}
/**
* Returns {@link ContentType} of the entity, if set.
*/
public ContentType getContentType() {
return contentType;
}
/**
* Sets {@link ContentType} of the entity.
*/
public EntityBuilder setContentType(final ContentType contentType) {
this.contentType = contentType;
return this;
}
/**
* Returns content encoding of the entity, if set.
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
* Sets content encoding of the entity.
*/
public EntityBuilder setContentEncoding(final String contentEncoding) {
this.contentEncoding = contentEncoding;
return this;
}
/**
* Returns <code>true</code> if entity is to be chunk coded, <code>false</code> otherwise.
*/
public boolean isChunked() {
return chunked;
}
/**
* Makes entity chunk coded.
*/
public EntityBuilder chunked() {
this.chunked = true;
return this;
}
/**
* Returns <code>true</code> if entity is to be GZIP compressed, <code>false</code> otherwise.
*/
public boolean isGzipCompress() {
return gzipCompress;
}
/**
* Makes entity GZIP compressed.
*/
public EntityBuilder gzipCompress() {
this.gzipCompress = true;
return this;
}
private ContentType getContentOrDefault(final ContentType def) {
return this.contentType != null ? this.contentType : def;
}
/**
* Creates new instance of {@link HttpEntity} based on the current state.
*/
public HttpEntity build() {
final AbstractHttpEntity e;
if (this.text != null) {
e = new StringEntity(this.text, getContentOrDefault(ContentType.DEFAULT_TEXT));
} else if (this.binary != null) {
e = new ByteArrayEntity(this.binary, getContentOrDefault(ContentType.DEFAULT_BINARY));
} else if (this.stream != null) {
e = new InputStreamEntity(this.stream, 1, getContentOrDefault(ContentType.DEFAULT_BINARY));
} else if (this.parameters != null) {
e = new UrlEncodedFormEntity(this.parameters,
this.contentType != null ? this.contentType.getCharset() : null);
} else if (this.serializable != null) {
e = new SerializableEntity(this.serializable);
e.setContentType(ContentType.DEFAULT_BINARY.toString());
} else if (this.file != null) {
e = new FileEntity(this.file, getContentOrDefault(ContentType.DEFAULT_BINARY));
} else {
e = new BasicHttpEntity();
}
if (e.getContentType() != null && this.contentType != null) {
e.setContentType(this.contentType.toString());
}
e.setContentEncoding(this.contentEncoding);
e.setChunked(this.chunked);
if (this.gzipCompress) {
return new GzipCompressingEntity(e);
}
return e;
}
}

View file

@ -0,0 +1,113 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper;
import ch.boye.httpclientandroidlib.message.BasicHeader;
import ch.boye.httpclientandroidlib.protocol.HTTP;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Wrapping entity that compresses content when {@link #writeTo writing}.
*
*
* @since 4.0
*/
public class GzipCompressingEntity extends HttpEntityWrapper {
private static final String GZIP_CODEC = "gzip";
public GzipCompressingEntity(final HttpEntity entity) {
super(entity);
}
@Override
public Header getContentEncoding() {
return new BasicHeader(HTTP.CONTENT_ENCODING, GZIP_CODEC);
}
@Override
public long getContentLength() {
return -1;
}
@Override
public boolean isChunked() {
// force content chunking
return true;
}
@Override
public InputStream getContent() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
Args.notNull(outstream, "Output stream");
final GZIPOutputStream gzip = new GZIPOutputStream(outstream);
wrappedEntity.writeTo(gzip);
// Only close output stream if the wrapped entity has been
// successfully written out
gzip.close();
}
}

View file

@ -0,0 +1,80 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
/**
* {@link ch.boye.httpclientandroidlib.entity.HttpEntityWrapper} for handling gzip
* Content Coded responses.
*
* @since 4.1
*/
public class GzipDecompressingEntity extends DecompressingEntity {
/**
* Creates a new {@link GzipDecompressingEntity} which will wrap the specified
* {@link HttpEntity}.
*
* @param entity
* the non-null {@link HttpEntity} to be wrapped
*/
public GzipDecompressingEntity(final HttpEntity entity) {
super(entity);
}
@Override
InputStream decorate(final InputStream wrapped) throws IOException {
return new GZIPInputStream(wrapped);
}
/**
* {@inheritDoc}
*/
@Override
public Header getContentEncoding() {
/* This HttpEntityWrapper has dealt with the Content-Encoding. */
return null;
}
/**
* {@inheritDoc}
*/
@Override
public long getContentLength() {
/* length of ungzipped content is not known */
return -1;
}
}

View file

@ -0,0 +1,105 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import java.io.IOException;
import java.io.InputStream;
/**
* Lazy init InputStream wrapper.
*/
@NotThreadSafe
class LazyDecompressingInputStream extends InputStream {
private final InputStream wrappedStream;
private final DecompressingEntity decompressingEntity;
private InputStream wrapperStream;
public LazyDecompressingInputStream(
final InputStream wrappedStream,
final DecompressingEntity decompressingEntity) {
this.wrappedStream = wrappedStream;
this.decompressingEntity = decompressingEntity;
}
private void initWrapper() throws IOException {
if (wrapperStream == null) {
wrapperStream = decompressingEntity.decorate(wrappedStream);
}
}
@Override
public int read() throws IOException {
initWrapper();
return wrapperStream.read();
}
@Override
public int read(final byte[] b) throws IOException {
initWrapper();
return wrapperStream.read(b);
}
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
initWrapper();
return wrapperStream.read(b, off, len);
}
@Override
public long skip(final long n) throws IOException {
initWrapper();
return wrapperStream.skip(n);
}
@Override
public boolean markSupported() {
return false;
}
@Override
public int available() throws IOException {
initWrapper();
return wrapperStream.available();
}
@Override
public void close() throws IOException {
try {
if (wrapperStream != null) {
wrapperStream.close();
}
} finally {
wrappedStream.close();
}
}
}

View file

@ -0,0 +1,107 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.entity;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.List;
import ch.boye.httpclientandroidlib.NameValuePair;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils;
import ch.boye.httpclientandroidlib.entity.ContentType;
import ch.boye.httpclientandroidlib.entity.StringEntity;
import ch.boye.httpclientandroidlib.protocol.HTTP;
/**
* An entity composed of a list of url-encoded pairs.
* This is typically useful while sending an HTTP POST request.
*
* @since 4.0
*/
@NotThreadSafe // AbstractHttpEntity is not thread-safe
public class UrlEncodedFormEntity extends StringEntity {
/**
* Constructs a new {@link UrlEncodedFormEntity} with the list
* of parameters in the specified encoding.
*
* @param parameters list of name/value pairs
* @param charset encoding the name/value pairs be encoded with
* @throws UnsupportedEncodingException if the encoding isn't supported
*/
public UrlEncodedFormEntity (
final List <? extends NameValuePair> parameters,
final String charset) throws UnsupportedEncodingException {
super(URLEncodedUtils.format(parameters,
charset != null ? charset : HTTP.DEF_CONTENT_CHARSET.name()),
ContentType.create(URLEncodedUtils.CONTENT_TYPE, charset));
}
/**
* Constructs a new {@link UrlEncodedFormEntity} with the list
* of parameters in the specified encoding.
*
* @param parameters iterable collection of name/value pairs
* @param charset encoding the name/value pairs be encoded with
*
* @since 4.2
*/
public UrlEncodedFormEntity (
final Iterable <? extends NameValuePair> parameters,
final Charset charset) {
super(URLEncodedUtils.format(parameters,
charset != null ? charset : HTTP.DEF_CONTENT_CHARSET),
ContentType.create(URLEncodedUtils.CONTENT_TYPE, charset));
}
/**
* Constructs a new {@link UrlEncodedFormEntity} with the list
* of parameters with the default encoding of {@link HTTP#DEFAULT_CONTENT_CHARSET}
*
* @param parameters list of name/value pairs
* @throws UnsupportedEncodingException if the default encoding isn't supported
*/
public UrlEncodedFormEntity (
final List <? extends NameValuePair> parameters) throws UnsupportedEncodingException {
this(parameters, (Charset) null);
}
/**
* Constructs a new {@link UrlEncodedFormEntity} with the list
* of parameters with the default encoding of {@link HTTP#DEFAULT_CONTENT_CHARSET}
*
* @param parameters iterable collection of name/value pairs
*
* @since 4.2
*/
public UrlEncodedFormEntity (
final Iterable <? extends NameValuePair> parameters) {
this(parameters, null);
}
}

View file

@ -0,0 +1,31 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
/**
* Client specific HTTP entity implementations.
*/
package ch.boye.httpclientandroidlib.client.entity;

View file

@ -0,0 +1,82 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
import ch.boye.httpclientandroidlib.conn.ConnectionReleaseTrigger;
import java.io.IOException;
/**
* Interface representing an HTTP request that can be aborted by shutting
* down the underlying HTTP connection.
*
* @since 4.0
*
* @deprecated (4.3) use {@link HttpExecutionAware}
*/
@Deprecated
public interface AbortableHttpRequest {
/**
* Sets the {@link ch.boye.httpclientandroidlib.conn.ClientConnectionRequest}
* callback that can be used to abort a long-lived request for a connection.
* If the request is already aborted, throws an {@link IOException}.
*
* @see ch.boye.httpclientandroidlib.conn.ClientConnectionManager
*/
void setConnectionRequest(ClientConnectionRequest connRequest) throws IOException;
/**
* Sets the {@link ConnectionReleaseTrigger} callback that can
* be used to abort an active connection.
* Typically, this will be the
* {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} itself.
* If the request is already aborted, throws an {@link IOException}.
*/
void setReleaseTrigger(ConnectionReleaseTrigger releaseTrigger) throws IOException;
/**
* Aborts this http request. Any active execution of this method should
* return immediately. If the request has not started, it will abort after
* the next execution. Aborting this request will cause all subsequent
* executions with this request to fail.
*
* @see ch.boye.httpclientandroidlib.client.HttpClient#execute(HttpUriRequest)
* @see ch.boye.httpclientandroidlib.client.HttpClient#execute(ch.boye.httpclientandroidlib.HttpHost,
* ch.boye.httpclientandroidlib.HttpRequest)
* @see ch.boye.httpclientandroidlib.client.HttpClient#execute(HttpUriRequest,
* ch.boye.httpclientandroidlib.protocol.HttpContext)
* @see ch.boye.httpclientandroidlib.client.HttpClient#execute(ch.boye.httpclientandroidlib.HttpHost,
* ch.boye.httpclientandroidlib.HttpRequest, ch.boye.httpclientandroidlib.protocol.HttpContext)
*/
void abort();
}

View file

@ -0,0 +1,131 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.client.utils.CloneUtils;
import ch.boye.httpclientandroidlib.concurrent.Cancellable;
import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
import ch.boye.httpclientandroidlib.conn.ConnectionReleaseTrigger;
import ch.boye.httpclientandroidlib.message.AbstractHttpMessage;
@SuppressWarnings("deprecation")
public abstract class AbstractExecutionAwareRequest extends AbstractHttpMessage implements
HttpExecutionAware, AbortableHttpRequest, Cloneable, HttpRequest {
private final AtomicBoolean aborted;
private final AtomicReference<Cancellable> cancellableRef;
protected AbstractExecutionAwareRequest() {
super();
this.aborted = new AtomicBoolean(false);
this.cancellableRef = new AtomicReference<Cancellable>(null);
}
@Deprecated
public void setConnectionRequest(final ClientConnectionRequest connRequest) {
setCancellable(new Cancellable() {
public boolean cancel() {
connRequest.abortRequest();
return true;
}
});
}
@Deprecated
public void setReleaseTrigger(final ConnectionReleaseTrigger releaseTrigger) {
setCancellable(new Cancellable() {
public boolean cancel() {
try {
releaseTrigger.abortConnection();
return true;
} catch (final IOException ex) {
return false;
}
}
});
}
public void abort() {
if (this.aborted.compareAndSet(false, true)) {
final Cancellable cancellable = this.cancellableRef.getAndSet(null);
if (cancellable != null) {
cancellable.cancel();
}
}
}
public boolean isAborted() {
return this.aborted.get();
}
/**
* @since 4.2
*/
public void setCancellable(final Cancellable cancellable) {
if (!this.aborted.get()) {
this.cancellableRef.set(cancellable);
}
}
@Override
public Object clone() throws CloneNotSupportedException {
final AbstractExecutionAwareRequest clone = (AbstractExecutionAwareRequest) super.clone();
clone.headergroup = CloneUtils.cloneObject(this.headergroup);
clone.params = CloneUtils.cloneObject(this.params);
return clone;
}
/**
* @since 4.2
*/
public void completed() {
this.cancellableRef.set(null);
}
/**
* Resets internal state of the request making it reusable.
*
* @since 4.2
*/
public void reset() {
final Cancellable cancellable = this.cancellableRef.getAndSet(null);
if (cancellable != null) {
cancellable.cancel();
}
this.aborted.set(false);
}
}

View file

@ -0,0 +1,40 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.io.Closeable;
import ch.boye.httpclientandroidlib.HttpResponse;
/**
* Extended version of the {@link HttpResponse} interface that also extends {@link Closeable}.
*
* @since 4.3
*/
public interface CloseableHttpResponse extends HttpResponse, Closeable {
}

View file

@ -0,0 +1,44 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import ch.boye.httpclientandroidlib.client.config.RequestConfig;
/**
* Configuration interface for HTTP requests.
*
* @since 4.3
*/
public interface Configurable {
/**
* Returns actual request configuration.
*/
RequestConfig getConfig();
}

View file

@ -0,0 +1,77 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* HTTP DELETE method
* <p>
* The HTTP DELETE method is defined in section 9.7 of
* <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
* <blockquote>
* The DELETE method requests that the origin server delete the resource
* identified by the Request-URI. [...] The client cannot
* be guaranteed that the operation has been carried out, even if the
* status code returned from the origin server indicates that the action
* has been completed successfully.
* </blockquote>
*
* @since 4.0
*/
@NotThreadSafe // HttpRequestBase is @NotThreadSafe
public class HttpDelete extends HttpRequestBase {
public final static String METHOD_NAME = "DELETE";
public HttpDelete() {
super();
}
public HttpDelete(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpDelete(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}

View file

@ -0,0 +1,76 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.client.utils.CloneUtils;
import ch.boye.httpclientandroidlib.protocol.HTTP;
/**
* Basic implementation of an entity enclosing HTTP request
* that can be modified
*
* @since 4.0
*/
@NotThreadSafe // HttpRequestBase is @NotThreadSafe
public abstract class HttpEntityEnclosingRequestBase
extends HttpRequestBase implements HttpEntityEnclosingRequest {
private HttpEntity entity;
public HttpEntityEnclosingRequestBase() {
super();
}
public HttpEntity getEntity() {
return this.entity;
}
public void setEntity(final HttpEntity entity) {
this.entity = entity;
}
public boolean expectContinue() {
final Header expect = getFirstHeader(HTTP.EXPECT_DIRECTIVE);
return expect != null && HTTP.EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue());
}
@Override
public Object clone() throws CloneNotSupportedException {
final HttpEntityEnclosingRequestBase clone =
(HttpEntityEnclosingRequestBase) super.clone();
if (this.entity != null) {
clone.entity = CloneUtils.cloneObject(this.entity);
}
return clone;
}
}

View file

@ -0,0 +1,47 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import ch.boye.httpclientandroidlib.concurrent.Cancellable;
/**
* Interface to be implemented by any object that wishes to be notified of
* blocking I/O operations that could be cancelled.
*
* @since 4.3
*/
public interface HttpExecutionAware {
boolean isAborted();
/**
* Sets {@link Cancellable} for the ongoing operation.
*/
void setCancellable(Cancellable cancellable);
}

View file

@ -0,0 +1,77 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* HTTP GET method.
* <p>
* The HTTP GET method is defined in section 9.3 of
* <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
* <blockquote>
* The GET method means retrieve whatever information (in the form of an
* entity) is identified by the Request-URI. If the Request-URI refers
* to a data-producing process, it is the produced data which shall be
* returned as the entity in the response and not the source text of the
* process, unless that text happens to be the output of the process.
* </blockquote>
* </p>
*
* @since 4.0
*/
@NotThreadSafe
public class HttpGet extends HttpRequestBase {
public final static String METHOD_NAME = "GET";
public HttpGet() {
super();
}
public HttpGet(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpGet(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}

View file

@ -0,0 +1,80 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* HTTP HEAD method.
* <p>
* The HTTP HEAD method is defined in section 9.4 of
* <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
* <blockquote>
* The HEAD method is identical to GET except that the server MUST NOT
* return a message-body in the response. The metainformation contained
* in the HTTP headers in response to a HEAD request SHOULD be identical
* to the information sent in response to a GET request. This method can
* be used for obtaining metainformation about the entity implied by the
* request without transferring the entity-body itself. This method is
* often used for testing hypertext links for validity, accessibility,
* and recent modification.
* </blockquote>
* </p>
*
* @since 4.0
*/
@NotThreadSafe
public class HttpHead extends HttpRequestBase {
public final static String METHOD_NAME = "HEAD";
public HttpHead() {
super();
}
public HttpHead(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpHead(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}

View file

@ -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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HeaderElement;
import ch.boye.httpclientandroidlib.HeaderIterator;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.util.Args;
/**
* HTTP OPTIONS method.
* <p>
* The HTTP OPTIONS method is defined in section 9.2 of
* <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
* <blockquote>
* The OPTIONS method represents a request for information about the
* communication options available on the request/response chain
* identified by the Request-URI. This method allows the client to
* determine the options and/or requirements associated with a resource,
* or the capabilities of a server, without implying a resource action
* or initiating a resource retrieval.
* </blockquote>
* </p>
*
* @since 4.0
*/
@NotThreadSafe
public class HttpOptions extends HttpRequestBase {
public final static String METHOD_NAME = "OPTIONS";
public HttpOptions() {
super();
}
public HttpOptions(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpOptions(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
public Set<String> getAllowedMethods(final HttpResponse response) {
Args.notNull(response, "HTTP response");
final HeaderIterator it = response.headerIterator("Allow");
final Set<String> methods = new HashSet<String>();
while (it.hasNext()) {
final Header header = it.nextHeader();
final HeaderElement[] elements = header.getElements();
for (final HeaderElement element : elements) {
methods.add(element.getName());
}
}
return methods;
}
}

View file

@ -0,0 +1,75 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* HTTP PATCH method.
* <p>
* The HTTP PATCH method is defined in <a
* href="http://tools.ietf.org/html/rfc5789">RF5789</a>: <blockquote> The PATCH
* method requests that a set of changes described in the request entity be
* applied to the resource identified by the Request- URI. Differs from the PUT
* method in the way the server processes the enclosed entity to modify the
* resource identified by the Request-URI. In a PUT request, the enclosed entity
* origin server, and the client is requesting that the stored version be
* replaced. With PATCH, however, the enclosed entity contains a set of
* instructions describing how a resource currently residing on the origin
* server should be modified to produce a new version. </blockquote>
* </p>
*
* @since 4.2
*/
@NotThreadSafe
public class HttpPatch extends HttpEntityEnclosingRequestBase {
public final static String METHOD_NAME = "PATCH";
public HttpPatch() {
super();
}
public HttpPatch(final URI uri) {
super();
setURI(uri);
}
public HttpPatch(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}

View file

@ -0,0 +1,84 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* HTTP POST method.
* <p>
* The HTTP POST method is defined in section 9.5 of
* <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
* <blockquote>
* The POST method is used to request that the origin server accept the entity
* enclosed in the request as a new subordinate of the resource identified by
* the Request-URI in the Request-Line. POST is designed to allow a uniform
* method to cover the following functions:
* <ul>
* <li>Annotation of existing resources</li>
* <li>Posting a message to a bulletin board, newsgroup, mailing list, or
* similar group of articles</li>
* <li>Providing a block of data, such as the result of submitting a form,
* to a data-handling process</li>
* <li>Extending a database through an append operation</li>
* </ul>
* </blockquote>
* </p>
*
* @since 4.0
*/
@NotThreadSafe
public class HttpPost extends HttpEntityEnclosingRequestBase {
public final static String METHOD_NAME = "POST";
public HttpPost() {
super();
}
public HttpPost(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpPost(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}

View file

@ -0,0 +1,76 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* HTTP PUT method.
* <p>
* The HTTP PUT method is defined in section 9.6 of
* <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
* <blockquote>
* The PUT method requests that the enclosed entity be stored under the
* supplied Request-URI. If the Request-URI refers to an already
* existing resource, the enclosed entity SHOULD be considered as a
* modified version of the one residing on the origin server.
* </blockquote>
* </p>
*
* @since 4.0
*/
@NotThreadSafe
public class HttpPut extends HttpEntityEnclosingRequestBase {
public final static String METHOD_NAME = "PUT";
public HttpPut() {
super();
}
public HttpPut(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpPut(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}

View file

@ -0,0 +1,124 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.ProtocolVersion;
import ch.boye.httpclientandroidlib.RequestLine;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.client.config.RequestConfig;
import ch.boye.httpclientandroidlib.message.BasicRequestLine;
import ch.boye.httpclientandroidlib.params.HttpProtocolParams;
/**
* Base implementation of {@link HttpUriRequest}.
*
* @since 4.0
*/
@SuppressWarnings("deprecation")
@NotThreadSafe
public abstract class HttpRequestBase extends AbstractExecutionAwareRequest
implements HttpUriRequest, Configurable {
private ProtocolVersion version;
private URI uri;
private RequestConfig config;
public abstract String getMethod();
/**
* @since 4.3
*/
public void setProtocolVersion(final ProtocolVersion version) {
this.version = version;
}
public ProtocolVersion getProtocolVersion() {
return version != null ? version : HttpProtocolParams.getVersion(getParams());
}
/**
* Returns the original request URI.
* <p>
* Please note URI remains unchanged in the course of request execution and
* is not updated if the request is redirected to another location.
*/
public URI getURI() {
return this.uri;
}
public RequestLine getRequestLine() {
final String method = getMethod();
final ProtocolVersion ver = getProtocolVersion();
final URI uri = getURI();
String uritext = null;
if (uri != null) {
uritext = uri.toASCIIString();
}
if (uritext == null || uritext.length() == 0) {
uritext = "/";
}
return new BasicRequestLine(method, uritext, ver);
}
public RequestConfig getConfig() {
return config;
}
public void setConfig(final RequestConfig config) {
this.config = config;
}
public void setURI(final URI uri) {
this.uri = uri;
}
/**
* @since 4.2
*/
public void started() {
}
/**
* A convenience method to simplify migration from HttpClient 3.1 API. This method is
* equivalent to {@link #reset()}.
*
* @since 4.2
*/
public void releaseConnection() {
reset();
}
@Override
public String toString() {
return getMethod() + " " + getURI() + " " + getProtocolVersion();
}
}

View file

@ -0,0 +1,171 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.ProtocolVersion;
import ch.boye.httpclientandroidlib.RequestLine;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.message.AbstractHttpMessage;
import ch.boye.httpclientandroidlib.message.BasicRequestLine;
import ch.boye.httpclientandroidlib.params.HttpParams;
import ch.boye.httpclientandroidlib.protocol.HTTP;
/**
* A wrapper class for {@link HttpRequest} that can be used to change properties of the current
* request without modifying the original object.
*
* @since 4.3
*/
@SuppressWarnings("deprecation")
@NotThreadSafe
public class HttpRequestWrapper extends AbstractHttpMessage implements HttpUriRequest {
private final HttpRequest original;
private final String method;
private ProtocolVersion version;
private URI uri;
private HttpRequestWrapper(final HttpRequest request) {
super();
this.original = request;
this.version = this.original.getRequestLine().getProtocolVersion();
this.method = this.original.getRequestLine().getMethod();
if (request instanceof HttpUriRequest) {
this.uri = ((HttpUriRequest) request).getURI();
} else {
this.uri = null;
}
setHeaders(request.getAllHeaders());
}
public ProtocolVersion getProtocolVersion() {
return this.version != null ? this.version : this.original.getProtocolVersion();
}
public void setProtocolVersion(final ProtocolVersion version) {
this.version = version;
}
public URI getURI() {
return this.uri;
}
public void setURI(final URI uri) {
this.uri = uri;
}
public String getMethod() {
return method;
}
public void abort() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public boolean isAborted() {
return false;
}
public RequestLine getRequestLine() {
String requestUri = null;
if (this.uri != null) {
requestUri = this.uri.toASCIIString();
} else {
requestUri = this.original.getRequestLine().getUri();
}
if (requestUri == null || requestUri.length() == 0) {
requestUri = "/";
}
return new BasicRequestLine(this.method, requestUri, getProtocolVersion());
}
public HttpRequest getOriginal() {
return this.original;
}
@Override
public String toString() {
return getRequestLine() + " " + this.headergroup;
}
static class HttpEntityEnclosingRequestWrapper extends HttpRequestWrapper
implements HttpEntityEnclosingRequest {
private HttpEntity entity;
public HttpEntityEnclosingRequestWrapper(final HttpEntityEnclosingRequest request) {
super(request);
this.entity = request.getEntity();
}
public HttpEntity getEntity() {
return this.entity;
}
public void setEntity(final HttpEntity entity) {
this.entity = entity;
}
public boolean expectContinue() {
final Header expect = getFirstHeader(HTTP.EXPECT_DIRECTIVE);
return expect != null && HTTP.EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue());
}
}
public static HttpRequestWrapper wrap(final HttpRequest request) {
if (request == null) {
return null;
}
if (request instanceof HttpEntityEnclosingRequest) {
return new HttpEntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request);
} else {
return new HttpRequestWrapper(request);
}
}
/**
* @deprecated (4.3) use
* {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
*/
@Override
@Deprecated
public HttpParams getParams() {
if (this.params == null) {
this.params = original.getParams().copy();
}
return this.params;
}
}

View file

@ -0,0 +1,79 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
/**
* HTTP TRACE method.
* <p>
* The HTTP TRACE method is defined in section 9.6 of
* <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
* <blockquote>
* The TRACE method is used to invoke a remote, application-layer loop-
* back of the request message. The final recipient of the request
* SHOULD reflect the message received back to the client as the
* entity-body of a 200 (OK) response. The final recipient is either the
* origin server or the first proxy or gateway to receive a Max-Forwards
* value of zero (0) in the request (see section 14.31). A TRACE request
* MUST NOT include an entity.
* </blockquote>
* </p>
*
* @since 4.0
*/
@NotThreadSafe
public class HttpTrace extends HttpRequestBase {
public final static String METHOD_NAME = "TRACE";
public HttpTrace() {
super();
}
public HttpTrace(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpTrace(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}

View file

@ -0,0 +1,84 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import ch.boye.httpclientandroidlib.HttpRequest;
/**
* Extended version of the {@link HttpRequest} interface that provides
* convenience methods to access request properties such as request URI
* and method type.
*
* @since 4.0
*/
public interface HttpUriRequest extends HttpRequest {
/**
* Returns the HTTP method this request uses, such as <code>GET</code>,
* <code>PUT</code>, <code>POST</code>, or other.
*/
String getMethod();
/**
* Returns the URI this request uses, such as
* <code>http://example.org/path/to/file</code>.
* <br/>
* Note that the URI may be absolute URI (as above) or may be a relative URI.
* <p>
* Implementations are encouraged to return
* the URI that was initially requested.
* </p>
* <p>
* To find the final URI after any redirects have been processed,
* please see the section entitled
* <a href="http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d4e205">HTTP execution context</a>
* in the
* <a href="http://hc.apache.org/httpcomponents-client-ga/tutorial/html">HttpClient Tutorial</a>
* </p>
*/
URI getURI();
/**
* Aborts execution of the request.
*
* @throws UnsupportedOperationException if the abort operation
* is not supported / cannot be implemented.
*/
void abort() throws UnsupportedOperationException;
/**
* Tests if the request execution has been aborted.
*
* @return <code>true</code> if the request execution has been aborted,
* <code>false</code> otherwise.
*/
boolean isAborted();
}

View file

@ -0,0 +1,351 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.methods;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HeaderIterator;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.NameValuePair;
import ch.boye.httpclientandroidlib.ProtocolVersion;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.client.config.RequestConfig;
import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
import ch.boye.httpclientandroidlib.client.utils.URIBuilder;
import ch.boye.httpclientandroidlib.message.BasicHeader;
import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
import ch.boye.httpclientandroidlib.message.HeaderGroup;
import ch.boye.httpclientandroidlib.protocol.HTTP;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Builder for {@link HttpUriRequest} instances.
* <p/>
* Please note that this class treats parameters differently depending on composition
* of the request: if the request has a content entity explicitly set with
* {@link #setEntity(ch.boye.httpclientandroidlib.HttpEntity)} or it is not an entity enclosing method
* (such as POST or PUT), parameters will be added to the query component of the request URI.
* Otherwise, parameters will be added as a URL encoded {@link UrlEncodedFormEntity entity}.
*
* @since 4.3
*/
@NotThreadSafe
public class RequestBuilder {
private String method;
private ProtocolVersion version;
private URI uri;
private HeaderGroup headergroup;
private HttpEntity entity;
private LinkedList<NameValuePair> parameters;
private RequestConfig config;
RequestBuilder(final String method) {
super();
this.method = method;
}
RequestBuilder() {
this(null);
}
public static RequestBuilder create(final String method) {
Args.notBlank(method, "HTTP method");
return new RequestBuilder(method);
}
public static RequestBuilder get() {
return new RequestBuilder(HttpGet.METHOD_NAME);
}
public static RequestBuilder head() {
return new RequestBuilder(HttpHead.METHOD_NAME);
}
public static RequestBuilder post() {
return new RequestBuilder(HttpPost.METHOD_NAME);
}
public static RequestBuilder put() {
return new RequestBuilder(HttpPut.METHOD_NAME);
}
public static RequestBuilder delete() {
return new RequestBuilder(HttpDelete.METHOD_NAME);
}
public static RequestBuilder trace() {
return new RequestBuilder(HttpTrace.METHOD_NAME);
}
public static RequestBuilder options() {
return new RequestBuilder(HttpOptions.METHOD_NAME);
}
public static RequestBuilder copy(final HttpRequest request) {
Args.notNull(request, "HTTP request");
return new RequestBuilder().doCopy(request);
}
private RequestBuilder doCopy(final HttpRequest request) {
if (request == null) {
return this;
}
method = request.getRequestLine().getMethod();
version = request.getRequestLine().getProtocolVersion();
if (request instanceof HttpUriRequest) {
uri = ((HttpUriRequest) request).getURI();
} else {
uri = URI.create(request.getRequestLine().getUri());
}
if (headergroup == null) {
headergroup = new HeaderGroup();
}
headergroup.clear();
headergroup.setHeaders(request.getAllHeaders());
if (request instanceof HttpEntityEnclosingRequest) {
entity = ((HttpEntityEnclosingRequest) request).getEntity();
} else {
entity = null;
}
if (request instanceof Configurable) {
this.config = ((Configurable) request).getConfig();
} else {
this.config = null;
}
this.parameters = null;
return this;
}
public String getMethod() {
return method;
}
public ProtocolVersion getVersion() {
return version;
}
public RequestBuilder setVersion(final ProtocolVersion version) {
this.version = version;
return this;
}
public URI getUri() {
return uri;
}
public RequestBuilder setUri(final URI uri) {
this.uri = uri;
return this;
}
public RequestBuilder setUri(final String uri) {
this.uri = uri != null ? URI.create(uri) : null;
return this;
}
public Header getFirstHeader(final String name) {
return headergroup != null ? headergroup.getFirstHeader(name) : null;
}
public Header getLastHeader(final String name) {
return headergroup != null ? headergroup.getLastHeader(name) : null;
}
public Header[] getHeaders(final String name) {
return headergroup != null ? headergroup.getHeaders(name) : null;
}
public RequestBuilder addHeader(final Header header) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
headergroup.addHeader(header);
return this;
}
public RequestBuilder addHeader(final String name, final String value) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
this.headergroup.addHeader(new BasicHeader(name, value));
return this;
}
public RequestBuilder removeHeader(final Header header) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
headergroup.removeHeader(header);
return this;
}
public RequestBuilder removeHeaders(final String name) {
if (name == null || headergroup == null) {
return this;
}
for (final HeaderIterator i = headergroup.iterator(); i.hasNext(); ) {
final Header header = i.nextHeader();
if (name.equalsIgnoreCase(header.getName())) {
i.remove();
}
}
return this;
}
public RequestBuilder setHeader(final Header header) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
this.headergroup.updateHeader(header);
return this;
}
public RequestBuilder setHeader(final String name, final String value) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
this.headergroup.updateHeader(new BasicHeader(name, value));
return this;
}
public HttpEntity getEntity() {
return entity;
}
public RequestBuilder setEntity(final HttpEntity entity) {
this.entity = entity;
return this;
}
public List<NameValuePair> getParameters() {
return parameters != null ? new ArrayList<NameValuePair>(parameters) :
new ArrayList<NameValuePair>();
}
public RequestBuilder addParameter(final NameValuePair nvp) {
Args.notNull(nvp, "Name value pair");
if (parameters == null) {
parameters = new LinkedList<NameValuePair>();
}
parameters.add(nvp);
return this;
}
public RequestBuilder addParameter(final String name, final String value) {
return addParameter(new BasicNameValuePair(name, value));
}
public RequestBuilder addParameters(final NameValuePair... nvps) {
for (final NameValuePair nvp: nvps) {
addParameter(nvp);
}
return this;
}
public RequestConfig getConfig() {
return config;
}
public RequestBuilder setConfig(final RequestConfig config) {
this.config = config;
return this;
}
public HttpUriRequest build() {
final HttpRequestBase result;
URI uri = this.uri != null ? this.uri : URI.create("/");
HttpEntity entity = this.entity;
if (parameters != null && !parameters.isEmpty()) {
if (entity == null && (HttpPost.METHOD_NAME.equalsIgnoreCase(method)
|| HttpPut.METHOD_NAME.equalsIgnoreCase(method))) {
entity = new UrlEncodedFormEntity(parameters, HTTP.DEF_CONTENT_CHARSET);
} else {
try {
uri = new URIBuilder(uri).addParameters(parameters).build();
} catch (final URISyntaxException ex) {
// should never happen
}
}
}
if (entity == null) {
result = new InternalRequest(method);
} else {
final InternalEntityEclosingRequest request = new InternalEntityEclosingRequest(method);
request.setEntity(entity);
result = request;
}
result.setProtocolVersion(this.version);
result.setURI(uri);
if (this.headergroup != null) {
result.setHeaders(this.headergroup.getAllHeaders());
}
result.setConfig(this.config);
return result;
}
static class InternalRequest extends HttpRequestBase {
private final String method;
InternalRequest(final String method) {
super();
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
static class InternalEntityEclosingRequest extends HttpEntityEnclosingRequestBase {
private final String method;
InternalEntityEclosingRequest(final String method) {
super();
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
}

View file

@ -0,0 +1,31 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
/**
* Standard HTTP method implementations.
*/
package ch.boye.httpclientandroidlib.client.methods;

View file

@ -0,0 +1,31 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
/**
* Client HTTP communication APIs.
*/
package ch.boye.httpclientandroidlib.client;

View file

@ -0,0 +1,63 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.params;
import ch.boye.httpclientandroidlib.auth.params.AuthPNames;
import ch.boye.httpclientandroidlib.conn.params.ConnConnectionPNames;
import ch.boye.httpclientandroidlib.conn.params.ConnManagerPNames;
import ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames;
import ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames;
import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
/**
* Collected parameter names for the HttpClient module.
* This interface combines the parameter definitions of the HttpClient
* module and all dependency modules or informational units.
* It does not define additional parameter names, but references
* other interfaces defining parameter names.
* <br/>
* This interface is meant as a navigation aid for developers.
* When referring to parameter names, you should use the interfaces
* in which the respective constants are actually defined.
*
* @since 4.0
*
* @deprecated (4.3) use
* {@link ch.boye.httpclientandroidlib.client.config.RequestConfig},
* {@link ch.boye.httpclientandroidlib.config.ConnectionConfig},
* {@link ch.boye.httpclientandroidlib.config.SocketConfig}
*/
@Deprecated
public interface AllClientPNames extends
CoreConnectionPNames, CoreProtocolPNames,
ClientPNames, AuthPNames, CookieSpecPNames,
ConnConnectionPNames, ConnManagerPNames, ConnRoutePNames {
// no additional definitions
}

View file

@ -0,0 +1,79 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.params;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Standard authentication schemes supported by HttpClient.
*
* @since 4.0
*
* @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.AuthSchemes}.
*/
@Deprecated
@Immutable
public final class AuthPolicy {
private AuthPolicy() {
super();
}
/**
* The NTLM scheme is a proprietary Microsoft Windows Authentication
* protocol (considered to be the most secure among currently supported
* authentication schemes).
*/
public static final String NTLM = "NTLM";
/**
* Digest authentication scheme as defined in RFC2617.
*/
public static final String DIGEST = "Digest";
/**
* Basic authentication scheme as defined in RFC2617 (considered inherently
* insecure, but most widely supported)
*/
public static final String BASIC = "Basic";
/**
* SPNEGO Authentication scheme.
*
* @since 4.1
*/
public static final String SPNEGO = "negotiate";
/**
* Kerberos Authentication scheme.
*
* @since 4.2
*/
public static final String KERBEROS = "Kerberos";
}

View file

@ -0,0 +1,133 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.params;
/**
* Parameter names for HTTP client parameters.
*
* @since 4.0
*
* @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
*/
@Deprecated
public interface ClientPNames {
public static final String CONNECTION_MANAGER_FACTORY_CLASS_NAME = "http.connection-manager.factory-class-name";
/**
* Defines whether redirects should be handled automatically
* <p>
* This parameter expects a value of type {@link Boolean}.
* </p>
*/
public static final String HANDLE_REDIRECTS = "http.protocol.handle-redirects";
/**
* Defines whether relative redirects should be rejected. HTTP specification
* requires the location value be an absolute URI.
* <p>
* This parameter expects a value of type {@link Boolean}.
* </p>
*/
public static final String REJECT_RELATIVE_REDIRECT = "http.protocol.reject-relative-redirect";
/**
* Defines the maximum number of redirects to be followed.
* The limit on number of redirects is intended to prevent infinite loops.
* <p>
* This parameter expects a value of type {@link Integer}.
* </p>
*/
public static final String MAX_REDIRECTS = "http.protocol.max-redirects";
/**
* Defines whether circular redirects (redirects to the same location) should be allowed.
* The HTTP spec is not sufficiently clear whether circular redirects are permitted,
* therefore optionally they can be enabled
* <p>
* This parameter expects a value of type {@link Boolean}.
* </p>
*/
public static final String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects";
/**
* Defines whether authentication should be handled automatically.
* <p>
* This parameter expects a value of type {@link Boolean}.
* </p>
*/
public static final String HANDLE_AUTHENTICATION = "http.protocol.handle-authentication";
/**
* Defines the name of the cookie specification to be used for HTTP state management.
* <p>
* This parameter expects a value of type {@link String}.
* </p>
*/
public static final String COOKIE_POLICY = "http.protocol.cookie-policy";
/**
* Defines the virtual host to be used in the <code>Host</code>
* request header instead of the physical host.
* <p>
* This parameter expects a value of type {@link ch.boye.httpclientandroidlib.HttpHost}.
* </p>
* If a port is not provided, it will be derived from the request URL.
*/
public static final String VIRTUAL_HOST = "http.virtual-host";
/**
* Defines the request headers to be sent per default with each request.
* <p>
* This parameter expects a value of type {@link java.util.Collection}. The
* collection is expected to contain {@link ch.boye.httpclientandroidlib.Header}s.
* </p>
*/
public static final String DEFAULT_HEADERS = "http.default-headers";
/**
* Defines the default host. The default value will be used if the target host is
* not explicitly specified in the request URI.
* <p>
* This parameter expects a value of type {@link ch.boye.httpclientandroidlib.HttpHost}.
* </p>
*/
public static final String DEFAULT_HOST = "http.default-host";
/**
* Defines the timeout in milliseconds used when retrieving an instance of
* {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the
* {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}.
* <p>
* This parameter expects a value of type {@link Long}.
* <p>
* @since 4.2
*/
public static final String CONN_MANAGER_TIMEOUT = "http.conn-manager.timeout";
}

View file

@ -0,0 +1,106 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.params;
import java.util.Collection;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean;
import ch.boye.httpclientandroidlib.params.HttpParams;
/**
* This is a Java Bean class that can be used to wrap an instance of
* {@link HttpParams} and manipulate HTTP client parameters using
* Java Beans conventions.
*
* @since 4.0
*
* @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
*/
@Deprecated
@NotThreadSafe
public class ClientParamBean extends HttpAbstractParamBean {
public ClientParamBean (final HttpParams params) {
super(params);
}
/**
* @deprecated (4.2) do not use.
*/
@Deprecated
public void setConnectionManagerFactoryClassName (final String factory) {
params.setParameter(ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME, factory);
}
public void setHandleRedirects (final boolean handle) {
params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, handle);
}
public void setRejectRelativeRedirect (final boolean reject) {
params.setBooleanParameter(ClientPNames.REJECT_RELATIVE_REDIRECT, reject);
}
public void setMaxRedirects (final int maxRedirects) {
params.setIntParameter(ClientPNames.MAX_REDIRECTS, maxRedirects);
}
public void setAllowCircularRedirects (final boolean allow) {
params.setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, allow);
}
public void setHandleAuthentication (final boolean handle) {
params.setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, handle);
}
public void setCookiePolicy (final String policy) {
params.setParameter(ClientPNames.COOKIE_POLICY, policy);
}
public void setVirtualHost (final HttpHost host) {
params.setParameter(ClientPNames.VIRTUAL_HOST, host);
}
public void setDefaultHeaders (final Collection <Header> headers) {
params.setParameter(ClientPNames.DEFAULT_HEADERS, headers);
}
public void setDefaultHost (final HttpHost host) {
params.setParameter(ClientPNames.DEFAULT_HOST, host);
}
/**
* @since 4.2
*/
public void setConnectionManagerTimeout(final long timeout) {
params.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, timeout);
}
}

View file

@ -0,0 +1,80 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.params;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Standard cookie specifications supported by HttpClient.
*
* @since 4.0
*
* @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.CookieSpecs}.
*/
@Deprecated
@Immutable
public final class CookiePolicy {
/**
* The policy that provides high degree of compatibilty
* with common cookie management of popular HTTP agents.
*/
public static final String BROWSER_COMPATIBILITY = "compatibility";
/**
* The Netscape cookie draft compliant policy.
*/
public static final String NETSCAPE = "netscape";
/**
* The RFC 2109 compliant policy.
*/
public static final String RFC_2109 = "rfc2109";
/**
* The RFC 2965 compliant policy.
*/
public static final String RFC_2965 = "rfc2965";
/**
* The default 'best match' policy.
*/
public static final String BEST_MATCH = "best-match";
/**
* The policy that ignores cookies.
*
* @since 4.1-beta1
*/
public static final String IGNORE_COOKIES = "ignoreCookies";
private CookiePolicy() {
super();
}
}

View file

@ -0,0 +1,88 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.params;
import java.net.InetAddress;
import java.util.Collection;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.auth.params.AuthPNames;
import ch.boye.httpclientandroidlib.client.config.RequestConfig;
import ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames;
import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
import ch.boye.httpclientandroidlib.params.HttpParams;
/**
* @deprecated (4.3) provided for compatibility with {@link HttpParams}. Do not use.
*
* @since 4.3
*/
@Deprecated
public final class HttpClientParamConfig {
private HttpClientParamConfig() {
}
@SuppressWarnings("unchecked")
public static RequestConfig getRequestConfig(final HttpParams params) {
return RequestConfig.custom()
.setSocketTimeout(params.getIntParameter(
CoreConnectionPNames.SO_TIMEOUT, 0))
.setStaleConnectionCheckEnabled(params.getBooleanParameter(
CoreConnectionPNames.STALE_CONNECTION_CHECK, true))
.setConnectTimeout(params.getIntParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, 0))
.setExpectContinueEnabled(params.getBooleanParameter(
CoreProtocolPNames.USE_EXPECT_CONTINUE, false))
.setProxy((HttpHost) params.getParameter(
ConnRoutePNames.DEFAULT_PROXY))
.setLocalAddress((InetAddress) params.getParameter(
ConnRoutePNames.LOCAL_ADDRESS))
.setProxyPreferredAuthSchemes((Collection<String>) params.getParameter(
AuthPNames.PROXY_AUTH_PREF))
.setTargetPreferredAuthSchemes((Collection<String>) params.getParameter(
AuthPNames.TARGET_AUTH_PREF))
.setAuthenticationEnabled(params.getBooleanParameter(
ClientPNames.HANDLE_AUTHENTICATION, true))
.setCircularRedirectsAllowed(params.getBooleanParameter(
ClientPNames.ALLOW_CIRCULAR_REDIRECTS, false))
.setConnectionRequestTimeout((int) params.getLongParameter(
ClientPNames.CONN_MANAGER_TIMEOUT, 0))
.setCookieSpec((String) params.getParameter(
ClientPNames.COOKIE_POLICY))
.setMaxRedirects(params.getIntParameter(
ClientPNames.MAX_REDIRECTS, 50))
.setRedirectsEnabled(params.getBooleanParameter(
ClientPNames.HANDLE_REDIRECTS, true))
.setRelativeRedirectsAllowed(!params.getBooleanParameter(
ClientPNames.REJECT_RELATIVE_REDIRECT, false))
.build();
}
}

View file

@ -0,0 +1,116 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.params;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
import ch.boye.httpclientandroidlib.params.HttpParams;
import ch.boye.httpclientandroidlib.util.Args;
/**
* An adaptor for manipulating HTTP client parameters in {@link HttpParams}.
*
* @since 4.0
*
* @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}
*/
@Deprecated
@Immutable
public class HttpClientParams {
private HttpClientParams() {
super();
}
public static boolean isRedirecting(final HttpParams params) {
Args.notNull(params, "HTTP parameters");
return params.getBooleanParameter
(ClientPNames.HANDLE_REDIRECTS, true);
}
public static void setRedirecting(final HttpParams params, final boolean value) {
Args.notNull(params, "HTTP parameters");
params.setBooleanParameter
(ClientPNames.HANDLE_REDIRECTS, value);
}
public static boolean isAuthenticating(final HttpParams params) {
Args.notNull(params, "HTTP parameters");
return params.getBooleanParameter
(ClientPNames.HANDLE_AUTHENTICATION, true);
}
public static void setAuthenticating(final HttpParams params, final boolean value) {
Args.notNull(params, "HTTP parameters");
params.setBooleanParameter
(ClientPNames.HANDLE_AUTHENTICATION, value);
}
public static String getCookiePolicy(final HttpParams params) {
Args.notNull(params, "HTTP parameters");
final String cookiePolicy = (String)
params.getParameter(ClientPNames.COOKIE_POLICY);
if (cookiePolicy == null) {
return CookiePolicy.BEST_MATCH;
}
return cookiePolicy;
}
public static void setCookiePolicy(final HttpParams params, final String cookiePolicy) {
Args.notNull(params, "HTTP parameters");
params.setParameter(ClientPNames.COOKIE_POLICY, cookiePolicy);
}
/**
* Set the parameter {@code ClientPNames.CONN_MANAGER_TIMEOUT}.
*
* @since 4.2
*/
public static void setConnectionManagerTimeout(final HttpParams params, final long timeout) {
Args.notNull(params, "HTTP parameters");
params.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, timeout);
}
/**
* Get the connectiion manager timeout value.
* This is defined by the parameter {@code ClientPNames.CONN_MANAGER_TIMEOUT}.
* Failing that it uses the parameter {@code CoreConnectionPNames.CONNECTION_TIMEOUT}
* which defaults to 0 if not defined.
*
* @since 4.2
* @return the timeout value
*/
public static long getConnectionManagerTimeout(final HttpParams params) {
Args.notNull(params, "HTTP parameters");
final Long timeout = (Long) params.getParameter(ClientPNames.CONN_MANAGER_TIMEOUT);
if (timeout != null) {
return timeout.longValue();
}
return HttpConnectionParams.getConnectionTimeout(params);
}
}

View file

@ -0,0 +1,32 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
/**
* Deprecated.
* @deprecated (4.3).
*/
package ch.boye.httpclientandroidlib.client.params;

View file

@ -0,0 +1,132 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
/**
* {@link ch.boye.httpclientandroidlib.protocol.HttpContext} attribute names for
* client side HTTP protocol processing.
*
* @since 4.0
*
* @deprecated (4.3) use {@link HttpClientContext}.
*/
@Deprecated
public interface ClientContext {
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.conn.routing.RouteInfo}
* object that represents the actual connection route.
*
* @since 4.3
*/
public static final String ROUTE = "http.route";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.conn.scheme.Scheme}
* object that represents the actual protocol scheme registry.
*/
@Deprecated
public static final String SCHEME_REGISTRY = "http.scheme-registry";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
* the actual {@link ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry} registry.
*/
public static final String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieSpec}
* object that represents the actual cookie specification.
*/
public static final String COOKIE_SPEC = "http.cookie-spec";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieOrigin}
* object that represents the actual details of the origin server.
*/
public static final String COOKIE_ORIGIN = "http.cookie-origin";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.CookieStore}
* object that represents the actual cookie store.
*/
public static final String COOKIE_STORE = "http.cookie-store";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.CredentialsProvider}
* object that represents the actual credentials provider.
*/
public static final String CREDS_PROVIDER = "http.auth.credentials-provider";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.AuthCache} object
* that represents the auth scheme cache.
*/
public static final String AUTH_CACHE = "http.auth.auth-cache";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
* object that represents the actual target authentication state.
*/
public static final String TARGET_AUTH_STATE = "http.auth.target-scope";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
* object that represents the actual proxy authentication state.
*/
public static final String PROXY_AUTH_STATE = "http.auth.proxy-scope";
/**
* @deprecated (4.1) do not use
*/
@Deprecated
public static final String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
/**
* Attribute name of a {@link java.lang.Object} object that represents
* the actual user identity such as user {@link java.security.Principal}.
*/
public static final String USER_TOKEN = "http.user-token";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
* the actual {@link ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry} registry.
*/
public static final String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
public static final String SOCKET_FACTORY_REGISTRY = "http.socket-factory-registry";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.config.RequestConfig} object that
* represents the actual request configuration.
*
* @since 4.3
*/
public static final String REQUEST_CONFIG = "http.request-config";
}

View file

@ -0,0 +1,72 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry;
import ch.boye.httpclientandroidlib.client.CookieStore;
import ch.boye.httpclientandroidlib.client.CredentialsProvider;
import ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Configuration facade for {@link HttpContext} instances.
*
* @since 4.0
*
* @deprecated (4.3) use {@link HttpClientContext}
*/
@NotThreadSafe
@Deprecated
public class ClientContextConfigurer implements ClientContext {
private final HttpContext context;
public ClientContextConfigurer (final HttpContext context) {
Args.notNull(context, "HTTP context");
this.context = context;
}
public void setCookieSpecRegistry(final CookieSpecRegistry registry) {
this.context.setAttribute(COOKIESPEC_REGISTRY, registry);
}
public void setAuthSchemeRegistry(final AuthSchemeRegistry registry) {
this.context.setAttribute(AUTHSCHEME_REGISTRY, registry);
}
public void setCookieStore(final CookieStore store) {
this.context.setAttribute(COOKIE_STORE, store);
}
public void setCredentialsProvider(final CredentialsProvider provider) {
this.context.setAttribute(CREDS_PROVIDER, provider);
}
}

View file

@ -0,0 +1,249 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.net.URI;
import java.util.List;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
import ch.boye.httpclientandroidlib.auth.AuthState;
import ch.boye.httpclientandroidlib.client.AuthCache;
import ch.boye.httpclientandroidlib.client.CookieStore;
import ch.boye.httpclientandroidlib.client.CredentialsProvider;
import ch.boye.httpclientandroidlib.client.config.RequestConfig;
import ch.boye.httpclientandroidlib.config.Lookup;
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
import ch.boye.httpclientandroidlib.cookie.CookieSpec;
import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.protocol.HttpCoreContext;
/**
* Adaptor class that provides convenience type safe setters and getters
* for common {@link HttpContext} attributes used in the course
* of HTTP request execution.
*
* @since 4.3
*/
@NotThreadSafe
public class HttpClientContext extends HttpCoreContext {
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.conn.routing.RouteInfo}
* object that represents the actual connection route.
*/
public static final String HTTP_ROUTE = "http.route";
/**
* Attribute name of a {@link List} object that represents a collection of all
* redirect locations received in the process of request execution.
*/
public static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
* the actual {@link CookieSpecProvider} registry.
*/
public static final String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieSpec}
* object that represents the actual cookie specification.
*/
public static final String COOKIE_SPEC = "http.cookie-spec";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieOrigin}
* object that represents the actual details of the origin server.
*/
public static final String COOKIE_ORIGIN = "http.cookie-origin";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.CookieStore}
* object that represents the actual cookie store.
*/
public static final String COOKIE_STORE = "http.cookie-store";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.CredentialsProvider}
* object that represents the actual credentials provider.
*/
public static final String CREDS_PROVIDER = "http.auth.credentials-provider";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.AuthCache} object
* that represents the auth scheme cache.
*/
public static final String AUTH_CACHE = "http.auth.auth-cache";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
* object that represents the actual target authentication state.
*/
public static final String TARGET_AUTH_STATE = "http.auth.target-scope";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
* object that represents the actual proxy authentication state.
*/
public static final String PROXY_AUTH_STATE = "http.auth.proxy-scope";
/**
* Attribute name of a {@link java.lang.Object} object that represents
* the actual user identity such as user {@link java.security.Principal}.
*/
public static final String USER_TOKEN = "http.user-token";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
* the actual {@link AuthSchemeProvider} registry.
*/
public static final String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
/**
* Attribute name of a {@link ch.boye.httpclientandroidlib.client.config.RequestConfig} object that
* represents the actual request configuration.
*/
public static final String REQUEST_CONFIG = "http.request-config";
public static HttpClientContext adapt(final HttpContext context) {
if (context instanceof HttpClientContext) {
return (HttpClientContext) context;
} else {
return new HttpClientContext(context);
}
}
public static HttpClientContext create() {
return new HttpClientContext(new BasicHttpContext());
}
public HttpClientContext(final HttpContext context) {
super(context);
}
public HttpClientContext() {
super();
}
public RouteInfo getHttpRoute() {
return getAttribute(HTTP_ROUTE, HttpRoute.class);
}
@SuppressWarnings("unchecked")
public List<URI> getRedirectLocations() {
return getAttribute(REDIRECT_LOCATIONS, List.class);
}
public CookieStore getCookieStore() {
return getAttribute(COOKIE_STORE, CookieStore.class);
}
public void setCookieStore(final CookieStore cookieStore) {
setAttribute(COOKIE_STORE, cookieStore);
}
public CookieSpec getCookieSpec() {
return getAttribute(COOKIE_SPEC, CookieSpec.class);
}
public CookieOrigin getCookieOrigin() {
return getAttribute(COOKIE_ORIGIN, CookieOrigin.class);
}
@SuppressWarnings("unchecked")
private <T> Lookup<T> getLookup(final String name, final Class<T> clazz) {
return getAttribute(name, Lookup.class);
}
public Lookup<CookieSpecProvider> getCookieSpecRegistry() {
return getLookup(COOKIESPEC_REGISTRY, CookieSpecProvider.class);
}
public void setCookieSpecRegistry(final Lookup<CookieSpecProvider> lookup) {
setAttribute(COOKIESPEC_REGISTRY, lookup);
}
public Lookup<AuthSchemeProvider> getAuthSchemeRegistry() {
return getLookup(AUTHSCHEME_REGISTRY, AuthSchemeProvider.class);
}
public void setAuthSchemeRegistry(final Lookup<AuthSchemeProvider> lookup) {
setAttribute(AUTHSCHEME_REGISTRY, lookup);
}
public CredentialsProvider getCredentialsProvider() {
return getAttribute(CREDS_PROVIDER, CredentialsProvider.class);
}
public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
setAttribute(CREDS_PROVIDER, credentialsProvider);
}
public AuthCache getAuthCache() {
return getAttribute(AUTH_CACHE, AuthCache.class);
}
public void setAuthCache(final AuthCache authCache) {
setAttribute(AUTH_CACHE, authCache);
}
public AuthState getTargetAuthState() {
return getAttribute(TARGET_AUTH_STATE, AuthState.class);
}
public AuthState getProxyAuthState() {
return getAttribute(PROXY_AUTH_STATE, AuthState.class);
}
public <T> T getUserToken(final Class<T> clazz) {
return getAttribute(USER_TOKEN, clazz);
}
public Object getUserToken() {
return getAttribute(USER_TOKEN);
}
public void setUserToken(final Object obj) {
setAttribute(USER_TOKEN, obj);
}
public RequestConfig getRequestConfig() {
final RequestConfig config = getAttribute(REQUEST_CONFIG, RequestConfig.class);
return config != null ? config : RequestConfig.DEFAULT;
}
public void setRequestConfig(final RequestConfig config) {
setAttribute(REQUEST_CONFIG, config);
}
}

View file

@ -0,0 +1,62 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* Class responsible for handling Content Encoding requests in HTTP.
* <p>
* Instances of this class are stateless, therefore they're thread-safe and immutable.
*
* @see "http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5"
*
* @since 4.1
*/
@Immutable
public class RequestAcceptEncoding implements HttpRequestInterceptor {
/**
* Adds the header {@code "Accept-Encoding: gzip,deflate"} to the request.
*/
public void process(
final HttpRequest request,
final HttpContext context) throws HttpException, IOException {
/* Signal support for Accept-Encoding transfer encodings. */
if (!request.containsHeader("Accept-Encoding")) {
request.addHeader("Accept-Encoding", "gzip,deflate");
}
}
}

View file

@ -0,0 +1,204 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
/* LogFactory removed by HttpClient for Android script. */
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.client.CookieStore;
import ch.boye.httpclientandroidlib.client.config.CookieSpecs;
import ch.boye.httpclientandroidlib.client.config.RequestConfig;
import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
import ch.boye.httpclientandroidlib.config.Lookup;
import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
import ch.boye.httpclientandroidlib.cookie.Cookie;
import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
import ch.boye.httpclientandroidlib.cookie.CookieSpec;
import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
import ch.boye.httpclientandroidlib.cookie.SetCookie2;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
import ch.boye.httpclientandroidlib.util.TextUtils;
/**
* Request interceptor that matches cookies available in the current
* {@link CookieStore} to the request being executed and generates
* corresponding <code>Cookie</code> request headers.
*
* @since 4.0
*/
@Immutable
public class RequestAddCookies implements HttpRequestInterceptor {
public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
public RequestAddCookies() {
super();
}
public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {
Args.notNull(request, "HTTP request");
Args.notNull(context, "HTTP context");
final String method = request.getRequestLine().getMethod();
if (method.equalsIgnoreCase("CONNECT")) {
return;
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
// Obtain cookie store
final CookieStore cookieStore = clientContext.getCookieStore();
if (cookieStore == null) {
this.log.debug("Cookie store not specified in HTTP context");
return;
}
// Obtain the registry of cookie specs
final Lookup<CookieSpecProvider> registry = clientContext.getCookieSpecRegistry();
if (registry == null) {
this.log.debug("CookieSpec registry not specified in HTTP context");
return;
}
// Obtain the target host, possibly virtual (required)
final HttpHost targetHost = clientContext.getTargetHost();
if (targetHost == null) {
this.log.debug("Target host not set in the context");
return;
}
// Obtain the route (required)
final RouteInfo route = clientContext.getHttpRoute();
if (route == null) {
this.log.debug("Connection route not set in the context");
return;
}
final RequestConfig config = clientContext.getRequestConfig();
String policy = config.getCookieSpec();
if (policy == null) {
policy = CookieSpecs.BEST_MATCH;
}
if (this.log.isDebugEnabled()) {
this.log.debug("CookieSpec selected: " + policy);
}
URI requestURI = null;
if (request instanceof HttpUriRequest) {
requestURI = ((HttpUriRequest) request).getURI();
} else {
try {
requestURI = new URI(request.getRequestLine().getUri());
} catch (final URISyntaxException ignore) {
}
}
final String path = requestURI != null ? requestURI.getPath() : null;
final String hostName = targetHost.getHostName();
int port = targetHost.getPort();
if (port < 0) {
port = route.getTargetHost().getPort();
}
final CookieOrigin cookieOrigin = new CookieOrigin(
hostName,
port >= 0 ? port : 0,
!TextUtils.isEmpty(path) ? path : "/",
route.isSecure());
// Get an instance of the selected cookie policy
final CookieSpecProvider provider = registry.lookup(policy);
if (provider == null) {
throw new HttpException("Unsupported cookie policy: " + policy);
}
final CookieSpec cookieSpec = provider.create(clientContext);
// Get all cookies available in the HTTP state
final List<Cookie> cookies = new ArrayList<Cookie>(cookieStore.getCookies());
// Find cookies matching the given origin
final List<Cookie> matchedCookies = new ArrayList<Cookie>();
final Date now = new Date();
for (final Cookie cookie : cookies) {
if (!cookie.isExpired(now)) {
if (cookieSpec.match(cookie, cookieOrigin)) {
if (this.log.isDebugEnabled()) {
this.log.debug("Cookie " + cookie + " match " + cookieOrigin);
}
matchedCookies.add(cookie);
}
} else {
if (this.log.isDebugEnabled()) {
this.log.debug("Cookie " + cookie + " expired");
}
}
}
// Generate Cookie request headers
if (!matchedCookies.isEmpty()) {
final List<Header> headers = cookieSpec.formatCookies(matchedCookies);
for (final Header header : headers) {
request.addHeader(header);
}
}
final int ver = cookieSpec.getVersion();
if (ver > 0) {
boolean needVersionHeader = false;
for (final Cookie cookie : matchedCookies) {
if (ver != cookie.getVersion() || !(cookie instanceof SetCookie2)) {
needVersionHeader = true;
}
}
if (needVersionHeader) {
final Header header = cookieSpec.getVersionHeader();
if (header != null) {
// Advertise cookie version support
request.addHeader(header);
}
}
}
// Stick the CookieSpec and CookieOrigin instances to the HTTP context
// so they could be obtained by the response interceptor
context.setAttribute(HttpClientContext.COOKIE_SPEC, cookieSpec);
context.setAttribute(HttpClientContext.COOKIE_ORIGIN, cookieOrigin);
}
}

View file

@ -0,0 +1,147 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
/* LogFactory removed by HttpClient for Android script. */
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.auth.AuthProtocolState;
import ch.boye.httpclientandroidlib.auth.AuthScheme;
import ch.boye.httpclientandroidlib.auth.AuthScope;
import ch.boye.httpclientandroidlib.auth.AuthState;
import ch.boye.httpclientandroidlib.auth.Credentials;
import ch.boye.httpclientandroidlib.client.AuthCache;
import ch.boye.httpclientandroidlib.client.CredentialsProvider;
import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Request interceptor that can preemptively authenticate against known hosts,
* if there is a cached {@link AuthScheme} instance in the local
* {@link AuthCache} associated with the given target or proxy host.
*
* @since 4.1
*/
@Immutable
public class RequestAuthCache implements HttpRequestInterceptor {
public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
public RequestAuthCache() {
super();
}
public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {
Args.notNull(request, "HTTP request");
Args.notNull(context, "HTTP context");
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final AuthCache authCache = clientContext.getAuthCache();
if (authCache == null) {
this.log.debug("Auth cache not set in the context");
return;
}
final CredentialsProvider credsProvider = clientContext.getCredentialsProvider();
if (credsProvider == null) {
this.log.debug("Credentials provider not set in the context");
return;
}
final RouteInfo route = clientContext.getHttpRoute();
if (route == null) {
this.log.debug("Route info not set in the context");
return;
}
HttpHost target = clientContext.getTargetHost();
if (target == null) {
this.log.debug("Target host not set in the context");
return;
}
if (target.getPort() < 0) {
target = new HttpHost(
target.getHostName(),
route.getTargetHost().getPort(),
target.getSchemeName());
}
final AuthState targetState = clientContext.getTargetAuthState();
if (targetState != null && targetState.getState() == AuthProtocolState.UNCHALLENGED) {
final AuthScheme authScheme = authCache.get(target);
if (authScheme != null) {
doPreemptiveAuth(target, authScheme, targetState, credsProvider);
}
}
final HttpHost proxy = route.getProxyHost();
final AuthState proxyState = clientContext.getProxyAuthState();
if (proxy != null && proxyState != null && proxyState.getState() == AuthProtocolState.UNCHALLENGED) {
final AuthScheme authScheme = authCache.get(proxy);
if (authScheme != null) {
doPreemptiveAuth(proxy, authScheme, proxyState, credsProvider);
}
}
}
private void doPreemptiveAuth(
final HttpHost host,
final AuthScheme authScheme,
final AuthState authState,
final CredentialsProvider credsProvider) {
final String schemeName = authScheme.getSchemeName();
if (this.log.isDebugEnabled()) {
this.log.debug("Re-using cached '" + schemeName + "' auth scheme for " + host);
}
final AuthScope authScope = new AuthScope(host, AuthScope.ANY_REALM, schemeName);
final Credentials creds = credsProvider.getCredentials(authScope);
if (creds != null) {
if ("BASIC".equalsIgnoreCase(authScheme.getSchemeName())) {
authState.setState(AuthProtocolState.CHALLENGED);
} else {
authState.setState(AuthProtocolState.SUCCESS);
}
authState.update(authScheme, creds);
} else {
this.log.debug("No credentials for preemptive authentication");
}
}
}

View file

@ -0,0 +1,126 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.util.Queue;
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
/* LogFactory removed by HttpClient for Android script. */
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
import ch.boye.httpclientandroidlib.auth.AuthOption;
import ch.boye.httpclientandroidlib.auth.AuthScheme;
import ch.boye.httpclientandroidlib.auth.AuthState;
import ch.boye.httpclientandroidlib.auth.AuthenticationException;
import ch.boye.httpclientandroidlib.auth.ContextAwareAuthScheme;
import ch.boye.httpclientandroidlib.auth.Credentials;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Asserts;
@Deprecated
abstract class RequestAuthenticationBase implements HttpRequestInterceptor {
final HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
public RequestAuthenticationBase() {
super();
}
void process(
final AuthState authState,
final HttpRequest request,
final HttpContext context) {
AuthScheme authScheme = authState.getAuthScheme();
Credentials creds = authState.getCredentials();
switch (authState.getState()) {
case FAILURE:
return;
case SUCCESS:
ensureAuthScheme(authScheme);
if (authScheme.isConnectionBased()) {
return;
}
break;
case CHALLENGED:
final Queue<AuthOption> authOptions = authState.getAuthOptions();
if (authOptions != null) {
while (!authOptions.isEmpty()) {
final AuthOption authOption = authOptions.remove();
authScheme = authOption.getAuthScheme();
creds = authOption.getCredentials();
authState.update(authScheme, creds);
if (this.log.isDebugEnabled()) {
this.log.debug("Generating response to an authentication challenge using "
+ authScheme.getSchemeName() + " scheme");
}
try {
final Header header = authenticate(authScheme, creds, request, context);
request.addHeader(header);
break;
} catch (final AuthenticationException ex) {
if (this.log.isWarnEnabled()) {
this.log.warn(authScheme + " authentication error: " + ex.getMessage());
}
}
}
return;
} else {
ensureAuthScheme(authScheme);
}
}
if (authScheme != null) {
try {
final Header header = authenticate(authScheme, creds, request, context);
request.addHeader(header);
} catch (final AuthenticationException ex) {
if (this.log.isErrorEnabled()) {
this.log.error(authScheme + " authentication error: " + ex.getMessage());
}
}
}
}
private void ensureAuthScheme(final AuthScheme authScheme) {
Asserts.notNull(authScheme, "Auth scheme");
}
private Header authenticate(
final AuthScheme authScheme,
final Credentials creds,
final HttpRequest request,
final HttpContext context) throws AuthenticationException {
Asserts.notNull(authScheme, "Auth scheme");
if (authScheme instanceof ContextAwareAuthScheme) {
return ((ContextAwareAuthScheme) authScheme).authenticate(creds, request, context);
} else {
return authScheme.authenticate(creds, request);
}
}
}

View file

@ -0,0 +1,92 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
/* LogFactory removed by HttpClient for Android script. */
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
import ch.boye.httpclientandroidlib.protocol.HTTP;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* This protocol interceptor is responsible for adding <code>Connection</code>
* or <code>Proxy-Connection</code> headers to the outgoing requests, which
* is essential for managing persistence of <code>HTTP/1.0</code> connections.
*
* @since 4.0
*/
@Immutable
public class RequestClientConnControl implements HttpRequestInterceptor {
public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
private static final String PROXY_CONN_DIRECTIVE = "Proxy-Connection";
public RequestClientConnControl() {
super();
}
public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {
Args.notNull(request, "HTTP request");
final String method = request.getRequestLine().getMethod();
if (method.equalsIgnoreCase("CONNECT")) {
request.setHeader(PROXY_CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
return;
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
// Obtain the client connection (required)
final RouteInfo route = clientContext.getHttpRoute();
if (route == null) {
this.log.debug("Connection route not set in the context");
return;
}
if (route.getHopCount() == 1 || route.isTunnelled()) {
if (!request.containsHeader(HTTP.CONN_DIRECTIVE)) {
request.addHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
}
}
if (route.getHopCount() == 2 && !route.isTunnelled()) {
if (!request.containsHeader(PROXY_CONN_DIRECTIVE)) {
request.addHeader(PROXY_CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
}
}
}
}

View file

@ -0,0 +1,89 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import java.util.Collection;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.client.params.ClientPNames;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Request interceptor that adds default request headers.
*
* @since 4.0
*/
@SuppressWarnings("deprecation")
@Immutable
public class RequestDefaultHeaders implements HttpRequestInterceptor {
private final Collection<? extends Header> defaultHeaders;
/**
* @since 4.3
*/
public RequestDefaultHeaders(final Collection<? extends Header> defaultHeaders) {
super();
this.defaultHeaders = defaultHeaders;
}
public RequestDefaultHeaders() {
this(null);
}
public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {
Args.notNull(request, "HTTP request");
final String method = request.getRequestLine().getMethod();
if (method.equalsIgnoreCase("CONNECT")) {
return;
}
// Add default headers
@SuppressWarnings("unchecked")
Collection<? extends Header> defHeaders = (Collection<? extends Header>)
request.getParams().getParameter(ClientPNames.DEFAULT_HEADERS);
if (defHeaders == null) {
defHeaders = this.defaultHeaders;
}
if (defHeaders != null) {
for (final Header defHeader : defHeaders) {
request.addHeader(defHeader);
}
}
}
}

View file

@ -0,0 +1,82 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
import ch.boye.httpclientandroidlib.HttpVersion;
import ch.boye.httpclientandroidlib.ProtocolVersion;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.client.config.RequestConfig;
import ch.boye.httpclientandroidlib.protocol.HTTP;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* RequestExpectContinue is responsible for enabling the 'expect-continue'
* handshake by adding <code>Expect</code> header.
* <p/>
* This interceptor takes into account {@link RequestConfig#isExpectContinueEnabled()}
* setting.
*
* @since 4.3
*/
@Immutable
public class RequestExpectContinue implements HttpRequestInterceptor {
public RequestExpectContinue() {
super();
}
public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {
Args.notNull(request, "HTTP request");
if (!request.containsHeader(HTTP.EXPECT_DIRECTIVE)) {
if (request instanceof HttpEntityEnclosingRequest) {
final ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
final HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
// Do not send the expect header if request body is known to be empty
if (entity != null
&& entity.getContentLength() != 0 && !ver.lessEquals(HttpVersion.HTTP_1_0)) {
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final RequestConfig config = clientContext.getRequestConfig();
if (config.isExpectContinueEnabled()) {
request.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
}
}
}
}
}
}

View file

@ -0,0 +1,92 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.auth.AUTH;
import ch.boye.httpclientandroidlib.auth.AuthState;
import ch.boye.httpclientandroidlib.conn.HttpRoutedConnection;
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Generates authentication header for the proxy host, if required,
* based on the actual state of the HTTP authentication context.
*
* @since 4.0
*
* @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.impl.auth.HttpAuthenticator}.
*/
@Deprecated
@Immutable
public class RequestProxyAuthentication extends RequestAuthenticationBase {
public RequestProxyAuthentication() {
super();
}
public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {
Args.notNull(request, "HTTP request");
Args.notNull(context, "HTTP context");
if (request.containsHeader(AUTH.PROXY_AUTH_RESP)) {
return;
}
final HttpRoutedConnection conn = (HttpRoutedConnection) context.getAttribute(
ExecutionContext.HTTP_CONNECTION);
if (conn == null) {
this.log.debug("HTTP connection not set in the context");
return;
}
final HttpRoute route = conn.getRoute();
if (route.isTunnelled()) {
return;
}
// Obtain authentication state
final AuthState authState = (AuthState) context.getAttribute(
ClientContext.PROXY_AUTH_STATE);
if (authState == null) {
this.log.debug("Proxy auth state not set in the context");
return;
}
if (this.log.isDebugEnabled()) {
this.log.debug("Proxy auth state: " + authState.getState());
}
process(authState, request, context);
}
}

View file

@ -0,0 +1,83 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpRequest;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.auth.AUTH;
import ch.boye.httpclientandroidlib.auth.AuthState;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Generates authentication header for the target host, if required,
* based on the actual state of the HTTP authentication context.
*
* @since 4.0
*
* @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.impl.auth.HttpAuthenticator}.
*/
@Deprecated
@Immutable
public class RequestTargetAuthentication extends RequestAuthenticationBase {
public RequestTargetAuthentication() {
super();
}
public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {
Args.notNull(request, "HTTP request");
Args.notNull(context, "HTTP context");
final String method = request.getRequestLine().getMethod();
if (method.equalsIgnoreCase("CONNECT")) {
return;
}
if (request.containsHeader(AUTH.WWW_AUTH_RESP)) {
return;
}
// Obtain authentication state
final AuthState authState = (AuthState) context.getAttribute(
ClientContext.TARGET_AUTH_STATE);
if (authState == null) {
this.log.debug("Target auth state not set in the context");
return;
}
if (this.log.isDebugEnabled()) {
this.log.debug("Target auth state: " + authState.getState());
}
process(authState, request, context);
}
}

View file

@ -0,0 +1,151 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
/* LogFactory removed by HttpClient for Android script. */
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.auth.AuthScheme;
import ch.boye.httpclientandroidlib.auth.AuthState;
import ch.boye.httpclientandroidlib.client.AuthCache;
import ch.boye.httpclientandroidlib.client.params.AuthPolicy;
import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
import ch.boye.httpclientandroidlib.impl.client.BasicAuthCache;
import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Response interceptor that adds successfully completed {@link AuthScheme}s
* to the local {@link AuthCache} instance. Cached {@link AuthScheme}s can be
* re-used when executing requests against known hosts, thus avoiding
* additional authentication round-trips.
*
* @since 4.1
*
* @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.client.AuthenticationStrategy}
*/
@Immutable
@Deprecated
public class ResponseAuthCache implements HttpResponseInterceptor {
public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
public ResponseAuthCache() {
super();
}
public void process(final HttpResponse response, final HttpContext context)
throws HttpException, IOException {
Args.notNull(response, "HTTP request");
Args.notNull(context, "HTTP context");
AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
HttpHost target = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
final AuthState targetState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
if (target != null && targetState != null) {
if (this.log.isDebugEnabled()) {
this.log.debug("Target auth state: " + targetState.getState());
}
if (isCachable(targetState)) {
final SchemeRegistry schemeRegistry = (SchemeRegistry) context.getAttribute(
ClientContext.SCHEME_REGISTRY);
if (target.getPort() < 0) {
final Scheme scheme = schemeRegistry.getScheme(target);
target = new HttpHost(target.getHostName(),
scheme.resolvePort(target.getPort()), target.getSchemeName());
}
if (authCache == null) {
authCache = new BasicAuthCache();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
}
switch (targetState.getState()) {
case CHALLENGED:
cache(authCache, target, targetState.getAuthScheme());
break;
case FAILURE:
uncache(authCache, target, targetState.getAuthScheme());
}
}
}
final HttpHost proxy = (HttpHost) context.getAttribute(ExecutionContext.HTTP_PROXY_HOST);
final AuthState proxyState = (AuthState) context.getAttribute(ClientContext.PROXY_AUTH_STATE);
if (proxy != null && proxyState != null) {
if (this.log.isDebugEnabled()) {
this.log.debug("Proxy auth state: " + proxyState.getState());
}
if (isCachable(proxyState)) {
if (authCache == null) {
authCache = new BasicAuthCache();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
}
switch (proxyState.getState()) {
case CHALLENGED:
cache(authCache, proxy, proxyState.getAuthScheme());
break;
case FAILURE:
uncache(authCache, proxy, proxyState.getAuthScheme());
}
}
}
}
private boolean isCachable(final AuthState authState) {
final AuthScheme authScheme = authState.getAuthScheme();
if (authScheme == null || !authScheme.isComplete()) {
return false;
}
final String schemeName = authScheme.getSchemeName();
return schemeName.equalsIgnoreCase(AuthPolicy.BASIC) ||
schemeName.equalsIgnoreCase(AuthPolicy.DIGEST);
}
private void cache(final AuthCache authCache, final HttpHost host, final AuthScheme authScheme) {
if (this.log.isDebugEnabled()) {
this.log.debug("Caching '" + authScheme.getSchemeName() +
"' auth scheme for " + host);
}
authCache.put(host, authScheme);
}
private void uncache(final AuthCache authCache, final HttpHost host, final AuthScheme authScheme) {
if (this.log.isDebugEnabled()) {
this.log.debug("Removing from cache '" + authScheme.getSchemeName() +
"' auth scheme for " + host);
}
authCache.remove(host);
}
}

View file

@ -0,0 +1,110 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import java.util.Locale;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HeaderElement;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.client.entity.DeflateDecompressingEntity;
import ch.boye.httpclientandroidlib.client.entity.GzipDecompressingEntity;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
/**
* {@link HttpResponseInterceptor} responsible for processing Content-Encoding
* responses.
* <p>
* Instances of this class are stateless and immutable, therefore threadsafe.
*
* @since 4.1
*
*/
@Immutable
public class ResponseContentEncoding implements HttpResponseInterceptor {
public static final String UNCOMPRESSED = "http.client.response.uncompressed";
/**
* Handles the following {@code Content-Encoding}s by
* using the appropriate decompressor to wrap the response Entity:
* <ul>
* <li>gzip - see {@link GzipDecompressingEntity}</li>
* <li>deflate - see {@link DeflateDecompressingEntity}</li>
* <li>identity - no action needed</li>
* </ul>
*
* @param response the response which contains the entity
* @param context not currently used
*
* @throws HttpException if the {@code Content-Encoding} is none of the above
*/
public void process(
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
final HttpEntity entity = response.getEntity();
// entity can be null in case of 304 Not Modified, 204 No Content or similar
// check for zero length entity.
if (entity != null && entity.getContentLength() != 0) {
final Header ceheader = entity.getContentEncoding();
if (ceheader != null) {
final HeaderElement[] codecs = ceheader.getElements();
boolean uncompressed = false;
for (final HeaderElement codec : codecs) {
final String codecname = codec.getName().toLowerCase(Locale.ENGLISH);
if ("gzip".equals(codecname) || "x-gzip".equals(codecname)) {
response.setEntity(new GzipDecompressingEntity(response.getEntity()));
uncompressed = true;
break;
} else if ("deflate".equals(codecname)) {
response.setEntity(new DeflateDecompressingEntity(response.getEntity()));
uncompressed = true;
break;
} else if ("identity".equals(codecname)) {
/* Don't need to transform the content - no-op */
return;
} else {
throw new HttpException("Unsupported Content-Coding: " + codec.getName());
}
}
if (uncompressed) {
response.removeHeaders("Content-Length");
response.removeHeaders("Content-Encoding");
response.removeHeaders("Content-MD5");
}
}
}
}
}

View file

@ -0,0 +1,156 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.protocol;
import java.io.IOException;
import java.util.List;
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
/* LogFactory removed by HttpClient for Android script. */
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HeaderIterator;
import ch.boye.httpclientandroidlib.HttpException;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.client.CookieStore;
import ch.boye.httpclientandroidlib.cookie.Cookie;
import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
import ch.boye.httpclientandroidlib.cookie.CookieSpec;
import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
import ch.boye.httpclientandroidlib.cookie.SM;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.Args;
/**
* Response interceptor that populates the current {@link CookieStore} with data
* contained in response cookies received in the given the HTTP response.
*
* @since 4.0
*/
@Immutable
public class ResponseProcessCookies implements HttpResponseInterceptor {
public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
public ResponseProcessCookies() {
super();
}
public void process(final HttpResponse response, final HttpContext context)
throws HttpException, IOException {
Args.notNull(response, "HTTP request");
Args.notNull(context, "HTTP context");
final HttpClientContext clientContext = HttpClientContext.adapt(context);
// Obtain actual CookieSpec instance
final CookieSpec cookieSpec = clientContext.getCookieSpec();
if (cookieSpec == null) {
this.log.debug("Cookie spec not specified in HTTP context");
return;
}
// Obtain cookie store
final CookieStore cookieStore = clientContext.getCookieStore();
if (cookieStore == null) {
this.log.debug("Cookie store not specified in HTTP context");
return;
}
// Obtain actual CookieOrigin instance
final CookieOrigin cookieOrigin = clientContext.getCookieOrigin();
if (cookieOrigin == null) {
this.log.debug("Cookie origin not specified in HTTP context");
return;
}
HeaderIterator it = response.headerIterator(SM.SET_COOKIE);
processCookies(it, cookieSpec, cookieOrigin, cookieStore);
// see if the cookie spec supports cookie versioning.
if (cookieSpec.getVersion() > 0) {
// process set-cookie2 headers.
// Cookie2 will replace equivalent Cookie instances
it = response.headerIterator(SM.SET_COOKIE2);
processCookies(it, cookieSpec, cookieOrigin, cookieStore);
}
}
private void processCookies(
final HeaderIterator iterator,
final CookieSpec cookieSpec,
final CookieOrigin cookieOrigin,
final CookieStore cookieStore) {
while (iterator.hasNext()) {
final Header header = iterator.nextHeader();
try {
final List<Cookie> cookies = cookieSpec.parse(header, cookieOrigin);
for (final Cookie cookie : cookies) {
try {
cookieSpec.validate(cookie, cookieOrigin);
cookieStore.addCookie(cookie);
if (this.log.isDebugEnabled()) {
this.log.debug("Cookie accepted [" + formatCooke(cookie) + "]");
}
} catch (final MalformedCookieException ex) {
if (this.log.isWarnEnabled()) {
this.log.warn("Cookie rejected [" + formatCooke(cookie) + "] "
+ ex.getMessage());
}
}
}
} catch (final MalformedCookieException ex) {
if (this.log.isWarnEnabled()) {
this.log.warn("Invalid cookie header: \""
+ header + "\". " + ex.getMessage());
}
}
}
}
private static String formatCooke(final Cookie cookie) {
final StringBuilder buf = new StringBuilder();
buf.append(cookie.getName());
buf.append("=\"");
String v = cookie.getValue();
if (v.length() > 100) {
v = v.substring(0, 100) + "...";
}
buf.append(v);
buf.append("\"");
buf.append(", version:");
buf.append(Integer.toString(cookie.getVersion()));
buf.append(", domain:");
buf.append(cookie.getDomain());
buf.append(", path:");
buf.append(cookie.getPath());
buf.append(", expiry:");
buf.append(cookie.getExpiryDate());
return buf.toString();
}
}

View file

@ -0,0 +1,31 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
/**
* Client specific HTTP protocol handlers.
*/
package ch.boye.httpclientandroidlib.client.protocol;

View file

@ -0,0 +1,86 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* A collection of utilities to workaround limitations of Java clone framework.
*
* @since 4.0
*/
@Immutable
public class CloneUtils {
/**
* @since 4.3
*/
public static <T> T cloneObject(final T obj) throws CloneNotSupportedException {
if (obj == null) {
return null;
}
if (obj instanceof Cloneable) {
final Class<?> clazz = obj.getClass ();
final Method m;
try {
m = clazz.getMethod("clone", (Class[]) null);
} catch (final NoSuchMethodException ex) {
throw new NoSuchMethodError(ex.getMessage());
}
try {
@SuppressWarnings("unchecked") // OK because clone() preserves the class
final T result = (T) m.invoke(obj, (Object []) null);
return result;
} catch (final InvocationTargetException ex) {
final Throwable cause = ex.getCause();
if (cause instanceof CloneNotSupportedException) {
throw ((CloneNotSupportedException) cause);
} else {
throw new Error("Unexpected exception", cause);
}
} catch (final IllegalAccessException ex) {
throw new IllegalAccessError(ex.getMessage());
}
} else {
throw new CloneNotSupportedException();
}
}
public static Object clone(final Object obj) throws CloneNotSupportedException {
return cloneObject(obj);
}
/**
* This class should not be instantiated.
*/
private CloneUtils() {
}
}

View file

@ -0,0 +1,250 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import java.lang.ref.SoftReference;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.util.Args;
/**
* A utility class for parsing and formatting HTTP dates as used in cookies and
* other headers. This class handles dates as defined by RFC 2616 section
* 3.3.1 as well as some other common non-standard formats.
*
* @since 4.3
*/
@Immutable
public final class DateUtils {
/**
* Date format pattern used to parse HTTP date headers in RFC 1123 format.
*/
public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
/**
* Date format pattern used to parse HTTP date headers in RFC 1036 format.
*/
public static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
/**
* Date format pattern used to parse HTTP date headers in ANSI C
* <code>asctime()</code> format.
*/
public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
private static final String[] DEFAULT_PATTERNS = new String[] {
PATTERN_RFC1123,
PATTERN_RFC1036,
PATTERN_ASCTIME
};
private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
static {
final Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(GMT);
calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
}
/**
* Parses a date value. The formats used for parsing the date value are retrieved from
* the default http params.
*
* @param dateValue the date value to parse
*
* @return the parsed date or null if input could not be parsed
*/
public static Date parseDate(final String dateValue) {
return parseDate(dateValue, null, null);
}
/**
* Parses the date value using the given date formats.
*
* @param dateValue the date value to parse
* @param dateFormats the date formats to use
*
* @return the parsed date or null if input could not be parsed
*/
public static Date parseDate(final String dateValue, final String[] dateFormats) {
return parseDate(dateValue, dateFormats, null);
}
/**
* Parses the date value using the given date formats.
*
* @param dateValue the date value to parse
* @param dateFormats the date formats to use
* @param startDate During parsing, two digit years will be placed in the range
* <code>startDate</code> to <code>startDate + 100 years</code>. This value may
* be <code>null</code>. When <code>null</code> is given as a parameter, year
* <code>2000</code> will be used.
*
* @return the parsed date or null if input could not be parsed
*/
public static Date parseDate(
final String dateValue,
final String[] dateFormats,
final Date startDate) {
Args.notNull(dateValue, "Date value");
final String[] localDateFormats = dateFormats != null ? dateFormats : DEFAULT_PATTERNS;
final Date localStartDate = startDate != null ? startDate : DEFAULT_TWO_DIGIT_YEAR_START;
String v = dateValue;
// trim single quotes around date if present
// see issue #5279
if (v.length() > 1 && v.startsWith("'") && v.endsWith("'")) {
v = v.substring (1, v.length() - 1);
}
for (final String dateFormat : localDateFormats) {
final SimpleDateFormat dateParser = DateFormatHolder.formatFor(dateFormat);
dateParser.set2DigitYearStart(localStartDate);
final ParsePosition pos = new ParsePosition(0);
final Date result = dateParser.parse(v, pos);
if (pos.getIndex() != 0) {
return result;
}
}
return null;
}
/**
* Formats the given date according to the RFC 1123 pattern.
*
* @param date The date to format.
* @return An RFC 1123 formatted date string.
*
* @see #PATTERN_RFC1123
*/
public static String formatDate(final Date date) {
return formatDate(date, PATTERN_RFC1123);
}
/**
* Formats the given date according to the specified pattern. The pattern
* must conform to that used by the {@link SimpleDateFormat simple date
* format} class.
*
* @param date The date to format.
* @param pattern The pattern to use for formatting the date.
* @return A formatted date string.
*
* @throws IllegalArgumentException If the given date pattern is invalid.
*
* @see SimpleDateFormat
*/
public static String formatDate(final Date date, final String pattern) {
Args.notNull(date, "Date");
Args.notNull(pattern, "Pattern");
final SimpleDateFormat formatter = DateFormatHolder.formatFor(pattern);
return formatter.format(date);
}
/**
* Clears thread-local variable containing {@link java.text.DateFormat} cache.
*
* @since 4.3
*/
public static void clearThreadLocal() {
DateFormatHolder.clearThreadLocal();
}
/** This class should not be instantiated. */
private DateUtils() {
}
/**
* A factory for {@link SimpleDateFormat}s. The instances are stored in a
* threadlocal way because SimpleDateFormat is not threadsafe as noted in
* {@link SimpleDateFormat its javadoc}.
*
*/
final static class DateFormatHolder {
private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>
THREADLOCAL_FORMATS = new ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>() {
@Override
protected SoftReference<Map<String, SimpleDateFormat>> initialValue() {
return new SoftReference<Map<String, SimpleDateFormat>>(
new HashMap<String, SimpleDateFormat>());
}
};
/**
* creates a {@link SimpleDateFormat} for the requested format string.
*
* @param pattern
* a non-<code>null</code> format String according to
* {@link SimpleDateFormat}. The format is not checked against
* <code>null</code> since all paths go through
* {@link DateUtils}.
* @return the requested format. This simple dateformat should not be used
* to {@link SimpleDateFormat#applyPattern(String) apply} to a
* different pattern.
*/
public static SimpleDateFormat formatFor(final String pattern) {
final SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get();
Map<String, SimpleDateFormat> formats = ref.get();
if (formats == null) {
formats = new HashMap<String, SimpleDateFormat>();
THREADLOCAL_FORMATS.set(
new SoftReference<Map<String, SimpleDateFormat>>(formats));
}
SimpleDateFormat format = formats.get(pattern);
if (format == null) {
format = new SimpleDateFormat(pattern, Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
formats.put(pattern, format);
}
return format;
}
public static void clearThreadLocal() {
THREADLOCAL_FORMATS.remove();
}
}
}

View file

@ -0,0 +1,149 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import java.io.Closeable;
import java.io.IOException;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.HttpClient;
import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
import ch.boye.httpclientandroidlib.util.EntityUtils;
/**
* Convenience methods for closing response and client objects.
*
* @since 4.2
*/
public class HttpClientUtils {
private HttpClientUtils() {
}
/**
* Unconditionally close a response.
* <p>
* Example Code:
*
* <pre>
* HttpResponse httpResponse = null;
* try {
* httpResponse = httpClient.execute(httpGet);
* } catch (Exception e) {
* // error handling
* } finally {
* HttpClientUtils.closeQuietly(httpResponse);
* }
* </pre>
*
* @param response
* the HttpResponse to release resources, may be null or already
* closed.
*
* @since 4.2
*/
public static void closeQuietly(final HttpResponse response) {
if (response != null) {
final HttpEntity entity = response.getEntity();
if (entity != null) {
try {
EntityUtils.consume(entity);
} catch (final IOException ex) {
}
}
}
}
/**
* Unconditionally close a response.
* <p>
* Example Code:
*
* <pre>
* HttpResponse httpResponse = null;
* try {
* httpResponse = httpClient.execute(httpGet);
* } catch (Exception e) {
* // error handling
* } finally {
* HttpClientUtils.closeQuietly(httpResponse);
* }
* </pre>
*
* @param response
* the HttpResponse to release resources, may be null or already
* closed.
*
* @since 4.3
*/
public static void closeQuietly(final CloseableHttpResponse response) {
if (response != null) {
try {
try {
EntityUtils.consume(response.getEntity());
} finally {
response.close();
}
} catch (final IOException ignore) {
}
}
}
/**
* Unconditionally close a httpClient. Shuts down the underlying connection
* manager and releases the resources.
* <p>
* Example Code:
*
* <pre>
* HttpClient httpClient = HttpClients.createDefault();
* try {
* httpClient.execute(request);
* } catch (Exception e) {
* // error handling
* } finally {
* HttpClientUtils.closeQuietly(httpClient);
* }
* </pre>
*
* @param httpClient
* the HttpClient to close, may be null or already closed.
* @since 4.2
*/
public static void closeQuietly(final HttpClient httpClient) {
if (httpClient != null) {
if (httpClient instanceof Closeable) {
try {
((Closeable) httpClient).close();
} catch (final IOException ignore) {
}
}
}
}
}

View file

@ -0,0 +1,42 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
/**
* Abstraction of international domain name (IDN) conversion.
*
* @since 4.0
*/
public interface Idn {
/**
* Converts a name from its punycode representation to Unicode.
* The name may be a single hostname or a dot-separated qualified domain name.
* @param punycode the Punycode representation
* @return the Unicode domain name
*/
String toUnicode(String punycode);
}

View file

@ -0,0 +1,71 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Uses the java.net.IDN class through reflection.
*
* @since 4.0
*/
@Immutable
public class JdkIdn implements Idn {
private final Method toUnicode;
/**
*
* @throws ClassNotFoundException if java.net.IDN is not available
*/
public JdkIdn() throws ClassNotFoundException {
final Class<?> clazz = Class.forName("java.net.IDN");
try {
toUnicode = clazz.getMethod("toUnicode", String.class);
} catch (final SecurityException e) {
// doesn't happen
throw new IllegalStateException(e.getMessage(), e);
} catch (final NoSuchMethodException e) {
// doesn't happen
throw new IllegalStateException(e.getMessage(), e);
}
}
public String toUnicode(final String punycode) {
try {
return (String) toUnicode.invoke(null, punycode);
} catch (final IllegalAccessException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final InvocationTargetException e) {
final Throwable t = e.getCause();
throw new RuntimeException(t.getMessage(), t);
}
}
}

View file

@ -0,0 +1,54 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Facade that provides conversion between Unicode and Punycode domain names.
* It will use an appropriate implementation.
*
* @since 4.0
*/
@Immutable
public class Punycode {
private static final Idn impl;
static {
Idn _impl;
try {
_impl = new JdkIdn();
} catch (final Exception e) {
_impl = new Rfc3492Idn();
}
impl = _impl;
}
public static String toUnicode(final String punycode) {
return impl.toUnicode(punycode);
}
}

View file

@ -0,0 +1,141 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import java.util.StringTokenizer;
import ch.boye.httpclientandroidlib.annotation.Immutable;
/**
* Implementation from pseudo code in RFC 3492.
*
* @since 4.0
*/
@Immutable
public class Rfc3492Idn implements Idn {
private static final int base = 36;
private static final int tmin = 1;
private static final int tmax = 26;
private static final int skew = 38;
private static final int damp = 700;
private static final int initial_bias = 72;
private static final int initial_n = 128;
private static final char delimiter = '-';
private static final String ACE_PREFIX = "xn--";
private int adapt(final int delta, final int numpoints, final boolean firsttime) {
int d = delta;
if (firsttime) {
d = d / damp;
} else {
d = d / 2;
}
d = d + (d / numpoints);
int k = 0;
while (d > ((base - tmin) * tmax) / 2) {
d = d / (base - tmin);
k = k + base;
}
return k + (((base - tmin + 1) * d) / (d + skew));
}
private int digit(final char c) {
if ((c >= 'A') && (c <= 'Z')) {
return (c - 'A');
}
if ((c >= 'a') && (c <= 'z')) {
return (c - 'a');
}
if ((c >= '0') && (c <= '9')) {
return (c - '0') + 26;
}
throw new IllegalArgumentException("illegal digit: "+ c);
}
public String toUnicode(final String punycode) {
final StringBuilder unicode = new StringBuilder(punycode.length());
final StringTokenizer tok = new StringTokenizer(punycode, ".");
while (tok.hasMoreTokens()) {
String t = tok.nextToken();
if (unicode.length() > 0) {
unicode.append('.');
}
if (t.startsWith(ACE_PREFIX)) {
t = decode(t.substring(4));
}
unicode.append(t);
}
return unicode.toString();
}
protected String decode(final String s) {
String input = s;
int n = initial_n;
int i = 0;
int bias = initial_bias;
final StringBuilder output = new StringBuilder(input.length());
final int lastdelim = input.lastIndexOf(delimiter);
if (lastdelim != -1) {
output.append(input.subSequence(0, lastdelim));
input = input.substring(lastdelim + 1);
}
while (input.length() > 0) {
final int oldi = i;
int w = 1;
for (int k = base;; k += base) {
if (input.length() == 0) {
break;
}
final char c = input.charAt(0);
input = input.substring(1);
final int digit = digit(c);
i = i + digit * w; // FIXME fail on overflow
final int t;
if (k <= bias + tmin) {
t = tmin;
} else if (k >= bias + tmax) {
t = tmax;
} else {
t = k - bias;
}
if (digit < t) {
break;
}
w = w * (base - t); // FIXME fail on overflow
}
bias = adapt(i - oldi, output.length() + 1, (oldi == 0));
n = n + i / (output.length() + 1); // FIXME fail on overflow
i = i % (output.length() + 1);
// {if n is a basic code point then fail}
output.insert(i, (char) n);
i++;
}
return output.toString();
}
}

View file

@ -0,0 +1,490 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import ch.boye.httpclientandroidlib.Consts;
import ch.boye.httpclientandroidlib.NameValuePair;
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
import ch.boye.httpclientandroidlib.conn.util.InetAddressUtils;
import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
/**
* Builder for {@link URI} instances.
*
* @since 4.2
*/
@NotThreadSafe
public class URIBuilder {
private String scheme;
private String encodedSchemeSpecificPart;
private String encodedAuthority;
private String userInfo;
private String encodedUserInfo;
private String host;
private int port;
private String path;
private String encodedPath;
private String encodedQuery;
private List<NameValuePair> queryParams;
private String query;
private String fragment;
private String encodedFragment;
/**
* Constructs an empty instance.
*/
public URIBuilder() {
super();
this.port = -1;
}
/**
* Construct an instance from the string which must be a valid URI.
*
* @param string a valid URI in string form
* @throws URISyntaxException if the input is not a valid URI
*/
public URIBuilder(final String string) throws URISyntaxException {
super();
digestURI(new URI(string));
}
/**
* Construct an instance from the provided URI.
* @param uri
*/
public URIBuilder(final URI uri) {
super();
digestURI(uri);
}
private List <NameValuePair> parseQuery(final String query, final Charset charset) {
if (query != null && query.length() > 0) {
return URLEncodedUtils.parse(query, charset);
}
return null;
}
/**
* Builds a {@link URI} instance.
*/
public URI build() throws URISyntaxException {
return new URI(buildString());
}
private String buildString() {
final StringBuilder sb = new StringBuilder();
if (this.scheme != null) {
sb.append(this.scheme).append(':');
}
if (this.encodedSchemeSpecificPart != null) {
sb.append(this.encodedSchemeSpecificPart);
} else {
if (this.encodedAuthority != null) {
sb.append("//").append(this.encodedAuthority);
} else if (this.host != null) {
sb.append("//");
if (this.encodedUserInfo != null) {
sb.append(this.encodedUserInfo).append("@");
} else if (this.userInfo != null) {
sb.append(encodeUserInfo(this.userInfo)).append("@");
}
if (InetAddressUtils.isIPv6Address(this.host)) {
sb.append("[").append(this.host).append("]");
} else {
sb.append(this.host);
}
if (this.port >= 0) {
sb.append(":").append(this.port);
}
}
if (this.encodedPath != null) {
sb.append(normalizePath(this.encodedPath));
} else if (this.path != null) {
sb.append(encodePath(normalizePath(this.path)));
}
if (this.encodedQuery != null) {
sb.append("?").append(this.encodedQuery);
} else if (this.queryParams != null) {
sb.append("?").append(encodeUrlForm(this.queryParams));
} else if (this.query != null) {
sb.append("?").append(encodeUric(this.query));
}
}
if (this.encodedFragment != null) {
sb.append("#").append(this.encodedFragment);
} else if (this.fragment != null) {
sb.append("#").append(encodeUric(this.fragment));
}
return sb.toString();
}
private void digestURI(final URI uri) {
this.scheme = uri.getScheme();
this.encodedSchemeSpecificPart = uri.getRawSchemeSpecificPart();
this.encodedAuthority = uri.getRawAuthority();
this.host = uri.getHost();
this.port = uri.getPort();
this.encodedUserInfo = uri.getRawUserInfo();
this.userInfo = uri.getUserInfo();
this.encodedPath = uri.getRawPath();
this.path = uri.getPath();
this.encodedQuery = uri.getRawQuery();
this.queryParams = parseQuery(uri.getRawQuery(), Consts.UTF_8);
this.encodedFragment = uri.getRawFragment();
this.fragment = uri.getFragment();
}
private String encodeUserInfo(final String userInfo) {
return URLEncodedUtils.encUserInfo(userInfo, Consts.UTF_8);
}
private String encodePath(final String path) {
return URLEncodedUtils.encPath(path, Consts.UTF_8);
}
private String encodeUrlForm(final List<NameValuePair> params) {
return URLEncodedUtils.format(params, Consts.UTF_8);
}
private String encodeUric(final String fragment) {
return URLEncodedUtils.encUric(fragment, Consts.UTF_8);
}
/**
* Sets URI scheme.
*/
public URIBuilder setScheme(final String scheme) {
this.scheme = scheme;
return this;
}
/**
* Sets URI user info. The value is expected to be unescaped and may contain non ASCII
* characters.
*/
public URIBuilder setUserInfo(final String userInfo) {
this.userInfo = userInfo;
this.encodedSchemeSpecificPart = null;
this.encodedAuthority = null;
this.encodedUserInfo = null;
return this;
}
/**
* Sets URI user info as a combination of username and password. These values are expected to
* be unescaped and may contain non ASCII characters.
*/
public URIBuilder setUserInfo(final String username, final String password) {
return setUserInfo(username + ':' + password);
}
/**
* Sets URI host.
*/
public URIBuilder setHost(final String host) {
this.host = host;
this.encodedSchemeSpecificPart = null;
this.encodedAuthority = null;
return this;
}
/**
* Sets URI port.
*/
public URIBuilder setPort(final int port) {
this.port = port < 0 ? -1 : port;
this.encodedSchemeSpecificPart = null;
this.encodedAuthority = null;
return this;
}
/**
* Sets URI path. The value is expected to be unescaped and may contain non ASCII characters.
*/
public URIBuilder setPath(final String path) {
this.path = path;
this.encodedSchemeSpecificPart = null;
this.encodedPath = null;
return this;
}
/**
* Removes URI query.
*/
public URIBuilder removeQuery() {
this.queryParams = null;
this.query = null;
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
return this;
}
/**
* Sets URI query.
* <p>
* The value is expected to be encoded form data.
*
* @deprecated (4.3) use {@link #setParameters(List)} or {@link #setParameters(NameValuePair...)}
*
* @see URLEncodedUtils#parse
*/
@Deprecated
public URIBuilder setQuery(final String query) {
this.queryParams = parseQuery(query, Consts.UTF_8);
this.query = null;
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
return this;
}
/**
* Sets URI query parameters. The parameter name / values are expected to be unescaped
* and may contain non ASCII characters.
* <p/>
* Please note query parameters and custom query component are mutually exclusive. This method
* will remove custom query if present.
*
* @since 4.3
*/
public URIBuilder setParameters(final List <NameValuePair> nvps) {
if (this.queryParams == null) {
this.queryParams = new ArrayList<NameValuePair>();
} else {
this.queryParams.clear();
}
this.queryParams.addAll(nvps);
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
this.query = null;
return this;
}
/**
* Adds URI query parameters. The parameter name / values are expected to be unescaped
* and may contain non ASCII characters.
* <p/>
* Please note query parameters and custom query component are mutually exclusive. This method
* will remove custom query if present.
*
* @since 4.3
*/
public URIBuilder addParameters(final List <NameValuePair> nvps) {
if (this.queryParams == null) {
this.queryParams = new ArrayList<NameValuePair>();
}
this.queryParams.addAll(nvps);
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
this.query = null;
return this;
}
/**
* Sets URI query parameters. The parameter name / values are expected to be unescaped
* and may contain non ASCII characters.
* <p/>
* Please note query parameters and custom query component are mutually exclusive. This method
* will remove custom query if present.
*
* @since 4.3
*/
public URIBuilder setParameters(final NameValuePair... nvps) {
if (this.queryParams == null) {
this.queryParams = new ArrayList<NameValuePair>();
} else {
this.queryParams.clear();
}
for (final NameValuePair nvp: nvps) {
this.queryParams.add(nvp);
}
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
this.query = null;
return this;
}
/**
* Adds parameter to URI query. The parameter name and value are expected to be unescaped
* and may contain non ASCII characters.
* <p/>
* Please note query parameters and custom query component are mutually exclusive. This method
* will remove custom query if present.
*/
public URIBuilder addParameter(final String param, final String value) {
if (this.queryParams == null) {
this.queryParams = new ArrayList<NameValuePair>();
}
this.queryParams.add(new BasicNameValuePair(param, value));
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
this.query = null;
return this;
}
/**
* Sets parameter of URI query overriding existing value if set. The parameter name and value
* are expected to be unescaped and may contain non ASCII characters.
* <p/>
* Please note query parameters and custom query component are mutually exclusive. This method
* will remove custom query if present.
*/
public URIBuilder setParameter(final String param, final String value) {
if (this.queryParams == null) {
this.queryParams = new ArrayList<NameValuePair>();
}
if (!this.queryParams.isEmpty()) {
for (final Iterator<NameValuePair> it = this.queryParams.iterator(); it.hasNext(); ) {
final NameValuePair nvp = it.next();
if (nvp.getName().equals(param)) {
it.remove();
}
}
}
this.queryParams.add(new BasicNameValuePair(param, value));
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
this.query = null;
return this;
}
/**
* Clears URI query parameters.
*
* @since 4.3
*/
public URIBuilder clearParameters() {
this.queryParams = null;
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
return this;
}
/**
* Sets custom URI query. The value is expected to be unescaped and may contain non ASCII
* characters.
* <p/>
* Please note query parameters and custom query component are mutually exclusive. This method
* will remove query parameters if present.
*
* @since 4.3
*/
public URIBuilder setCustomQuery(final String query) {
this.query = query;
this.encodedQuery = null;
this.encodedSchemeSpecificPart = null;
this.queryParams = null;
return this;
}
/**
* Sets URI fragment. The value is expected to be unescaped and may contain non ASCII
* characters.
*/
public URIBuilder setFragment(final String fragment) {
this.fragment = fragment;
this.encodedFragment = null;
return this;
}
/**
* @since 4.3
*/
public boolean isAbsolute() {
return this.scheme != null;
}
/**
* @since 4.3
*/
public boolean isOpaque() {
return this.path == null;
}
public String getScheme() {
return this.scheme;
}
public String getUserInfo() {
return this.userInfo;
}
public String getHost() {
return this.host;
}
public int getPort() {
return this.port;
}
public String getPath() {
return this.path;
}
public List<NameValuePair> getQueryParams() {
if (this.queryParams != null) {
return new ArrayList<NameValuePair>(this.queryParams);
} else {
return new ArrayList<NameValuePair>();
}
}
public String getFragment() {
return this.fragment;
}
@Override
public String toString() {
return buildString();
}
private static String normalizePath(final String path) {
String s = path;
if (s == null) {
return null;
}
int n = 0;
for (; n < s.length(); n++) {
if (s.charAt(n) != '/') {
break;
}
}
if (n > 1) {
s = s.substring(n - 1);
}
return s;
}
}

View file

@ -0,0 +1,428 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package ch.boye.httpclientandroidlib.client.utils;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Locale;
import java.util.Stack;
import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.annotation.Immutable;
import ch.boye.httpclientandroidlib.util.Args;
import ch.boye.httpclientandroidlib.util.TextUtils;
/**
* A collection of utilities for {@link URI URIs}, to workaround
* bugs within the class or for ease-of-use features.
*
* @since 4.0
*/
@Immutable
public class URIUtils {
/**
* Constructs a {@link URI} using all the parameters. This should be
* used instead of
* {@link URI#URI(String, String, String, int, String, String, String)}
* or any of the other URI multi-argument URI constructors.
*
* @param scheme
* Scheme name
* @param host
* Host name
* @param port
* Port number
* @param path
* Path
* @param query
* Query
* @param fragment
* Fragment
*
* @throws URISyntaxException
* If both a scheme and a path are given but the path is
* relative, if the URI string constructed from the given
* components violates RFC&nbsp;2396, or if the authority
* component of the string is present but cannot be parsed
* as a server-based authority
*
* @deprecated (4.2) use {@link URIBuilder}.
*/
@Deprecated
public static URI createURI(
final String scheme,
final String host,
final int port,
final String path,
final String query,
final String fragment) throws URISyntaxException {
final StringBuilder buffer = new StringBuilder();
if (host != null) {
if (scheme != null) {
buffer.append(scheme);
buffer.append("://");
}
buffer.append(host);
if (port > 0) {
buffer.append(':');
buffer.append(port);
}
}
if (path == null || !path.startsWith("/")) {
buffer.append('/');
}
if (path != null) {
buffer.append(path);
}
if (query != null) {
buffer.append('?');
buffer.append(query);
}
if (fragment != null) {
buffer.append('#');
buffer.append(fragment);
}
return new URI(buffer.toString());
}
/**
* A convenience method for creating a new {@link URI} whose scheme, host
* and port are taken from the target host, but whose path, query and
* fragment are taken from the existing URI. The fragment is only used if
* dropFragment is false. The path is set to "/" if not explicitly specified.
*
* @param uri
* Contains the path, query and fragment to use.
* @param target
* Contains the scheme, host and port to use.
* @param dropFragment
* True if the fragment should not be copied.
*
* @throws URISyntaxException
* If the resulting URI is invalid.
*/
public static URI rewriteURI(
final URI uri,
final HttpHost target,
final boolean dropFragment) throws URISyntaxException {
Args.notNull(uri, "URI");
if (uri.isOpaque()) {
return uri;
}
final URIBuilder uribuilder = new URIBuilder(uri);
if (target != null) {
uribuilder.setScheme(target.getSchemeName());
uribuilder.setHost(target.getHostName());
uribuilder.setPort(target.getPort());
} else {
uribuilder.setScheme(null);
uribuilder.setHost(null);
uribuilder.setPort(-1);
}
if (dropFragment) {
uribuilder.setFragment(null);
}
if (TextUtils.isEmpty(uribuilder.getPath())) {
uribuilder.setPath("/");
}
return uribuilder.build();
}
/**
* A convenience method for
* {@link URIUtils#rewriteURI(URI, HttpHost, boolean)} that always keeps the
* fragment.
*/
public static URI rewriteURI(
final URI uri,
final HttpHost target) throws URISyntaxException {
return rewriteURI(uri, target, false);
}
/**
* A convenience method that creates a new {@link URI} whose scheme, host, port, path,
* query are taken from the existing URI, dropping any fragment or user-information.
* The path is set to "/" if not explicitly specified. The existing URI is returned
* unmodified if it has no fragment or user-information and has a path.
*
* @param uri
* original URI.
* @throws URISyntaxException
* If the resulting URI is invalid.
*/
public static URI rewriteURI(final URI uri) throws URISyntaxException {
Args.notNull(uri, "URI");
if (uri.isOpaque()) {
return uri;
}
final URIBuilder uribuilder = new URIBuilder(uri);
if (uribuilder.getUserInfo() != null) {
uribuilder.setUserInfo(null);
}
if (TextUtils.isEmpty(uribuilder.getPath())) {
uribuilder.setPath("/");
}
if (uribuilder.getHost() != null) {
uribuilder.setHost(uribuilder.getHost().toLowerCase(Locale.ENGLISH));
}
uribuilder.setFragment(null);
return uribuilder.build();
}
/**
* Resolves a URI reference against a base URI. Work-around for bug in
* java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
*
* @param baseURI the base URI
* @param reference the URI reference
* @return the resulting URI
*/
public static URI resolve(final URI baseURI, final String reference) {
return URIUtils.resolve(baseURI, URI.create(reference));
}
/**
* Resolves a URI reference against a base URI. Work-around for bugs in
* java.net.URI (e.g. <http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
*
* @param baseURI the base URI
* @param reference the URI reference
* @return the resulting URI
*/
public static URI resolve(final URI baseURI, final URI reference){
Args.notNull(baseURI, "Base URI");
Args.notNull(reference, "Reference URI");
URI ref = reference;
final String s = ref.toString();
if (s.startsWith("?")) {
return resolveReferenceStartingWithQueryString(baseURI, ref);
}
final boolean emptyReference = s.length() == 0;
if (emptyReference) {
ref = URI.create("#");
}
URI resolved = baseURI.resolve(ref);
if (emptyReference) {
final String resolvedString = resolved.toString();
resolved = URI.create(resolvedString.substring(0,
resolvedString.indexOf('#')));
}
return normalizeSyntax(resolved);
}
/**
* Resolves a reference starting with a query string.
*
* @param baseURI the base URI
* @param reference the URI reference starting with a query string
* @return the resulting URI
*/
private static URI resolveReferenceStartingWithQueryString(
final URI baseURI, final URI reference) {
String baseUri = baseURI.toString();
baseUri = baseUri.indexOf('?') > -1 ?
baseUri.substring(0, baseUri.indexOf('?')) : baseUri;
return URI.create(baseUri + reference.toString());
}
/**
* Removes dot segments according to RFC 3986, section 5.2.4 and
* Syntax-Based Normalization according to RFC 3986, section 6.2.2.
*
* @param uri the original URI
* @return the URI without dot segments
*/
private static URI normalizeSyntax(final URI uri) {
if (uri.isOpaque() || uri.getAuthority() == null) {
// opaque and file: URIs
return uri;
}
Args.check(uri.isAbsolute(), "Base URI must be absolute");
final String path = uri.getPath() == null ? "" : uri.getPath();
final String[] inputSegments = path.split("/");
final Stack<String> outputSegments = new Stack<String>();
for (final String inputSegment : inputSegments) {
if ((inputSegment.length() == 0)
|| (".".equals(inputSegment))) {
// Do nothing
} else if ("..".equals(inputSegment)) {
if (!outputSegments.isEmpty()) {
outputSegments.pop();
}
} else {
outputSegments.push(inputSegment);
}
}
final StringBuilder outputBuffer = new StringBuilder();
for (final String outputSegment : outputSegments) {
outputBuffer.append('/').append(outputSegment);
}
if (path.lastIndexOf('/') == path.length() - 1) {
// path.endsWith("/") || path.equals("")
outputBuffer.append('/');
}
try {
final String scheme = uri.getScheme().toLowerCase(Locale.ENGLISH);
final String auth = uri.getAuthority().toLowerCase(Locale.ENGLISH);
final URI ref = new URI(scheme, auth, outputBuffer.toString(),
null, null);
if (uri.getQuery() == null && uri.getFragment() == null) {
return ref;
}
final StringBuilder normalized = new StringBuilder(
ref.toASCIIString());
if (uri.getQuery() != null) {
// query string passed through unchanged
normalized.append('?').append(uri.getRawQuery());
}
if (uri.getFragment() != null) {
// fragment passed through unchanged
normalized.append('#').append(uri.getRawFragment());
}
return URI.create(normalized.toString());
} catch (final URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Extracts target host from the given {@link URI}.
*
* @param uri
* @return the target host if the URI is absolute or <code>null</null> if the URI is
* relative or does not contain a valid host name.
*
* @since 4.1
*/
public static HttpHost extractHost(final URI uri) {
if (uri == null) {
return null;
}
HttpHost target = null;
if (uri.isAbsolute()) {
int port = uri.getPort(); // may be overridden later
String host = uri.getHost();
if (host == null) { // normal parse failed; let's do it ourselves
// authority does not seem to care about the valid character-set for host names
host = uri.getAuthority();
if (host != null) {
// Strip off any leading user credentials
final int at = host.indexOf('@');
if (at >= 0) {
if (host.length() > at+1 ) {
host = host.substring(at+1);
} else {
host = null; // @ on its own
}
}
// Extract the port suffix, if present
if (host != null) {
final int colon = host.indexOf(':');
if (colon >= 0) {
final int pos = colon + 1;
int len = 0;
for (int i = pos; i < host.length(); i++) {
if (Character.isDigit(host.charAt(i))) {
len++;
} else {
break;
}
}
if (len > 0) {
try {
port = Integer.parseInt(host.substring(pos, pos + len));
} catch (final NumberFormatException ex) {
}
}
host = host.substring(0, colon);
}
}
}
}
final String scheme = uri.getScheme();
if (!TextUtils.isBlank(host)) {
target = new HttpHost(host, port, scheme);
}
}
return target;
}
/**
* Derives the interpreted (absolute) URI that was used to generate the last
* request. This is done by extracting the request-uri and target origin for
* the last request and scanning all the redirect locations for the last
* fragment identifier, then combining the result into a {@link URI}.
*
* @param originalURI
* original request before any redirects
* @param target
* if the last URI is relative, it is resolved against this target,
* or <code>null</code> if not available.
* @param redirects
* collection of redirect locations since the original request
* or <code>null</code> if not available.
* @return interpreted (absolute) URI
*/
public static URI resolve(
final URI originalURI,
final HttpHost target,
final List<URI> redirects) throws URISyntaxException {
Args.notNull(originalURI, "Request URI");
final URIBuilder uribuilder;
if (redirects == null || redirects.isEmpty()) {
uribuilder = new URIBuilder(originalURI);
} else {
uribuilder = new URIBuilder(redirects.get(redirects.size() - 1));
String frag = uribuilder.getFragment();
// read interpreted fragment identifier from redirect locations
for (int i = redirects.size() - 1; frag == null && i >= 0; i--) {
frag = redirects.get(i).getFragment();
}
uribuilder.setFragment(frag);
}
// read interpreted fragment identifier from original request
if (uribuilder.getFragment() == null) {
uribuilder.setFragment(originalURI.getFragment());
}
// last target origin
if (target != null && !uribuilder.isAbsolute()) {
uribuilder.setScheme(target.getSchemeName());
uribuilder.setHost(target.getHostName());
uribuilder.setPort(target.getPort());
}
return uribuilder.build();
}
/**
* This class should not be instantiated.
*/
private URIUtils() {
}
}

Some files were not shown because too many files have changed in this diff Show more