Index: 3rdParty_sources/versions.txt =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/versions.txt,v diff -u -r1.1 -r1.2 --- 3rdParty_sources/versions.txt 17 Aug 2012 15:17:21 -0000 1.1 +++ 3rdParty_sources/versions.txt 22 Aug 2012 17:30:39 -0000 1.2 @@ -9,6 +9,8 @@ CKEditor 3.6.2 +Commons HttpClient 3.0 + Hibernate Core 3.3.1 GA jbosscache 3.1.0.CR1 Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/AutoCloseInputStream.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/AutoCloseInputStream.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/AutoCloseInputStream.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,185 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/AutoCloseInputStream.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Closes an underlying stream as soon as the end of the stream is reached, and + * notifies a client when it has done so. + * + * @author Ortwin Glueck + * @author Eric Johnson + * @author Mike Bowler + * + * @since 2.0 + */ +class AutoCloseInputStream extends FilterInputStream { + + /** + * True if this stream is open. Assume that the underlying stream + * is open until we get an EOF indication. + */ + private boolean streamOpen = true; + + /** True if the stream closed itself. */ + private boolean selfClosed = false; + + /** + * The watcher is notified when the contents of the stream have + * been exhausted + */ + private ResponseConsumedWatcher watcher = null; + + /** + * Create a new auto closing stream for the provided connection + * + * @param in the input stream to read from + * @param watcher To be notified when the contents of the stream have been + * consumed. + */ + public AutoCloseInputStream( + final InputStream in, final ResponseConsumedWatcher watcher) { + super(in); + this.watcher = watcher; + } + + /** + * Reads the next byte of data from the input stream. + * + * @throws IOException when there is an error reading + * @return the character read, or -1 for EOF + */ + public int read() throws IOException { + int l = -1; + + if (isReadAllowed()) { + // underlying stream not closed, go ahead and read. + l = super.read(); + checkClose(l); + } + + return l; + } + + /** + * Reads up to len bytes of data from the stream. + * + * @param b a byte array to read data into + * @param off an offset within the array to store data + * @param len the maximum number of bytes to read + * @return the number of bytes read or -1 for EOF + * @throws IOException if there are errors reading + */ + public int read(byte[] b, int off, int len) throws IOException { + int l = -1; + + if (isReadAllowed()) { + l = super.read(b, off, len); + checkClose(l); + } + + return l; + } + + /** + * Reads some number of bytes from the input stream and stores them into the + * buffer array b. + * + * @param b a byte array to read data into + * @return the number of bytes read or -1 for EOF + * @throws IOException if there are errors reading + */ + public int read(byte[] b) throws IOException { + int l = -1; + + if (isReadAllowed()) { + l = super.read(b); + checkClose(l); + } + return l; + } + + /** + * Close the stream, and also close the underlying stream if it is not + * already closed. + * @throws IOException If an IO problem occurs. + */ + public void close() throws IOException { + if (!selfClosed) { + selfClosed = true; + notifyWatcher(); + } + } + + /** + * Close the underlying stream should the end of the stream arrive. + * + * @param readResult The result of the read operation to check. + * @throws IOException If an IO problem occurs. + */ + private void checkClose(int readResult) throws IOException { + if (readResult == -1) { + notifyWatcher(); + } + } + + /** + * See whether a read of the underlying stream should be allowed, and if + * not, check to see whether our stream has already been closed! + * + * @return true if it is still OK to read from the stream. + * @throws IOException If an IO problem occurs. + */ + private boolean isReadAllowed() throws IOException { + if (!streamOpen && selfClosed) { + throw new IOException("Attempted read on closed stream."); + } + return streamOpen; + } + + /** + * Notify the watcher that the contents have been consumed. + * @throws IOException If an IO problem occurs. + */ + private void notifyWatcher() throws IOException { + if (streamOpen) { + super.close(); + streamOpen = false; + + if (watcher != null) { + watcher.responseConsumed(); + } + } + } +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedInputStream.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedInputStream.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedInputStream.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,372 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedInputStream.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.httpclient.util.ExceptionUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + *

Transparently coalesces chunks of a HTTP stream that uses + * Transfer-Encoding chunked.

+ * + *

Note that this class NEVER closes the underlying stream, even when close + * gets called. Instead, it will read until the "end" of its chunking on close, + * which allows for the seamless invocation of subsequent HTTP 1.1 calls, while + * not requiring the client to remember to read the entire contents of the + * response.

+ * + * @author Ortwin Glueck + * @author Sean C. Sullivan + * @author Martin Elwin + * @author Eric Johnson + * @author Mike Bowler + * @author Michael Becke + * @author Oleg Kalnichevski + * + * @since 2.0 + * + */ +public class ChunkedInputStream extends InputStream { + /** The inputstream that we're wrapping */ + private InputStream in; + + /** The chunk size */ + private int chunkSize; + + /** The current position within the current chunk */ + private int pos; + + /** True if we'are at the beginning of stream */ + private boolean bof = true; + + /** True if we've reached the end of stream */ + private boolean eof = false; + + /** True if this stream is closed */ + private boolean closed = false; + + /** The method that this stream came from */ + private HttpMethod method = null; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(ChunkedInputStream.class); + + /** + * ChunkedInputStream constructor that associates the chunked input stream with a + * {@link HttpMethod HTTP method}. Usually it should be the same {@link HttpMethod + * HTTP method} the chunked input stream originates from. If chunked input stream + * contains any footers (trailing headers), they will be added to the associated + * {@link HttpMethod HTTP method}. + * + * @param in the raw input stream + * @param method the HTTP method to associate this input stream with. Can be null. + * + * @throws IOException If an IO error occurs + */ + public ChunkedInputStream( + final InputStream in, final HttpMethod method) throws IOException { + + if (in == null) { + throw new IllegalArgumentException("InputStream parameter may not be null"); + } + this.in = in; + this.method = method; + this.pos = 0; + } + + /** + * ChunkedInputStream constructor + * + * @param in the raw input stream + * + * @throws IOException If an IO error occurs + */ + public ChunkedInputStream(final InputStream in) throws IOException { + this(in, null); + } + + /** + *

Returns all the data in a chunked stream in coalesced form. A chunk + * is followed by a CRLF. The method returns -1 as soon as a chunksize of 0 + * is detected.

+ * + *

Trailer headers are read automcatically at the end of the stream and + * can be obtained with the getResponseFooters() method.

+ * + * @return -1 of the end of the stream has been reached or the next data + * byte + * @throws IOException If an IO problem occurs + * + * @see HttpMethod#getResponseFooters() + */ + public int read() throws IOException { + + if (closed) { + throw new IOException("Attempted read from closed stream."); + } + if (eof) { + return -1; + } + if (pos >= chunkSize) { + nextChunk(); + if (eof) { + return -1; + } + } + pos++; + return in.read(); + } + + /** + * Read some bytes from the stream. + * @param b The byte array that will hold the contents from the stream. + * @param off The offset into the byte array at which bytes will start to be + * placed. + * @param len the maximum number of bytes that can be returned. + * @return The number of bytes returned or -1 if the end of stream has been + * reached. + * @see java.io.InputStream#read(byte[], int, int) + * @throws IOException if an IO problem occurs. + */ + public int read (byte[] b, int off, int len) throws IOException { + + if (closed) { + throw new IOException("Attempted read from closed stream."); + } + + if (eof) { + return -1; + } + if (pos >= chunkSize) { + nextChunk(); + if (eof) { + return -1; + } + } + len = Math.min(len, chunkSize - pos); + int count = in.read(b, off, len); + pos += count; + return count; + } + + /** + * Read some bytes from the stream. + * @param b The byte array that will hold the contents from the stream. + * @return The number of bytes returned or -1 if the end of stream has been + * reached. + * @see java.io.InputStream#read(byte[]) + * @throws IOException if an IO problem occurs. + */ + public int read (byte[] b) throws IOException { + return read(b, 0, b.length); + } + + /** + * Read the CRLF terminator. + * @throws IOException If an IO error occurs. + */ + private void readCRLF() throws IOException { + int cr = in.read(); + int lf = in.read(); + if ((cr != '\r') || (lf != '\n')) { + throw new IOException( + "CRLF expected at end of chunk: " + cr + "/" + lf); + } + } + + + /** + * Read the next chunk. + * @throws IOException If an IO error occurs. + */ + private void nextChunk() throws IOException { + if (!bof) { + readCRLF(); + } + chunkSize = getChunkSizeFromInputStream(in); + bof = false; + pos = 0; + if (chunkSize == 0) { + eof = true; + parseTrailerHeaders(); + } + } + + /** + * Expects the stream to start with a chunksize in hex with optional + * comments after a semicolon. The line must end with a CRLF: "a3; some + * comment\r\n" Positions the stream at the start of the next line. + * + * @param in The new input stream. + * @param required true if a valid chunk must be present, + * false otherwise. + * + * @return the chunk size as integer + * + * @throws IOException when the chunk size could not be parsed + */ + private static int getChunkSizeFromInputStream(final InputStream in) + throws IOException { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // States: 0=normal, 1=\r was scanned, 2=inside quoted string, -1=end + int state = 0; + while (state != -1) { + int b = in.read(); + if (b == -1) { + throw new IOException("chunked stream ended unexpectedly"); + } + switch (state) { + case 0: + switch (b) { + case '\r': + state = 1; + break; + case '\"': + state = 2; + /* fall through */ + default: + baos.write(b); + } + break; + + case 1: + if (b == '\n') { + state = -1; + } else { + // this was not CRLF + throw new IOException("Protocol violation: Unexpected" + + " single newline character in chunk size"); + } + break; + + case 2: + switch (b) { + case '\\': + b = in.read(); + baos.write(b); + break; + case '\"': + state = 0; + /* fall through */ + default: + baos.write(b); + } + break; + default: throw new RuntimeException("assertion failed"); + } + } + + //parse data + String dataString = EncodingUtil.getAsciiString(baos.toByteArray()); + int separator = dataString.indexOf(';'); + dataString = (separator > 0) + ? dataString.substring(0, separator).trim() + : dataString.trim(); + + int result; + try { + result = Integer.parseInt(dataString.trim(), 16); + } catch (NumberFormatException e) { + throw new IOException ("Bad chunk size: " + dataString); + } + return result; + } + + /** + * Reads and stores the Trailer headers. + * @throws IOException If an IO problem occurs + */ + private void parseTrailerHeaders() throws IOException { + Header[] footers = null; + try { + String charset = "US-ASCII"; + if (this.method != null) { + charset = this.method.getParams().getHttpElementCharset(); + } + footers = HttpParser.parseHeaders(in, charset); + } catch(HttpException e) { + LOG.error("Error parsing trailer headers", e); + IOException ioe = new IOException(e.getMessage()); + ExceptionUtil.initCause(ioe, e); + throw ioe; + } + if (this.method != null) { + for (int i = 0; i < footers.length; i++) { + this.method.addResponseFooter(footers[i]); + } + } + } + + /** + * Upon close, this reads the remainder of the chunked message, + * leaving the underlying socket at a position to start reading the + * next response without scanning. + * @throws IOException If an IO problem occurs. + */ + public void close() throws IOException { + if (!closed) { + try { + if (!eof) { + exhaustInputStream(this); + } + } finally { + eof = true; + closed = true; + } + } + } + + /** + * Exhaust an input stream, reading until EOF has been encountered. + * + *

Note that this function is intended as a non-public utility. + * This is a little weird, but it seemed silly to make a utility + * class for this one function, so instead it is just static and + * shared that way.

+ * + * @param inStream The {@link InputStream} to exhaust. + * @throws IOException If an IO problem occurs + */ + static void exhaustInputStream(InputStream inStream) throws IOException { + // read and discard the remainder of the message + byte buffer[] = new byte[1024]; + while (inStream.read(buffer) >= 0) { + ; + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedOutputStream.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedOutputStream.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedOutputStream.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,201 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ChunkedOutputStream.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.commons.httpclient.util.EncodingUtil; + +/** + * Implements HTTP chunking support. Writes are buffered to an internal buffer (2048 default size). + * Chunks are guaranteed to be at least as large as the buffer size (except for the last chunk). + * + * @author Mohammad Rezaei, Goldman, Sachs & Co. + */ +public class ChunkedOutputStream extends OutputStream { + + // ------------------------------------------------------- Static Variables + private static final byte CRLF[] = new byte[] {(byte) 13, (byte) 10}; + + /** End chunk */ + private static final byte ENDCHUNK[] = CRLF; + + /** 0 */ + private static final byte ZERO[] = new byte[] {(byte) '0'}; + + // ----------------------------------------------------- Instance Variables + private OutputStream stream = null; + + private byte[] cache; + + private int cachePosition = 0; + + private boolean wroteLastChunk = false; + + // ----------------------------------------------------------- Constructors + /** + * Wraps a stream and chunks the output. + * @param stream to wrap + * @param bufferSize minimum chunk size (excluding last chunk) + * @throws IOException + * + * @since 3.0 + */ + public ChunkedOutputStream(OutputStream stream, int bufferSize) throws IOException { + this.cache = new byte[bufferSize]; + this.stream = stream; + } + + /** + * Wraps a stream and chunks the output. The default buffer size of 2048 was chosen because + * the chunk overhead is less than 0.5% + * @param stream + * @throws IOException + */ + public ChunkedOutputStream(OutputStream stream) throws IOException { + this(stream, 2048); + } + + // ----------------------------------------------------------- Internal methods + /** + * Writes the cache out onto the underlying stream + * @throws IOException + * + * @since 3.0 + */ + protected void flushCache() throws IOException { + if (cachePosition > 0) { + byte chunkHeader[] = EncodingUtil.getAsciiBytes( + Integer.toHexString(cachePosition) + "\r\n"); + stream.write(chunkHeader, 0, chunkHeader.length); + stream.write(cache, 0, cachePosition); + stream.write(ENDCHUNK, 0, ENDCHUNK.length); + cachePosition = 0; + } + } + + /** + * Writes the cache and bufferToAppend to the underlying stream + * as one large chunk + * @param bufferToAppend + * @param off + * @param len + * @throws IOException + * + * @since 3.0 + */ + protected void flushCacheWithAppend(byte bufferToAppend[], int off, int len) throws IOException { + byte chunkHeader[] = EncodingUtil.getAsciiBytes( + Integer.toHexString(cachePosition + len) + "\r\n"); + stream.write(chunkHeader, 0, chunkHeader.length); + stream.write(cache, 0, cachePosition); + stream.write(bufferToAppend, off, len); + stream.write(ENDCHUNK, 0, ENDCHUNK.length); + cachePosition = 0; + } + + protected void writeClosingChunk() throws IOException { + // Write the final chunk. + + stream.write(ZERO, 0, ZERO.length); + stream.write(CRLF, 0, CRLF.length); + stream.write(ENDCHUNK, 0, ENDCHUNK.length); + } + + // ----------------------------------------------------------- Public Methods + /** + * Must be called to ensure the internal cache is flushed and the closing chunk is written. + * @throws IOException + * + * @since 3.0 + */ + public void finish() throws IOException { + if (!wroteLastChunk) { + flushCache(); + writeClosingChunk(); + wroteLastChunk = true; + } + } + + // -------------------------------------------- OutputStream Methods + /** + * Write the specified byte to our output stream. + * + * Note: Avoid this method as it will cause an inefficient single byte chunk. + * Use write (byte[], int, int) instead. + * + * @param b The byte to be written + * @throws IOException if an input/output error occurs + */ + public void write(int b) throws IOException { + cache[cachePosition] = (byte) b; + cachePosition++; + if (cachePosition == cache.length) flushCache(); + } + + /** + * Writes the array. If the array does not fit within the buffer, it is + * not split, but rather written out as one large chunk. + * @param b + * @throws IOException + * + * @since 3.0 + */ + public void write(byte b[]) throws IOException { + this.write(b, 0, b.length); + } + + public void write(byte src[], int off, int len) throws IOException { + if (len >= cache.length - cachePosition) { + flushCacheWithAppend(src, off, len); + } else { + System.arraycopy(src, off, cache, cachePosition, len); + cachePosition += len; + } + } + + /** + * Flushes the underlying stream, but leaves the internal buffer alone. + * @throws IOException + */ + public void flush() throws IOException { + stream.flush(); + } + + /** + * Finishes writing to the underlying stream, but does NOT close the underlying stream. + * @throws IOException + */ + public void close() throws IOException { + finish(); + super.close(); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/CircularRedirectException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/CircularRedirectException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/CircularRedirectException.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,67 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/CircularRedirectException.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * Signals a circular redirect + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class CircularRedirectException extends RedirectException { + + /** + * Creates a new CircularRedirectException with a null detail message. + */ + public CircularRedirectException() { + super(); + } + + /** + * Creates a new CircularRedirectException with the specified detail message. + * + * @param message The exception detail message + */ + public CircularRedirectException(String message) { + super(message); + } + + /** + * Creates a new CircularRedirectException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public CircularRedirectException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectMethod.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,217 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectMethod.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Establishes a tunneled HTTP connection via the CONNECT method. + * + * @author Ortwin Gl???ck + * @author dIon Gillard + * @author Mike Bowler + * @author Oleg Kalnichevski + * @since 2.0 + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:35 $ + */ +public class ConnectMethod extends HttpMethodBase { + + /** the name of this method */ + public static final String NAME = "CONNECT"; + + /** + * Create a connect method. + * + * @since 3.0 + */ + public ConnectMethod() { + LOG.trace("enter ConnectMethod()"); + } + + /** + * @deprecated the wrapped method is no longer used + * + * Create a connect method wrapping the existing method + * + * @param method the {@link HttpMethod method} to execute after connecting + * to the server + */ + public ConnectMethod(HttpMethod method) { + LOG.trace("enter ConnectMethod(HttpMethod)"); + } + + /** + * Provide the {@link #NAME name} of this method. + * + * @return the String "CONNECT" + */ + public String getName() { + return NAME; + } + + /** + * This method does nothing. CONNECT request is not supposed + * to contain Cookie request header. + * + * @param state current state of http requests + * @param conn the connection to use for I/O + * + * @throws IOException when errors occur reading or writing to/from the + * connection + * @throws HttpException when a recoverable error occurs + * + * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection) + */ + protected void addCookieRequestHeader(HttpState state, HttpConnection conn) + throws IOException, HttpException { + // Do nothing. Not applicable to CONNECT method + } + + + /** + * Populates the request headers map to with additional {@link Header + * headers} to be submitted to the given {@link HttpConnection}. + * + *

+ * This implementation adds User-Agent, Host, + * and Proxy-Authorization headers, when appropriate. + *

+ * + * @param state the client state + * @param conn the {@link HttpConnection} the headers will eventually be + * written to + * @throws IOException when an error occurs writing the request + * @throws HttpException when a HTTP protocol error occurs + * + * @see #writeRequestHeaders + */ + protected void addRequestHeaders(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, " + + "HttpConnection)"); + addUserAgentRequestHeader(state, conn); + addHostRequestHeader(state, conn); + addProxyConnectionHeader(state, conn); + } + + /** + * Execute this method and create a tunneled HttpConnection. If the method + * is successful (i.e. the status is a 2xx) tunnelCreated() will be called + * on the connection. + * + * @param state the current http state + * @param conn the connection to write to + * @return the http status code from execution + * @throws HttpException when an error occurs writing the headers + * @throws IOException when an error occurs writing the headers + * + * @see HttpConnection#tunnelCreated() + */ + public int execute(HttpState state, HttpConnection conn) + throws IOException, HttpException { + + LOG.trace("enter ConnectMethod.execute(HttpState, HttpConnection)"); + int code = super.execute(state, conn); + if (LOG.isDebugEnabled()) { + LOG.debug("CONNECT status code " + code); + } + return code; + } + + /** + * Special Connect request. + * + * @param state the current http state + * @param conn the connection to write to + * @throws IOException when an error occurs writing the request + * @throws HttpException when an error occurs writing the request + */ + protected void writeRequestLine(HttpState state, HttpConnection conn) + throws IOException, HttpException { + int port = conn.getPort(); + if (port == -1) { + port = conn.getProtocol().getDefaultPort(); + } + StringBuffer buffer = new StringBuffer(); + buffer.append(getName()); + buffer.append(' '); + buffer.append(conn.getHost()); + if (port > -1) { + buffer.append(':'); + buffer.append(port); + } + buffer.append(" "); + buffer.append(getEffectiveVersion()); + String line = buffer.toString(); + conn.printLine(line, getParams().getHttpElementCharset()); + if (Wire.HEADER_WIRE.enabled()) { + Wire.HEADER_WIRE.output(line); + } + } + + /** + * Returns true if the status code is anything other than + * SC_OK, false otherwise. + * + * @see HttpMethodBase#shouldCloseConnection(HttpConnection) + * @see HttpStatus#SC_OK + * + * @return true if the connection should be closed + */ + protected boolean shouldCloseConnection(HttpConnection conn) { + if (getStatusCode() == HttpStatus.SC_OK) { + Header connectionHeader = null; + if (!conn.isTransparent()) { + connectionHeader = getResponseHeader("proxy-connection"); + } + if (connectionHeader == null) { + connectionHeader = getResponseHeader("connection"); + } + if (connectionHeader != null) { + if (connectionHeader.getValue().equalsIgnoreCase("close")) { + if (LOG.isWarnEnabled()) { + LOG.warn("Invalid header encountered '" + connectionHeader.toExternalForm() + + "' in response " + getStatusLine().toString()); + } + } + } + return false; + } else { + return super.shouldCloseConnection(conn); + } + } + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(ConnectMethod.class); + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectTimeoutException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectTimeoutException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectTimeoutException.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,75 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectTimeoutException.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.InterruptedIOException; + +import org.apache.commons.httpclient.util.ExceptionUtil; + +/** + * A timeout while connecting to an HTTP server or waiting for an + * available connection from an HttpConnectionManager. + * + * @author Laura Werner + * + * @since 3.0 + */ +public class ConnectTimeoutException extends InterruptedIOException { + + /** + * Creates a ConnectTimeoutException with a null detail message. + */ + public ConnectTimeoutException() { + super(); + } + + /** + * Creates a ConnectTimeoutException with the specified detail message. + * + * @param message The exception detail message + */ + public ConnectTimeoutException(String message) { + super(message); + } + + /** + * Creates a new ConnectTimeoutException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public ConnectTimeoutException(String message, Throwable cause) { + super(message); + // If we're running on JDK 1.4 or later, tell Throwable what the cause was + ExceptionUtil.initCause(this, cause); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectionPoolTimeoutException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectionPoolTimeoutException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectionPoolTimeoutException.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,69 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ConnectionPoolTimeoutException.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * A timeout while connecting waiting for an available connection + * from an HttpConnectionManager. + * + * @author Laura Werner + * + * @since 3.0 + */ +public class ConnectionPoolTimeoutException extends ConnectTimeoutException { + + /** + * Creates a ConnectTimeoutException with a null detail message. + */ + public ConnectionPoolTimeoutException() { + super(); + } + + /** + * Creates a ConnectTimeoutException with the specified detail message. + * + * @param message The exception detail message + */ + public ConnectionPoolTimeoutException(String message) { + super(message); + } + + /** + * Creates a new ConnectTimeoutException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public ConnectionPoolTimeoutException(String message, Throwable cause) { + super(message, cause); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ContentLengthInputStream.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ContentLengthInputStream.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ContentLengthInputStream.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,207 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ContentLengthInputStream.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Cuts the wrapped InputStream off after a specified number of bytes. + * + *

Implementation note: Choices abound. One approach would pass + * through the {@link InputStream#mark} and {@link InputStream#reset} calls to + * the underlying stream. That's tricky, though, because you then have to + * start duplicating the work of keeping track of how much a reset rewinds. + * Further, you have to watch out for the "readLimit", and since the semantics + * for the readLimit leave room for differing implementations, you might get + * into a lot of trouble.

+ * + *

Alternatively, you could make this class extend {@link java.io.BufferedInputStream} + * and then use the protected members of that class to avoid duplicated effort. + * That solution has the side effect of adding yet another possible layer of + * buffering.

+ * + *

Then, there is the simple choice, which this takes - simply don't + * support {@link InputStream#mark} and {@link InputStream#reset}. That choice + * has the added benefit of keeping this class very simple.

+ * + * @author Ortwin Glueck + * @author Eric Johnson + * @author Mike Bowler + * @since 2.0 + */ +public class ContentLengthInputStream extends InputStream { + + /** + * The maximum number of bytes that can be read from the stream. Subsequent + * read operations will return -1. + */ + private long contentLength; + + /** The current position */ + private long pos = 0; + + /** True if the stream is closed. */ + private boolean closed = false; + + /** + * Wrapped input stream that all calls are delegated to. + */ + private InputStream wrappedStream = null; + + /** + * @deprecated use {@link #ContentLengthInputStream(InputStream, long)} + * + * Creates a new length limited stream + * + * @param in The stream to wrap + * @param contentLength The maximum number of bytes that can be read from + * the stream. Subsequent read operations will return -1. + */ + public ContentLengthInputStream(InputStream in, int contentLength) { + this(in, (long)contentLength); + } + + /** + * Creates a new length limited stream + * + * @param in The stream to wrap + * @param contentLength The maximum number of bytes that can be read from + * the stream. Subsequent read operations will return -1. + * + * @since 3.0 + */ + public ContentLengthInputStream(InputStream in, long contentLength) { + super(); + this.wrappedStream = in; + this.contentLength = contentLength; + } + + /** + *

Reads until the end of the known length of content.

+ * + *

Does not close the underlying socket input, but instead leaves it + * primed to parse the next response.

+ * @throws IOException If an IO problem occurs. + */ + public void close() throws IOException { + if (!closed) { + try { + ChunkedInputStream.exhaustInputStream(this); + } finally { + // close after above so that we don't throw an exception trying + // to read after closed! + closed = true; + } + } + } + + + /** + * Read the next byte from the stream + * @return The next byte or -1 if the end of stream has been reached. + * @throws IOException If an IO problem occurs + * @see java.io.InputStream#read() + */ + public int read() throws IOException { + if (closed) { + throw new IOException("Attempted read from closed stream."); + } + + if (pos >= contentLength) { + return -1; + } + pos++; + return this.wrappedStream.read(); + } + + /** + * Does standard {@link InputStream#read(byte[], int, int)} behavior, but + * also notifies the watcher when the contents have been consumed. + * + * @param b The byte array to fill. + * @param off Start filling at this position. + * @param len The number of bytes to attempt to read. + * @return The number of bytes read, or -1 if the end of content has been + * reached. + * + * @throws java.io.IOException Should an error occur on the wrapped stream. + */ + public int read (byte[] b, int off, int len) throws java.io.IOException { + if (closed) { + throw new IOException("Attempted read from closed stream."); + } + + if (pos >= contentLength) { + return -1; + } + + if (pos + len > contentLength) { + len = (int) (contentLength - pos); + } + int count = this.wrappedStream.read(b, off, len); + pos += count; + return count; + } + + + /** + * Read more bytes from the stream. + * @param b The byte array to put the new data in. + * @return The number of bytes read into the buffer. + * @throws IOException If an IO problem occurs + * @see java.io.InputStream#read(byte[]) + */ + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + /** + * Skips and discards a number of bytes from the input stream. + * @param n The number of bytes to skip. + * @return The actual number of bytes skipped. <= 0 if no bytes + * are skipped. + * @throws IOException If an error occurs while skipping bytes. + * @see InputStream#skip(long) + */ + public long skip(long n) throws IOException { + // make sure we don't skip more bytes than are + // still available + long length = Math.min(n, contentLength - pos); + // skip and keep track of the bytes actually skipped + length = this.wrappedStream.skip(length); + // only add the skipped bytes to the current position + // if bytes were actually skipped + if (length > 0) { + pos += length; + } + return length; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Cookie.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Cookie.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Cookie.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,545 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Cookie.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.Serializable; +import java.text.RuleBasedCollator; +import java.util.Comparator; +import java.util.Date; +import java.util.Locale; + +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.httpclient.cookie.CookieSpec; +import org.apache.commons.httpclient.util.LangUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * HTTP "magic-cookie" represents a piece of state information + * that the HTTP agent and the target server can exchange to maintain + * a session. + *

+ * + * @author B.C. Holmes + * @author Park, Sung-Gu + * @author Doug Sale + * @author Rod Waldhoff + * @author dIon Gillard + * @author Sean C. Sullivan + * @author John Evans + * @author Marc A. Saegesser + * @author Oleg Kalnichevski + * @author Mike Bowler + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:33 $ + */ +public class Cookie extends NameValuePair implements Serializable, Comparator { + + // ----------------------------------------------------------- Constructors + + /** + * Default constructor. Creates a blank cookie + */ + + public Cookie() { + this(null, "noname", null, null, null, false); + } + + /** + * Creates a cookie with the given name, value and domain attribute. + * + * @param name the cookie name + * @param value the cookie value + * @param domain the domain this cookie can be sent to + */ + public Cookie(String domain, String name, String value) { + this(domain, name, value, null, null, false); + } + + /** + * Creates a cookie with the given name, value, domain attribute, + * path attribute, expiration attribute, and secure attribute + * + * @param name the cookie name + * @param value the cookie value + * @param domain the domain this cookie can be sent to + * @param path the path prefix for which this cookie can be sent + * @param expires the {@link Date} at which this cookie expires, + * or null if the cookie expires at the end + * of the session + * @param secure if true this cookie can only be sent over secure + * connections + * @throws IllegalArgumentException If cookie name is null or blank, + * cookie name contains a blank, or cookie name starts with character $ + * + */ + public Cookie(String domain, String name, String value, + String path, Date expires, boolean secure) { + + super(name, value); + LOG.trace("enter Cookie(String, String, String, String, Date, boolean)"); + if (name == null) { + throw new IllegalArgumentException("Cookie name may not be null"); + } + if (name.trim().equals("")) { + throw new IllegalArgumentException("Cookie name may not be blank"); + } + this.setPath(path); + this.setDomain(domain); + this.setExpiryDate(expires); + this.setSecure(secure); + } + + /** + * Creates a cookie with the given name, value, domain attribute, + * path attribute, maximum age attribute, and secure attribute + * + * @param name the cookie name + * @param value the cookie value + * @param domain the domain this cookie can be sent to + * @param path the path prefix for which this cookie can be sent + * @param maxAge the number of seconds for which this cookie is valid. + * maxAge is expected to be a non-negative number. + * -1 signifies that the cookie should never expire. + * @param secure if true this cookie can only be sent over secure + * connections + */ + public Cookie(String domain, String name, String value, String path, + int maxAge, boolean secure) { + + this(domain, name, value, path, null, secure); + if (maxAge < -1) { + throw new IllegalArgumentException("Invalid max age: " + Integer.toString(maxAge)); + } + if (maxAge >= 0) { + setExpiryDate(new Date(System.currentTimeMillis() + maxAge * 1000L)); + } + } + + /** + * Returns the comment describing the purpose of this cookie, or + * null if no such comment has been defined. + * + * @return comment + * + * @see #setComment(String) + */ + public String getComment() { + return cookieComment; + } + + /** + * If a user agent (web browser) presents this cookie to a user, the + * cookie's purpose will be described using this comment. + * + * @param comment + * + * @see #getComment() + */ + public void setComment(String comment) { + cookieComment = comment; + } + + /** + * Returns the expiration {@link Date} of the cookie, or null + * if none exists. + *

Note: the object returned by this method is + * considered immutable. Changing it (e.g. using setTime()) could result + * in undefined behaviour. Do so at your peril.

+ * @return Expiration {@link Date}, or null. + * + * @see #setExpiryDate(java.util.Date) + * + */ + public Date getExpiryDate() { + return cookieExpiryDate; + } + + /** + * Sets expiration date. + *

Note: the object returned by this method is considered + * immutable. Changing it (e.g. using setTime()) could result in undefined + * behaviour. Do so at your peril.

+ * + * @param expiryDate the {@link Date} after which this cookie is no longer valid. + * + * @see #getExpiryDate + * + */ + public void setExpiryDate (Date expiryDate) { + cookieExpiryDate = expiryDate; + } + + + /** + * Returns false if the cookie should be discarded at the end + * of the "session"; true otherwise. + * + * @return false if the cookie should be discarded at the end + * of the "session"; true otherwise + */ + public boolean isPersistent() { + return (null != cookieExpiryDate); + } + + + /** + * Returns domain attribute of the cookie. + * + * @return the value of the domain attribute + * + * @see #setDomain(java.lang.String) + */ + public String getDomain() { + return cookieDomain; + } + + /** + * Sets the domain attribute. + * + * @param domain The value of the domain attribute + * + * @see #getDomain + */ + public void setDomain(String domain) { + if (domain != null) { + int ndx = domain.indexOf(":"); + if (ndx != -1) { + domain = domain.substring(0, ndx); + } + cookieDomain = domain.toLowerCase(); + } + } + + + /** + * Returns the path attribute of the cookie + * + * @return The value of the path attribute. + * + * @see #setPath(java.lang.String) + */ + public String getPath() { + return cookiePath; + } + + /** + * Sets the path attribute. + * + * @param path The value of the path attribute + * + * @see #getPath + * + */ + public void setPath(String path) { + cookiePath = path; + } + + /** + * @return true if this cookie should only be sent over secure connections. + * @see #setSecure(boolean) + */ + public boolean getSecure() { + return isSecure; + } + + /** + * Sets the secure attribute of the cookie. + *

+ * When true the cookie should only be sent + * using a secure protocol (https). This should only be set when + * the cookie's originating server used a secure protocol to set the + * cookie's value. + * + * @param secure The value of the secure attribute + * + * @see #getSecure() + */ + public void setSecure (boolean secure) { + isSecure = secure; + } + + /** + * Returns the version of the cookie specification to which this + * cookie conforms. + * + * @return the version of the cookie. + * + * @see #setVersion(int) + * + */ + public int getVersion() { + return cookieVersion; + } + + /** + * Sets the version of the cookie specification to which this + * cookie conforms. + * + * @param version the version of the cookie. + * + * @see #getVersion + */ + public void setVersion(int version) { + cookieVersion = version; + } + + /** + * Returns true if this cookie has expired. + * + * @return true if the cookie has expired. + */ + public boolean isExpired() { + return (cookieExpiryDate != null + && cookieExpiryDate.getTime() <= System.currentTimeMillis()); + } + + /** + * Returns true if this cookie has expired according to the time passed in. + * + * @param now The current time. + * + * @return true if the cookie expired. + */ + public boolean isExpired(Date now) { + return (cookieExpiryDate != null + && cookieExpiryDate.getTime() <= now.getTime()); + } + + + /** + * Indicates whether the cookie had a path specified in a + * path attribute of the Set-Cookie header. This value + * is important for generating the Cookie header because + * some cookie specifications require that the Cookie header + * should only include a path attribute if the cookie's path + * was specified in the Set-Cookie header. + * + * @param value true if the cookie's path was explicitly + * set, false otherwise. + * + * @see #isPathAttributeSpecified + */ + public void setPathAttributeSpecified(boolean value) { + hasPathAttribute = value; + } + + /** + * Returns true if cookie's path was set via a path attribute + * in the Set-Cookie header. + * + * @return value true if the cookie's path was explicitly + * set, false otherwise. + * + * @see #setPathAttributeSpecified + */ + public boolean isPathAttributeSpecified() { + return hasPathAttribute; + } + + /** + * Indicates whether the cookie had a domain specified in a + * domain attribute of the Set-Cookie header. This value + * is important for generating the Cookie header because + * some cookie specifications require that the Cookie header + * should only include a domain attribute if the cookie's domain + * was specified in the Set-Cookie header. + * + * @param value true if the cookie's domain was explicitly + * set, false otherwise. + * + * @see #isDomainAttributeSpecified + */ + public void setDomainAttributeSpecified(boolean value) { + hasDomainAttribute = value; + } + + /** + * Returns true if cookie's domain was set via a domain + * attribute in the Set-Cookie header. + * + * @return value true if the cookie's domain was explicitly + * set, false otherwise. + * + * @see #setDomainAttributeSpecified + */ + public boolean isDomainAttributeSpecified() { + return hasDomainAttribute; + } + + /** + * Returns a hash code in keeping with the + * {@link Object#hashCode} general hashCode contract. + * @return A hash code + */ + public int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.getName()); + hash = LangUtils.hashCode(hash, this.cookieDomain); + hash = LangUtils.hashCode(hash, this.cookiePath); + return hash; + } + + + /** + * Two cookies are equal if the name, path and domain match. + * @param obj The object to compare against. + * @return true if the two objects are equal. + */ + public boolean equals(Object obj) { + if (obj == null) return false; + if (this == obj) return true; + if (obj instanceof Cookie) { + Cookie that = (Cookie) obj; + return LangUtils.equals(this.getName(), that.getName()) + && LangUtils.equals(this.cookieDomain, that.cookieDomain) + && LangUtils.equals(this.cookiePath, that.cookiePath); + } else { + return false; + } + } + + + /** + * Return a textual representation of the cookie. + * + * @return string. + */ + public String toExternalForm() { + CookieSpec spec = null; + if (getVersion() > 0) { + spec = CookiePolicy.getDefaultSpec(); + } else { + spec = CookiePolicy.getCookieSpec(CookiePolicy.NETSCAPE); + } + return spec.formatCookie(this); + } + + /** + *

Compares two cookies to determine order for cookie header.

+ *

Most specific should be first.

+ *

This method is implemented so a cookie can be used as a comparator for + * a SortedSet of cookies. Specifically it's used above in the + * createCookieHeader method.

+ * @param o1 The first object to be compared + * @param o2 The second object to be compared + * @return See {@link java.util.Comparator#compare(Object,Object)} + */ + public int compare(Object o1, Object o2) { + LOG.trace("enter Cookie.compare(Object, Object)"); + + if (!(o1 instanceof Cookie)) { + throw new ClassCastException(o1.getClass().getName()); + } + if (!(o2 instanceof Cookie)) { + throw new ClassCastException(o2.getClass().getName()); + } + Cookie c1 = (Cookie) o1; + Cookie c2 = (Cookie) o2; + if (c1.getPath() == null && c2.getPath() == null) { + return 0; + } else if (c1.getPath() == null) { + // null is assumed to be "/" + if (c2.getPath().equals(CookieSpec.PATH_DELIM)) { + return 0; + } else { + return -1; + } + } else if (c2.getPath() == null) { + // null is assumed to be "/" + if (c1.getPath().equals(CookieSpec.PATH_DELIM)) { + return 0; + } else { + return 1; + } + } else { + return STRING_COLLATOR.compare(c1.getPath(), c2.getPath()); + } + } + + /** + * Return a textual representation of the cookie. + * + * @return string. + * + * @see #toExternalForm + */ + public String toString() { + return toExternalForm(); + } + + // ----------------------------------------------------- Instance Variables + + /** Comment attribute. */ + private String cookieComment; + + /** Domain attribute. */ + private String cookieDomain; + + /** Expiration {@link Date}. */ + private Date cookieExpiryDate; + + /** Path attribute. */ + private String cookiePath; + + /** My secure flag. */ + private boolean isSecure; + + /** + * Specifies if the set-cookie header included a Path attribute for this + * cookie + */ + private boolean hasPathAttribute = false; + + /** + * Specifies if the set-cookie header included a Domain attribute for this + * cookie + */ + private boolean hasDomainAttribute = false; + + /** The version of the cookie specification I was created from. */ + private int cookieVersion = 0; + + // -------------------------------------------------------------- Constants + + /** + * Collator for Cookie comparisons. Could be replaced with references to + * specific Locales. + */ + private static final RuleBasedCollator STRING_COLLATOR = + (RuleBasedCollator) RuleBasedCollator.getInstance( + new Locale("en", "US", "")); + + /** Log object for this class */ + private static final Log LOG = LogFactory.getLog(Cookie.class); + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Credentials.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Credentials.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Credentials.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,43 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Credentials.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + *

Authentication credentials.

+ *

+ * This is just a marker interface, the current implementation has no methods. + *

+ * @author Unascribed + * @author Mike Bowler + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:34 $ + */ +public interface Credentials { +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultHttpMethodRetryHandler.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultHttpMethodRetryHandler.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultHttpMethodRetryHandler.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,147 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultHttpMethodRetryHandler.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.NoRouteToHostException; +import java.net.UnknownHostException; + +/** + * The default {@link HttpMethodRetryHandler} used by {@link HttpMethod}s. + * + * @author Michael Becke + * @author Oleg Kalnichevski + */ +public class DefaultHttpMethodRetryHandler implements HttpMethodRetryHandler { + + + private static Class SSL_HANDSHAKE_EXCEPTION = null; + + static { + try { + SSL_HANDSHAKE_EXCEPTION = Class.forName("javax.net.ssl.SSLHandshakeException"); + } catch (ClassNotFoundException ignore) { + } + } + /** the number of times a method will be retried */ + private int retryCount; + + /** Whether or not methods that have successfully sent their request will be retried */ + private boolean requestSentRetryEnabled; + + /** + * Creates a new DefaultHttpMethodRetryHandler. + * @param retryCount the number of times a method will be retried + * @param requestSentRetryEnabled if true, methods that have successfully sent their request will be retried + */ + public DefaultHttpMethodRetryHandler(int retryCount, boolean requestSentRetryEnabled) { + super(); + this.retryCount = retryCount; + this.requestSentRetryEnabled = requestSentRetryEnabled; + } + + /** + * Creates a new DefaultHttpMethodRetryHandler that retries up to 3 times + * but does not retry methods that have successfully sent their requests. + */ + public DefaultHttpMethodRetryHandler() { + this(3, false); + } + /** + * Used retryCount and requestSentRetryEnabled to determine + * if the given method should be retried. + * + * @see HttpMethodRetryHandler#retryMethod(HttpMethod, IOException, int) + */ + public boolean retryMethod( + final HttpMethod method, + final IOException exception, + int executionCount) { + if (method == null) { + throw new IllegalArgumentException("HTTP method may not be null"); + } + if (exception == null) { + throw new IllegalArgumentException("Exception parameter may not be null"); + } + // HttpMethod interface is the WORST thing ever done to HttpClient + if (method instanceof HttpMethodBase) { + if (((HttpMethodBase)method).isAborted()) { + return false; + } + } + if (executionCount > this.retryCount) { + // Do not retry if over max retry count + return false; + } + if (exception instanceof NoHttpResponseException) { + // Retry if the server dropped connection on us + return true; + } + if (exception instanceof InterruptedIOException) { + // Timeout + return false; + } + if (exception instanceof UnknownHostException) { + // Unknown host + return false; + } + if (exception instanceof NoRouteToHostException) { + // Host unreachable + return false; + } + if (SSL_HANDSHAKE_EXCEPTION != null && SSL_HANDSHAKE_EXCEPTION.isInstance(exception)) { + // SSL handshake exception + return false; + } + if (!method.isRequestSent() || this.requestSentRetryEnabled) { + // Retry if the request has not been sent fully or + // if it's OK to retry methods that have been sent + return true; + } + // otherwise do not retry + return false; + } + + /** + * @return true if this handler will retry methods that have + * successfully sent their request, false otherwise + */ + public boolean isRequestSentRetryEnabled() { + return requestSentRetryEnabled; + } + + /** + * @return the maximum number of times a method will be retried + */ + public int getRetryCount() { + return retryCount; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultMethodRetryHandler.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultMethodRetryHandler.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultMethodRetryHandler.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,101 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/DefaultMethodRetryHandler.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * The default MethodRetryHandler used by HttpMethodBase. + * + * @author Michael Becke + * + * @see HttpMethodBase#setMethodRetryHandler(MethodRetryHandler) + * + * @deprecated use {@link org.apache.commons.httpclient.DefaultHttpMethodRetryHandler} + */ +public class DefaultMethodRetryHandler implements MethodRetryHandler { + + /** the number of times a method will be retried */ + private int retryCount; + + /** Whether or not methods that have successfully sent their request will be retried */ + private boolean requestSentRetryEnabled; + + /** + */ + public DefaultMethodRetryHandler() { + this.retryCount = 3; + this.requestSentRetryEnabled = false; + } + + /** + * Used retryCount and requestSentRetryEnabled to determine + * if the given method should be retried. + * + * @see MethodRetryHandler#retryMethod(HttpMethod, HttpConnection, HttpRecoverableException, int, boolean) + */ + public boolean retryMethod( + HttpMethod method, + HttpConnection connection, + HttpRecoverableException recoverableException, + int executionCount, + boolean requestSent + ) { + return ((!requestSent || requestSentRetryEnabled) && (executionCount <= retryCount)); + } + /** + * @return true if this handler will retry methods that have + * successfully sent their request, false otherwise + */ + public boolean isRequestSentRetryEnabled() { + return requestSentRetryEnabled; + } + + /** + * @return the maximum number of times a method will be retried + */ + public int getRetryCount() { + return retryCount; + } + + /** + * @param requestSentRetryEnabled a flag indicating if methods that have + * successfully sent their request should be retried + */ + public void setRequestSentRetryEnabled(boolean requestSentRetryEnabled) { + this.requestSentRetryEnabled = requestSentRetryEnabled; + } + + /** + * @param retryCount the maximum number of times a method can be retried + */ + public void setRetryCount(int retryCount) { + this.retryCount = retryCount; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Header.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Header.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Header.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,144 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Header.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + *

An HTTP header.

+ * + * @author Remy Maucherat + * @author Mike Bowler + * @author Oleg Kalnichevski + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:35 $ + */ +public class Header extends NameValuePair { + + // ----------------------------------------------------------- Constructors + + /** + * Autogenerated header flag. + */ + private boolean isAutogenerated = false; + + /** + * Default constructor. + */ + public Header() { + this(null, null); + } + + /** + * Constructor with name and value + * + * @param name the header name + * @param value the header value + */ + public Header(String name, String value) { + super(name, value); + } + + /** + * Constructor with name and value + * + * @param name the header name + * @param value the header value + * @param isAutogenerated true if the header is autogenerated, + * false otherwise. + * + * @since 3.0 + */ + public Header(String name, String value, boolean isAutogenerated) { + super(name, value); + this.isAutogenerated = isAutogenerated; + } + + // --------------------------------------------------------- Public Methods + + /** + * Returns a {@link String} representation of the header. + * + * @return stringHEAD + */ + public String toExternalForm() { + return ((null == getName() ? "" : getName()) + + ": " + + (null == getValue() ? "" : getValue()) + + "\r\n"); + } + + /** + * Returns a {@link String} representation of the header. + * + * @return stringHEAD + */ + public String toString() { + return toExternalForm(); + } + + /** + * Returns an array of {@link HeaderElement}s + * constructed from my value. + * + * @see HeaderElement#parse + * @throws HttpException if the header cannot be parsed + * @return an array of header elements + * + * @deprecated Use #getElements + */ + public HeaderElement[] getValues() throws HttpException { + return HeaderElement.parse(getValue()); + } + + /** + * Returns an array of {@link HeaderElement}s + * constructed from my value. + * + * @see HeaderElement#parseElements(String) + * + * @return an array of header elements + * + * @since 3.0 + */ + public HeaderElement[] getElements() { + return HeaderElement.parseElements(getValue()); + } + + /** + * Returns the value of the auto-generated header flag. + * + * @return true if the header is autogenerated, + * false otherwise. + * + * @since 3.0 + */ + public boolean isAutogenerated() { + return isAutogenerated; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderElement.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderElement.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderElement.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,298 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderElement.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.httpclient.util.ParameterParser; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

One element of an HTTP header's value.

+ *

+ * Some HTTP headers (such as the set-cookie header) have values that + * can be decomposed into multiple elements. Such headers must be in the + * following form: + *

+ *
+ * header  = [ element ] *( "," [ element ] )
+ * element = name [ "=" [ value ] ] *( ";" [ param ] )
+ * param   = name [ "=" [ value ] ]
+ *
+ * name    = token
+ * value   = ( token | quoted-string )
+ *
+ * token         = 1*<any char except "=", ",", ";", <"> and
+ *                       white space>
+ * quoted-string = <"> *( text | quoted-char ) <">
+ * text          = any char except <">
+ * quoted-char   = "\" char
+ * 
+ *

+ * Any amount of white space is allowed between any part of the + * header, element or param and is ignored. A missing value in any + * element or param will be stored as the empty {@link String}; + * if the "=" is also missing null will be stored instead. + *

+ *

+ * This class represents an individual header element, containing + * both a name/value pair (value may be null) and optionally + * a set of additional parameters. + *

+ *

+ * This class also exposes a {@link #parse} method for parsing a + * {@link Header} value into an array of elements. + *

+ * + * @see Header + * + * @author B.C. Holmes + * @author Park, Sung-Gu + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @since 1.0 + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:34 $ + */ +public class HeaderElement extends NameValuePair { + + // ----------------------------------------------------------- Constructors + + /** + * Default constructor. + */ + public HeaderElement() { + this(null, null, null); + } + + /** + * Constructor. + * @param name my name + * @param value my (possibly null) value + */ + public HeaderElement(String name, String value) { + this(name, value, null); + } + + /** + * Constructor with name, value and parameters. + * + * @param name my name + * @param value my (possibly null) value + * @param parameters my (possibly null) parameters + */ + public HeaderElement(String name, String value, + NameValuePair[] parameters) { + super(name, value); + this.parameters = parameters; + } + + /** + * Constructor with array of characters. + * + * @param chars the array of characters + * @param offset - the initial offset. + * @param length - the length. + * + * @since 3.0 + */ + public HeaderElement(char[] chars, int offset, int length) { + this(); + if (chars == null) { + return; + } + ParameterParser parser = new ParameterParser(); + List params = parser.parse(chars, offset, length, ';'); + if (params.size() > 0) { + NameValuePair element = (NameValuePair) params.remove(0); + setName(element.getName()); + setValue(element.getValue()); + if (params.size() > 0) { + this.parameters = (NameValuePair[]) + params.toArray(new NameValuePair[params.size()]); + } + } + } + + /** + * Constructor with array of characters. + * + * @param chars the array of characters + * + * @since 3.0 + */ + public HeaderElement(char[] chars) { + this(chars, 0, chars.length); + } + + // -------------------------------------------------------- Constants + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HeaderElement.class); + + // ----------------------------------------------------- Instance Variables + + /** My parameters, if any. */ + private NameValuePair[] parameters = null; + + // ------------------------------------------------------------- Properties + + /** + * Get parameters, if any. + * + * @since 2.0 + * @return parameters as an array of {@link NameValuePair}s + */ + public NameValuePair[] getParameters() { + return this.parameters; + } + + // --------------------------------------------------------- Public Methods + + /** + * This parses the value part of a header. The result is an array of + * HeaderElement objects. + * + * @param headerValue the array of char representation of the header value + * (as received from the web server). + * @return array of {@link HeaderElement}s. + * + * @since 3.0 + */ + public static final HeaderElement[] parseElements(char[] headerValue) { + + LOG.trace("enter HeaderElement.parseElements(char[])"); + + if (headerValue == null) { + return new HeaderElement[] {}; + } + List elements = new ArrayList(); + + int i = 0; + int from = 0; + int len = headerValue.length; + boolean qouted = false; + while (i < len) { + char ch = headerValue[i]; + if (ch == '"') { + qouted = !qouted; + } + HeaderElement element = null; + if ((!qouted) && (ch == ',')) { + element = new HeaderElement(headerValue, from, i); + from = i + 1; + } else if (i == len - 1) { + element = new HeaderElement(headerValue, from, len); + } + if ((element != null) && (element.getName() != null)) { + elements.add(element); + } + i++; + } + return (HeaderElement[]) + elements.toArray(new HeaderElement[elements.size()]); + } + + /** + * This parses the value part of a header. The result is an array of + * HeaderElement objects. + * + * @param headerValue the string representation of the header value + * (as received from the web server). + * @return array of {@link HeaderElement}s. + * + * @since 3.0 + */ + public static final HeaderElement[] parseElements(String headerValue) { + + LOG.trace("enter HeaderElement.parseElements(String)"); + + if (headerValue == null) { + return new HeaderElement[] {}; + } + return parseElements(headerValue.toCharArray()); + } + + /** + * This parses the value part of a header. The result is an array of + * HeaderElement objects. + * + * @param headerValue the string representation of the header value + * (as received from the web server). + * @return array of {@link HeaderElement}s. + * @throws HttpException if the above syntax rules are violated. + * + * @deprecated Use #parseElements(String). + */ + public static final HeaderElement[] parse(String headerValue) + throws HttpException { + + LOG.trace("enter HeaderElement.parse(String)"); + + if (headerValue == null) { + return new HeaderElement[] {}; + } + return parseElements(headerValue.toCharArray()); + } + + + /** + * Returns parameter with the given name, if found. Otherwise null + * is returned + * + * @param name The name to search by. + * @return NameValuePair parameter with the given name + */ + + public NameValuePair getParameterByName(String name) { + + LOG.trace("enter HeaderElement.getParameterByName(String)"); + + if (name == null) { + throw new IllegalArgumentException("Name may not be null"); + } + NameValuePair found = null; + NameValuePair parameters[] = getParameters(); + if (parameters != null) { + for (int i = 0; i < parameters.length; i++) { + NameValuePair current = parameters[ i ]; + if (current.getName().equalsIgnoreCase(name)) { + found = current; + break; + } + } + } + return found; + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderGroup.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderGroup.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderGroup.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,229 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HeaderGroup.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * A class for combining a set of headers. This class allows for multiple + * headers with the same name and keeps track of the order in which headers were + * added. + * + * @author Michael Becke + * + * @since 2.0beta1 + */ +public class HeaderGroup { + + /** The list of headers for this group, in the order in which they were added */ + private List headers; + + /** + * Constructor for HeaderGroup. + */ + public HeaderGroup() { + this.headers = new ArrayList(); + } + + /** + * Removes any contained headers. + */ + public void clear() { + headers.clear(); + } + + /** + * Adds the given header to the group. The order in which this header was + * added is preserved. + * + * @param header the header to add + */ + public void addHeader(Header header) { + headers.add(header); + } + + /** + * Removes the given header. + * + * @param header the header to remove + */ + public void removeHeader(Header header) { + headers.remove(header); + } + + /** + * Sets all of the headers contained within this group overriding any + * existing headers. The headers are added in the order in which they appear + * in the array. + * + * @param headers the headers to set + */ + public void setHeaders(Header[] headers) { + clear(); + + for (int i = 0; i < headers.length; i++) { + addHeader(headers[i]); + } + } + + /** + * Gets a header representing all of the header values with the given name. + * If more that one header with the given name exists the values will be + * combined with a "," as per RFC 2616. + * + *

Header name comparison is case insensitive. + * + * @param name the name of the header(s) to get + * @return a header with a condensed value or null if no + * headers by the given name are present + */ + public Header getCondensedHeader(String name) { + Header[] headers = getHeaders(name); + + if (headers.length == 0) { + return null; + } else if (headers.length == 1) { + return new Header(headers[0].getName(), headers[0].getValue()); + } else { + StringBuffer valueBuffer = new StringBuffer(headers[0].getValue()); + + for (int i = 1; i < headers.length; i++) { + valueBuffer.append(", "); + valueBuffer.append(headers[i].getValue()); + } + + return new Header(name.toLowerCase(), valueBuffer.toString()); + } + } + + /** + * Gets all of the headers with the given name. The returned array + * maintains the relative order in which the headers were added. + * + *

Header name comparison is case insensitive. + * + * @param name the name of the header(s) to get + * + * @return an array of length >= 0 + */ + public Header[] getHeaders(String name) { + ArrayList headersFound = new ArrayList(); + + for (Iterator headerIter = headers.iterator(); headerIter.hasNext();) { + Header header = (Header) headerIter.next(); + if (header.getName().equalsIgnoreCase(name)) { + headersFound.add(header); + } + } + + return (Header[]) headersFound.toArray(new Header[headersFound.size()]); + } + + /** + * Gets the first header with the given name. + * + *

Header name comparison is case insensitive. + * + * @param name the name of the header to get + * @return the first header or null + */ + public Header getFirstHeader(String name) { + for (Iterator headerIter = headers.iterator(); headerIter.hasNext();) { + Header header = (Header) headerIter.next(); + if (header.getName().equalsIgnoreCase(name)) { + return header; + } + } + + return null; + } + + /** + * Gets the last header with the given name. + * + *

Header name comparison is case insensitive. + * + * @param name the name of the header to get + * @return the last header or null + */ + public Header getLastHeader(String name) { + // start at the end of the list and work backwards + for (int i = headers.size() - 1; i >= 0; i--) { + Header header = (Header) headers.get(i); + if (header.getName().equalsIgnoreCase(name)) { + return header; + } + } + + return null; + } + + /** + * Gets all of the headers contained within this group. + * + * @return an array of length >= 0 + */ + public Header[] getAllHeaders() { + return (Header[]) headers.toArray(new Header[headers.size()]); + } + + /** + * Tests if headers with the given name are contained within this group. + * + *

Header name comparison is case insensitive. + * + * @param name the header name to test for + * @return true if at least one header with the name is + * contained, false otherwise + */ + public boolean containsHeader(String name) { + for (Iterator headerIter = headers.iterator(); headerIter.hasNext();) { + Header header = (Header) headerIter.next(); + if (header.getName().equalsIgnoreCase(name)) { + return true; + } + } + + return false; + } + + /** + * Returns an iterator over this group of headers. + * + * @return iterator over this group of headers. + * + * @since 3.0 + */ + public Iterator getIterator() { + return this.headers.iterator(); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HostConfiguration.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HostConfiguration.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HostConfiguration.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,514 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HostConfiguration.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.params.HostParams; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.util.LangUtils; + +import java.net.InetAddress; + +/** + * Holds all of the variables needed to describe an HTTP connection to a host. This includes + * remote host, port and protocol, proxy host and port, local address, and virtual host. + * + * @author Michael Becke + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author Laura Werner + * + * @since 2.0 + */ +public class HostConfiguration implements Cloneable { + + /** + * A value to represent any host configuration, instead of using something like + * null. This value should be treated as immutable and only used in + * lookups and other such places to represent "any" host config. + */ + public static final HostConfiguration ANY_HOST_CONFIGURATION = new HostConfiguration(); + + /** The host to use. */ + private HttpHost host = null; + + /** The host name of the proxy server */ + private ProxyHost proxyHost = null; + + /** The local address to use when creating the socket, or null to use the default */ + private InetAddress localAddress = null; + + /** Parameters specific to this host */ + private HostParams params = new HostParams(); + + /** + * Constructor for HostConfiguration. + */ + public HostConfiguration() { + super(); + } + + /** + * Copy constructor for HostConfiguration + * + * @param hostConfiguration the hostConfiguration to copy + */ + public HostConfiguration (final HostConfiguration hostConfiguration) { + // wrap all of the assignments in a synchronized block to avoid + // having to negotiate the monitor for each method call + synchronized (hostConfiguration) { + try { + if (hostConfiguration.host != null) { + this.host = (HttpHost) hostConfiguration.host.clone(); + } else { + this.host = null; + } + if (hostConfiguration.proxyHost != null) { + this.proxyHost = (ProxyHost) hostConfiguration.proxyHost.clone(); + } else { + this.proxyHost = null; + } + this.localAddress = hostConfiguration.getLocalAddress(); + this.params = (HostParams)hostConfiguration.getParams().clone(); + } catch (CloneNotSupportedException e) { + throw new IllegalArgumentException("Host configuration could not be cloned"); + } + } + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() { + return new HostConfiguration(this); + } + + /** + * @see java.lang.Object#toString() + */ + public synchronized String toString() { + + boolean appendComma = false; + StringBuffer b = new StringBuffer(50); + b.append("HostConfiguration["); + + if (this.host != null) { + appendComma = true; + b.append("host=").append(this.host); + } + if (this.proxyHost != null) { + if (appendComma) { + b.append(", "); + } else { + appendComma = true; + } + b.append("proxyHost=").append(this.proxyHost); + } + if (this.localAddress != null) { + if (appendComma) { + b.append(", "); + } else { + appendComma = true; + } + b.append("localAddress=").append(this.localAddress); + if (appendComma) { + b.append(", "); + } else { + appendComma = true; + } + b.append("params=").append(this.params); + } + b.append("]"); + return b.toString(); + } + + /** + * Tests if the host configuration equals the configuration set on the + * connection. True only if the host, port, protocol, local address and virtual address + * are equal. If no host configuration has been set false will be returned. + * + * @param connection the connection to test against + * @return true if the connection's host information equals that of this + * configuration + * + * @see #proxyEquals(HttpConnection) + */ + public synchronized boolean hostEquals(final HttpConnection connection) { + if (connection == null) { + throw new IllegalArgumentException("Connection may not be null"); + } + if (this.host != null) { + if (!this.host.getHostName().equalsIgnoreCase(connection.getHost())) { + return false; + } + if (this.host.getPort() != connection.getPort()) { + return false; + } + if (!this.host.getProtocol().equals(connection.getProtocol())) { + return false; + } + if (this.localAddress != null) { + if (!this.localAddress.equals(connection.getLocalAddress())) { + return false; + } + } else { + if (connection.getLocalAddress() != null) { + return false; + } + } + return true; + } else { + return false; + } + } + + /** + * Tests if the proxy configuration equals the configuration set on the + * connection. True only if the proxyHost and proxyPort are equal. + * + * @param connection the connection to test against + * @return true if the connection's proxy information equals that of this + * configuration + * + * @see #hostEquals(HttpConnection) + */ + public synchronized boolean proxyEquals(final HttpConnection connection) { + if (connection == null) { + throw new IllegalArgumentException("Connection may not be null"); + } + if (this.proxyHost != null) { + return + this.proxyHost.getHostName().equalsIgnoreCase(connection.getProxyHost()) + && this.proxyHost.getPort() == connection.getProxyPort(); + } else { + return connection.getProxyHost() == null; + } + } + + /** + * Returns true if the host is set. + * @return true if the host is set. + * + * @deprecated no longer used + */ + public synchronized boolean isHostSet() { + return this.host != null; + } + + /** + * Sets the given host + * + * @param host the host + */ + public synchronized void setHost(final HttpHost host) { + this.host = host; + } + + /** + * Sets the given host, port and protocol + * + * @param host the host(IP or DNS name) + * @param port The port + * @param protocol The protocol. + */ + public synchronized void setHost(final String host, int port, final String protocol) { + this.host = new HttpHost(host, port, Protocol.getProtocol(protocol)); + } + + /** + * Sets the given host, virtual host, port and protocol. + * + * @param host the host(IP or DNS name) + * @param virtualHost the virtual host name or null + * @param port the host port or -1 to use protocol default + * @param protocol the protocol + * + * @deprecated #setHost(String, int, Protocol) + */ + public synchronized void setHost(final String host, final String virtualHost, int port, + final Protocol protocol) { + setHost(host, port, protocol); + this.params.setVirtualHost(virtualHost); + } + + /** + * Sets the given host, port and protocol. + * + * @param host the host(IP or DNS name) + * @param port The port + * @param protocol the protocol + */ + public synchronized void setHost(final String host, int port, final Protocol protocol) { + if (host == null) { + throw new IllegalArgumentException("host must not be null"); + } + if (protocol == null) { + throw new IllegalArgumentException("protocol must not be null"); + } + this.host = new HttpHost(host, port, protocol); + } + + /** + * Sets the given host and port. Uses the default protocol "http". + * + * @param host the host(IP or DNS name) + * @param port The port + */ + public synchronized void setHost(final String host, int port) { + setHost(host, port, Protocol.getProtocol("http")); + } + + /** + * Set the given host. Uses the default protocol("http") and its port. + * + * @param host The host(IP or DNS name). + */ + public synchronized void setHost(final String host) { + Protocol defaultProtocol = Protocol.getProtocol("http"); + setHost(host, defaultProtocol.getDefaultPort(), defaultProtocol); + } + + /** + * Sets the protocol, host and port from the given URI. + * @param uri the URI. + */ + public synchronized void setHost(final URI uri) { + try { + setHost(uri.getHost(), uri.getPort(), uri.getScheme()); + } catch (URIException e) { + throw new IllegalArgumentException(e.toString()); + } + } + + /** + * Return the host url. + * + * @return The host url. + */ + public synchronized String getHostURL() { + if (this.host == null) { + throw new IllegalStateException("Host must be set to create a host URL"); + } else { + return this.host.toURI(); + } + } + + /** + * Returns the host. + * + * @return the host(IP or DNS name), or null if not set + * + * @see #isHostSet() + */ + public synchronized String getHost() { + if (this.host != null) { + return this.host.getHostName(); + } else { + return null; + } + } + + /** + * Returns the virtual host. + * + * @return the virtual host name, or null if not set + * + * @deprecated use HostParams + */ + public synchronized String getVirtualHost() { + return this.params.getVirtualHost(); + } + + /** + * Returns the port. + * + * @return the host port, or -1 if not set + * + * @see #isHostSet() + */ + public synchronized int getPort() { + if (this.host != null) { + return this.host.getPort(); + } else { + return -1; + } + } + + /** + * Returns the protocol. + * @return The protocol. + */ + public synchronized Protocol getProtocol() { + if (this.host != null) { + return this.host.getProtocol(); + } else { + return null; + } + } + + /** + * Tests if the proxy host/port have been set. + * + * @return true if a proxy server has been set. + * + * @see #setProxy(String, int) + * + * @deprecated no longer used + */ + public synchronized boolean isProxySet() { + return this.proxyHost != null; + } + + /** + * Sets the given proxy host + * + * @param proxyHost the proxy host + */ + public synchronized void setProxyHost(final ProxyHost proxyHost) { + this.proxyHost = proxyHost; + } + + /** + * Set the proxy settings. + * @param proxyHost The proxy host + * @param proxyPort The proxy port + */ + public synchronized void setProxy(final String proxyHost, int proxyPort) { + this.proxyHost = new ProxyHost(proxyHost, proxyPort); + } + + /** + * Returns the proxyHost. + * + * @return the proxy host, or null if not set + * + * @see #isProxySet() + */ + public synchronized String getProxyHost() { + if (this.proxyHost != null) { + return this.proxyHost.getHostName(); + } else { + return null; + } + } + + /** + * Returns the proxyPort. + * + * @return the proxy port, or -1 if not set + * + * @see #isProxySet() + */ + public synchronized int getProxyPort() { + if (this.proxyHost != null) { + return this.proxyHost.getPort(); + } else { + return -1; + } + } + + /** + * Set the local address to be used when creating connections. + * If this is unset, the default address will be used. + * This is useful for specifying the interface to use on multi-homed or clustered systems. + * + * @param localAddress the local address to use + */ + + public synchronized void setLocalAddress(InetAddress localAddress) { + this.localAddress = localAddress; + } + + /** + * Return the local address to be used when creating connections. + * If this is unset, the default address should be used. + * + * @return the local address to be used when creating Sockets, or null + */ + + public synchronized InetAddress getLocalAddress() { + return this.localAddress; + } + + /** + * Returns {@link HostParams HTTP protocol parameters} associated with this host. + * + * @return HTTP parameters. + * + * @since 3.0 + */ + public HostParams getParams() { + return this.params; + } + + /** + * Assigns {@link HostParams HTTP protocol parameters} specific to this host. + * + * @since 3.0 + * + * @see HostParams + */ + public void setParams(final HostParams params) { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + this.params = params; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public synchronized boolean equals(final Object o) { + if (o instanceof HostConfiguration) { + // shortcut if we're comparing with ourselves + if (o == this) { + return true; + } + HostConfiguration that = (HostConfiguration) o; + return LangUtils.equals(this.host, that.host) + && LangUtils.equals(this.proxyHost, that.proxyHost) + && LangUtils.equals(this.localAddress, that.localAddress); + } else { + return false; + } + + } + + /** + * @see java.lang.Object#hashCode() + */ + public synchronized int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.host); + hash = LangUtils.hashCode(hash, this.proxyHost); + hash = LangUtils.hashCode(hash, this.localAddress); + return hash; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClient.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClient.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClient.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,501 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClient.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.security.Provider; +import java.security.Security; + +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * An HTTP "user-agent", containing an {@link HttpState HTTP state} and + * one or more {@link HttpConnection HTTP connections}, to which + * {@link HttpMethod HTTP methods} can be applied. + *

+ * @author Remy Maucherat + * @author Rodney Waldhoff + * @author Sean C. Sullivan + * @author dIon Gillard + * @author Ortwin Gl?ck + * @author Michael Becke + * @author Mike Bowler + * @author Sam Maloney + * @author Laura Werner + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:33 $ + */ +public class HttpClient { + + + // -------------------------------------------------------------- Constants + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpClient.class); + + static { + + if (LOG.isDebugEnabled()) { + try { + LOG.debug("Java version: " + System.getProperty("java.version")); + LOG.debug("Java vendor: " + System.getProperty("java.vendor")); + LOG.debug("Java class path: " + System.getProperty("java.class.path")); + LOG.debug("Operating system name: " + System.getProperty("os.name")); + LOG.debug("Operating system architecture: " + System.getProperty("os.arch")); + LOG.debug("Operating system version: " + System.getProperty("os.version")); + + Provider[] providers = Security.getProviders(); + for (int i = 0; i < providers.length; i++) { + Provider provider = providers[i]; + LOG.debug(provider.getName() + " " + provider.getVersion() + + ": " + provider.getInfo()); + } + } catch (SecurityException ignore) { + } + } + } + // ----------------------------------------------------------- Constructors + + /** + * Creates an instance of HttpClient using default {@link HttpClientParams parameter set}. + * + * @see HttpClientParams + */ + public HttpClient() { + this(new HttpClientParams()); + } + + /** + * Creates an instance of HttpClient using the given + * {@link HttpClientParams parameter set}. + * + * @param params The {@link HttpClientParams parameters} to use. + * + * @see HttpClientParams + * + * @since 3.0 + */ + public HttpClient(HttpClientParams params) { + super(); + if (params == null) { + throw new IllegalArgumentException("Params may not be null"); + } + this.params = params; + this.httpConnectionManager = null; + Class clazz = params.getConnectionManagerClass(); + if (clazz != null) { + try { + this.httpConnectionManager = (HttpConnectionManager) clazz.newInstance(); + } catch (Exception e) { + LOG.warn("Error instantiating connection manager class, defaulting to" + + " SimpleHttpConnectionManager", + e); + } + } + if (this.httpConnectionManager == null) { + this.httpConnectionManager = new SimpleHttpConnectionManager(); + } + if (this.httpConnectionManager != null) { + this.httpConnectionManager.getParams().setDefaults(this.params); + } + } + + /** + * Creates an instance of HttpClient with a user specified + * {@link HttpClientParams parameter set} and + * {@link HttpConnectionManager HTTP connection manager}. + * + * @param params The {@link HttpClientParams parameters} to use. + * @param httpConnectionManager The {@link HttpConnectionManager connection manager} + * to use. + * + * @since 3.0 + */ + public HttpClient(HttpClientParams params, HttpConnectionManager httpConnectionManager) { + super(); + if (httpConnectionManager == null) { + throw new IllegalArgumentException("httpConnectionManager cannot be null"); + } + if (params == null) { + throw new IllegalArgumentException("Params may not be null"); + } + this.params = params; + this.httpConnectionManager = httpConnectionManager; + if (this.httpConnectionManager != null) { + this.httpConnectionManager.getParams().setDefaults(this.params); + } + } + + /** + * Creates an instance of HttpClient with a user specified + * {@link HttpConnectionManager HTTP connection manager}. + * + * @param httpConnectionManager The {@link HttpConnectionManager connection manager} + * to use. + * + * @since 2.0 + */ + public HttpClient(HttpConnectionManager httpConnectionManager) { + this(new HttpClientParams(), httpConnectionManager); + } + + // ----------------------------------------------------- Instance Variables + + /** + * The {@link HttpConnectionManager connection manager} being used to manage + * connections for this HttpClient + */ + private HttpConnectionManager httpConnectionManager; + + /** + * The {@link HttpState HTTP state} associated with this HttpClient. + */ + private HttpState state = new HttpState(); + + /** + * The {@link HttpClientParams collection of parameters} associated with this HttpClient. + */ + private HttpClientParams params = null; + + /** + * The {@link HostConfiguration host configuration} associated with + * the HttpClient + */ + private HostConfiguration hostConfiguration = new HostConfiguration(); + + // ------------------------------------------------------------- Properties + + /** + * Returns {@link HttpState HTTP state} associated with the HttpClient. + * + * @see #setState(HttpState) + * @return the shared client state + */ + public synchronized HttpState getState() { + return state; + } + + /** + * Assigns {@link HttpState HTTP state} for the HttpClient. + * + * @see #getState() + * @param state the new {@link HttpState HTTP state} for the client + */ + public synchronized void setState(HttpState state) { + this.state = state; + } + + /** + * Defines how strictly the method follows the HTTP protocol specification + * (see RFC 2616 and other relevant RFCs). + * + * In the strict mode the method precisely + * implements the requirements of the specification, whereas in non-strict mode + * it attempts to mimic the exact behaviour of commonly used HTTP agents, + * which many HTTP servers expect. + * + * @param strictMode true for strict mode, false otherwise + * + * @see #isStrictMode() + * + * @deprecated Use {@link HttpClientParams#setParameter(String, Object)} + * to exercise a more granular control over HTTP protocol strictness. + */ + public synchronized void setStrictMode(boolean strictMode) { + if (strictMode) { + this.params.makeStrict(); + } else { + this.params.makeLenient(); + } + } + + /** + * Returns the value of the strict mode flag. + * + * @return true if strict mode is enabled, false otherwise + * + * @see #setStrictMode(boolean) + * + * @deprecated Use + * {@link org.apache.commons.httpclient.params.HttpClientParams#getParameter(String)} + * to exercise a more granular control over HTTP protocol strictness. + */ + public synchronized boolean isStrictMode() { + return false; + } + + /** + * Sets the socket timeout (SO_TIMEOUT) in milliseconds which is the + * timeout for waiting for data. A timeout value of zero is interpreted as an + * infinite timeout. + * + * @param newTimeoutInMilliseconds Timeout in milliseconds + * + * @deprecated Use + * {@link org.apache.commons.httpclient.params.HttpConnectionManagerParams#setSoTimeout(int)}, + * {@link HttpConnectionManager#getParams()}. + * + */ + public synchronized void setTimeout(int newTimeoutInMilliseconds) { + this.params.setSoTimeout(newTimeoutInMilliseconds); + } + + /** + * Sets the timeout in milliseconds used when retrieving an + * {@link HttpConnection HTTP connection} from the + * {@link HttpConnectionManager HTTP connection manager}. + * + * @param timeout the timeout in milliseconds + * + * @see HttpConnectionManager#getConnection(HostConfiguration, long) + * + * @deprecated Use + * {@link org.apache.commons.httpclient.params.HttpClientParams#setConnectionManagerTimeout(long)}, + * {@link HttpClient#getParams()} + */ + public synchronized void setHttpConnectionFactoryTimeout(long timeout) { + this.params.setConnectionManagerTimeout(timeout); + } + + /** + * Sets the timeout until a connection is etablished. A value of zero + * means the timeout is not used. The default value is zero. + * + * @see HttpConnection#setConnectionTimeout(int) + * @param newTimeoutInMilliseconds Timeout in milliseconds. + * + * @deprecated Use + * {@link org.apache.commons.httpclient.params.HttpConnectionManagerParams#setConnectionTimeout(int)}, + * {@link HttpConnectionManager#getParams()}. + */ + public synchronized void setConnectionTimeout(int newTimeoutInMilliseconds) { + this.httpConnectionManager.getParams().setConnectionTimeout(newTimeoutInMilliseconds); + } + + // --------------------------------------------------------- Public Methods + + /** + * Executes the given {@link HttpMethod HTTP method}. + * + * @param method the {@link HttpMethod HTTP method} to execute. + * @return the method's response code + * + * @throws IOException If an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException If a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + public int executeMethod(HttpMethod method) + throws IOException, HttpException { + + LOG.trace("enter HttpClient.executeMethod(HttpMethod)"); + // execute this method and use its host configuration, if it has one + return executeMethod(null, method, null); + } + + /** + * Executes the given {@link HttpMethod HTTP method} using custom + * {@link HostConfiguration host configuration}. + * + * @param hostConfiguration The {@link HostConfiguration host configuration} to use. + * @param method the {@link HttpMethod HTTP method} to execute. + * @return the method's response code + * + * @throws IOException If an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException If a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * @since 2.0 + */ + public int executeMethod(final HostConfiguration hostConfiguration, final HttpMethod method) + throws IOException, HttpException { + + LOG.trace("enter HttpClient.executeMethod(HostConfiguration,HttpMethod)"); + + return executeMethod(hostConfiguration, method, null); + } + + + + /** + * Executes the given {@link HttpMethod HTTP method} using the given custom + * {@link HostConfiguration host configuration} with the given custom + * {@link HttpState HTTP state}. + * + * @param hostconfig The {@link HostConfiguration host configuration} to use. + * @param method the {@link HttpMethod HTTP method} to execute. + * @param state the {@link HttpState HTTP state} to use when executing the method. + * If null, the state returned by {@link #getState} will be used instead. + * + * @return the method's response code + * + * @throws IOException If an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException If a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * @since 2.0 + */ + public int executeMethod(HostConfiguration hostconfig, + final HttpMethod method, final HttpState state) + throws IOException, HttpException { + + LOG.trace("enter HttpClient.executeMethod(HostConfiguration,HttpMethod,HttpState)"); + + if (method == null) { + throw new IllegalArgumentException("HttpMethod parameter may not be null"); + } + HostConfiguration defaulthostconfig = getHostConfiguration(); + if (hostconfig == null) { + hostconfig = defaulthostconfig; + } + URI uri = method.getURI(); + if (hostconfig == defaulthostconfig || uri.isAbsoluteURI()) { + // make a deep copy of the host defaults + hostconfig = new HostConfiguration(hostconfig); + if (uri.isAbsoluteURI()) { + hostconfig.setHost(uri); + } + } + + HttpMethodDirector methodDirector = new HttpMethodDirector( + getHttpConnectionManager(), + hostconfig, + this.params, + (state == null ? getState() : state)); + methodDirector.executeMethod(method); + return method.getStatusCode(); + } + + /** + * Returns the default host. + * + * @return The default host. + * + * @deprecated use #getHostConfiguration() + */ + public String getHost() { + return hostConfiguration.getHost(); + } + + /** + * Returns the default port. + * + * @return The default port. + * + * @deprecated use #getHostConfiguration() + */ + public int getPort() { + return hostConfiguration.getPort(); + } + + /** + * Returns the {@link HostConfiguration host configuration} associated with the + * HttpClient. + * + * @return {@link HostConfiguration host configuration} + * + * @since 2.0 + */ + public synchronized HostConfiguration getHostConfiguration() { + return hostConfiguration; + } + + /** + * Assigns the {@link HostConfiguration host configuration} to use with the + * HttpClient. + * + * @param hostConfiguration The {@link HostConfiguration host configuration} to set + * + * @since 2.0 + */ + public synchronized void setHostConfiguration(HostConfiguration hostConfiguration) { + this.hostConfiguration = hostConfiguration; + } + + /** + * Returns the {@link HttpConnectionManager HTTP connection manager} associated + * with the HttpClient. + * + * @return {@link HttpConnectionManager HTTP connection manager} + * + * @since 2.0 + */ + public synchronized HttpConnectionManager getHttpConnectionManager() { + return httpConnectionManager; + } + + /** + * Assigns the {@link HttpConnectionManager HTTP connection manager} to use with + * the HttpClient. + * + * @param httpConnectionManager The {@link HttpConnectionManager HTTP connection manager} + * to set + * + * @since 2.0 + */ + public synchronized void setHttpConnectionManager( + HttpConnectionManager httpConnectionManager + ) { + this.httpConnectionManager = httpConnectionManager; + if (this.httpConnectionManager != null) { + this.httpConnectionManager.getParams().setDefaults(this.params); + } + } + + /** + * Returns {@link HttpClientParams HTTP protocol parameters} associated with this HttpClient. + * + * @since 3.0 + * + * @see HttpClientParams + */ + public HttpClientParams getParams() { + return this.params; + } + + /** + * Assigns {@link HttpClientParams HTTP protocol parameters} for this HttpClient. + * + * @since 3.0 + * + * @see HttpClientParams + */ + public void setParams(final HttpClientParams params) { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + this.params = params; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClientError.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClientError.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClientError.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,56 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpClientError.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * Signals that an error has occurred. + * + * @author Ortwin Gl?ck + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:35 $ + * @since 3.0 + */ +public class HttpClientError extends Error { + + /** + * Creates a new HttpClientError with a null detail message. + */ + public HttpClientError() { + super(); + } + + /** + * Creates a new HttpClientError with the specified detail message. + * @param message The error message + */ + public HttpClientError(String message) { + super(message); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnection.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnection.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnection.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,1372 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnection.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketException; + +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.httpclient.util.ExceptionUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * An abstraction of an HTTP {@link InputStream} and {@link OutputStream} + * pair, together with the relevant attributes. + *

+ * The following options are set on the socket before getting the input/output + * streams in the {@link #open()} method: + * + * + * + * + * + *
Socket Method + * Sockets Option + * Configuration + *
{@link java.net.Socket#setTcpNoDelay(boolean)} + * SO_NODELAY + * {@link HttpConnectionParams#setTcpNoDelay(boolean)} + *
{@link java.net.Socket#setSoTimeout(int)} + * SO_TIMEOUT + * {@link HttpConnectionParams#setSoTimeout(int)} + *
{@link java.net.Socket#setSendBufferSize(int)} + * SO_SNDBUF + * {@link HttpConnectionParams#setSendBufferSize(int)} + *
{@link java.net.Socket#setReceiveBufferSize(int)} + * SO_RCVBUF + * {@link HttpConnectionParams#setReceiveBufferSize(int)} + *
+ * + * @author Rod Waldhoff + * @author Sean C. Sullivan + * @author Ortwin Glueck + * @author Jeff Dever + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author Michael Becke + * @author Eric E Johnson + * @author Laura Werner + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:34 $ + */ +public class HttpConnection { + + // ----------------------------------------------------------- Constructors + + /** + * Creates a new HTTP connection for the given host and port. + * + * @param host the host to connect to + * @param port the port to connect to + */ + public HttpConnection(String host, int port) { + this(null, -1, host, null, port, Protocol.getProtocol("http")); + } + + /** + * Creates a new HTTP connection for the given host and port + * using the given protocol. + * + * @param host the host to connect to + * @param port the port to connect to + * @param protocol the protocol to use + */ + public HttpConnection(String host, int port, Protocol protocol) { + this(null, -1, host, null, port, protocol); + } + + /** + * Creates a new HTTP connection for the given host with the virtual + * alias and port using given protocol. + * + * @param host the host to connect to + * @param virtualHost the virtual host requests will be sent to + * @param port the port to connect to + * @param protocol the protocol to use + */ + public HttpConnection(String host, String virtualHost, int port, Protocol protocol) { + this(null, -1, host, virtualHost, port, protocol); + } + + /** + * Creates a new HTTP connection for the given host and port via the + * given proxy host and port using the default protocol. + * + * @param proxyHost the host to proxy via + * @param proxyPort the port to proxy via + * @param host the host to connect to + * @param port the port to connect to + */ + public HttpConnection( + String proxyHost, + int proxyPort, + String host, + int port) { + this(proxyHost, proxyPort, host, null, port, Protocol.getProtocol("http")); + } + + /** + * Creates a new HTTP connection for the given host configuration. + * + * @param hostConfiguration the host/proxy/protocol to use + */ + public HttpConnection(HostConfiguration hostConfiguration) { + this(hostConfiguration.getProxyHost(), + hostConfiguration.getProxyPort(), + hostConfiguration.getHost(), + hostConfiguration.getPort(), + hostConfiguration.getProtocol()); + this.localAddress = hostConfiguration.getLocalAddress(); + } + + /** + * Creates a new HTTP connection for the given host with the virtual + * alias and port via the given proxy host and port using the given + * protocol. + * + * @param proxyHost the host to proxy via + * @param proxyPort the port to proxy via + * @param host the host to connect to. Parameter value must be non-null. + * @param virtualHost No longer applicable. + * @param port the port to connect to + * @param protocol The protocol to use. Parameter value must be non-null. + * + * @deprecated use #HttpConnection(String, int, String, int, Protocol) + */ + public HttpConnection( + String proxyHost, + int proxyPort, + String host, + String virtualHost, + int port, + Protocol protocol) { + this(proxyHost, proxyPort, host, port, protocol); + } + + /** + * Creates a new HTTP connection for the given host with the virtual + * alias and port via the given proxy host and port using the given + * protocol. + * + * @param proxyHost the host to proxy via + * @param proxyPort the port to proxy via + * @param host the host to connect to. Parameter value must be non-null. + * @param port the port to connect to + * @param protocol The protocol to use. Parameter value must be non-null. + */ + public HttpConnection( + String proxyHost, + int proxyPort, + String host, + int port, + Protocol protocol) { + + if (host == null) { + throw new IllegalArgumentException("host parameter is null"); + } + if (protocol == null) { + throw new IllegalArgumentException("protocol is null"); + } + + proxyHostName = proxyHost; + proxyPortNumber = proxyPort; + hostName = host; + portNumber = protocol.resolvePort(port); + protocolInUse = protocol; + } + + // ------------------------------------------ Attribute Setters and Getters + + /** + * Returns the connection socket. + * + * @return the socket. + * + * @since 3.0 + */ + protected Socket getSocket() { + return this.socket; + } + + /** + * Returns the host. + * + * @return the host. + */ + public String getHost() { + return hostName; + } + + /** + * Sets the host to connect to. + * + * @param host the host to connect to. Parameter value must be non-null. + * @throws IllegalStateException if the connection is already open + */ + public void setHost(String host) throws IllegalStateException { + if (host == null) { + throw new IllegalArgumentException("host parameter is null"); + } + assertNotOpen(); + hostName = host; + } + + /** + * Returns the target virtual host. + * + * @return the virtual host. + * + * @deprecated no longer applicable + */ + + public String getVirtualHost() { + return this.hostName; + } + + /** + * Sets the virtual host to target. + * + * @param host the virtual host name that should be used instead of + * physical host name when sending HTTP requests. Virtual host + * name can be set to null if virtual host name is not + * to be used + * + * @throws IllegalStateException if the connection is already open + * + * @deprecated no longer applicable + */ + + public void setVirtualHost(String host) throws IllegalStateException { + assertNotOpen(); + } + + /** + * Returns the port of the host. + * + * If the port is -1 (or less than 0) the default port for + * the current protocol is returned. + * + * @return the port. + */ + public int getPort() { + if (portNumber < 0) { + return isSecure() ? 443 : 80; + } else { + return portNumber; + } + } + + /** + * Sets the port to connect to. + * + * @param port the port to connect to + * + * @throws IllegalStateException if the connection is already open + */ + public void setPort(int port) throws IllegalStateException { + assertNotOpen(); + portNumber = port; + } + + /** + * Returns the proxy host. + * + * @return the proxy host. + */ + public String getProxyHost() { + return proxyHostName; + } + + /** + * Sets the host to proxy through. + * + * @param host the host to proxy through. + * + * @throws IllegalStateException if the connection is already open + */ + public void setProxyHost(String host) throws IllegalStateException { + assertNotOpen(); + proxyHostName = host; + } + + /** + * Returns the port of the proxy host. + * + * @return the proxy port. + */ + public int getProxyPort() { + return proxyPortNumber; + } + + /** + * Sets the port of the host to proxy through. + * + * @param port the port of the host to proxy through. + * + * @throws IllegalStateException if the connection is already open + */ + public void setProxyPort(int port) throws IllegalStateException { + assertNotOpen(); + proxyPortNumber = port; + } + + /** + * Returns true if the connection is established over + * a secure protocol. + * + * @return true if connected over a secure protocol. + */ + public boolean isSecure() { + return protocolInUse.isSecure(); + } + + /** + * Returns the protocol used to establish the connection. + * @return The protocol + */ + public Protocol getProtocol() { + return protocolInUse; + } + + /** + * Sets the protocol used to establish the connection + * + * @param protocol The protocol to use. + * + * @throws IllegalStateException if the connection is already open + */ + public void setProtocol(Protocol protocol) { + assertNotOpen(); + + if (protocol == null) { + throw new IllegalArgumentException("protocol is null"); + } + + protocolInUse = protocol; + + } + + /** + * Return the local address used when creating the connection. + * If null, the default address is used. + * + * @return InetAddress the local address to be used when creating Sockets + */ + public InetAddress getLocalAddress() { + return this.localAddress; + } + + /** + * Set the local address used when creating the connection. + * If unset or null, the default address is used. + * + * @param localAddress the local address to use + */ + public void setLocalAddress(InetAddress localAddress) { + assertNotOpen(); + this.localAddress = localAddress; + } + + /** + * Tests if the connection is open. + * + * @return true if the connection is open + */ + public boolean isOpen() { + return isOpen; + } + + /** + * Closes the connection if stale. + * + * @return true if the connection was stale and therefore closed, + * false otherwise. + * + * @see #isStale() + * + * @since 3.0 + */ + public boolean closeIfStale() throws IOException { + if (isOpen && isStale()) { + LOG.debug("Connection is stale, closing..."); + close(); + return true; + } + return false; + } + + /** + * Tests if stale checking is enabled. + * + * @return true if enabled + * + * @see #isStale() + * + * @deprecated Use {@link HttpConnectionParams#isStaleCheckingEnabled()}, + * {@link HttpConnection#getParams()}. + */ + public boolean isStaleCheckingEnabled() { + return this.params.isStaleCheckingEnabled(); + } + + /** + * Sets whether or not isStale() will be called when testing if this connection is open. + * + *

Setting this flag to false will increase performance when reusing + * connections, but it will also make them less reliable. Stale checking ensures that + * connections are viable before they are used. When set to false some + * method executions will result in IOExceptions and they will have to be retried.

+ * + * @param staleCheckEnabled true to enable isStale() + * + * @see #isStale() + * @see #isOpen() + * + * @deprecated Use {@link HttpConnectionParams#setStaleCheckingEnabled(boolean)}, + * {@link HttpConnection#getParams()}. + */ + public void setStaleCheckingEnabled(boolean staleCheckEnabled) { + this.params.setStaleCheckingEnabled(staleCheckEnabled); + } + + /** + * Determines whether this connection is "stale", which is to say that either + * it is no longer open, or an attempt to read the connection would fail. + * + *

Unfortunately, due to the limitations of the JREs prior to 1.4, it is + * not possible to test a connection to see if both the read and write channels + * are open - except by reading and writing. This leads to a difficulty when + * some connections leave the "write" channel open, but close the read channel + * and ignore the request. This function attempts to ameliorate that + * problem by doing a test read, assuming that the caller will be doing a + * write followed by a read, rather than the other way around. + *

+ * + *

To avoid side-effects, the underlying connection is wrapped by a + * {@link BufferedInputStream}, so although data might be read, what is visible + * to clients of the connection will not change with this call.true if the connection is already closed, or a read would + * fail. + */ + protected boolean isStale() throws IOException { + boolean isStale = true; + if (isOpen) { + // the connection is open, but now we have to see if we can read it + // assume the connection is not stale. + isStale = false; + try { + if (inputStream.available() <= 0) { + try { + socket.setSoTimeout(1); + inputStream.mark(1); + int byteRead = inputStream.read(); + if (byteRead == -1) { + // again - if the socket is reporting all data read, + // probably stale + isStale = true; + } else { + inputStream.reset(); + } + } finally { + socket.setSoTimeout(this.params.getSoTimeout()); + } + } + } catch (InterruptedIOException e) { + if (!ExceptionUtil.isSocketTimeoutException(e)) { + throw e; + } + // aha - the connection is NOT stale - continue on! + } catch (IOException e) { + // oops - the connection is stale, the read or soTimeout failed. + LOG.debug( + "An error occurred while reading from the socket, is appears to be stale", + e + ); + isStale = true; + } + } + + return isStale; + } + + /** + * Returns true if the connection is established via a proxy, + * false otherwise. + * + * @return true if a proxy is used to establish the connection, + * false otherwise. + */ + public boolean isProxied() { + return (!(null == proxyHostName || 0 >= proxyPortNumber)); + } + + /** + * Set the state to keep track of the last response for the last request. + * + *

The connection managers use this to ensure that previous requests are + * properly closed before a new request is attempted. That way, a GET + * request need not be read in its entirety before a new request is issued. + * Instead, this stream can be closed as appropriate.

+ * + * @param inStream The stream associated with an HttpMethod. + */ + public void setLastResponseInputStream(InputStream inStream) { + lastResponseInputStream = inStream; + } + + /** + * Returns the stream used to read the last response's body. + * + *

Clients will generally not need to call this function unless + * using HttpConnection directly, instead of calling {@link HttpClient#executeMethod}. + * For those clients, call this function, and if it returns a non-null stream, + * close the stream before attempting to execute a method. Note that + * calling "close" on the stream returned by this function may close + * the connection if the previous response contained a "Connection: close" header.

+ * + * @return An {@link InputStream} corresponding to the body of the last + * response. + */ + public InputStream getLastResponseInputStream() { + return lastResponseInputStream; + } + + // --------------------------------------------------- Other Public Methods + + /** + * Returns {@link HttpConnectionParams HTTP protocol parameters} associated with this method. + * + * @return HTTP parameters. + * + * @since 3.0 + */ + public HttpConnectionParams getParams() { + return this.params; + } + + /** + * Assigns {@link HttpConnectionParams HTTP protocol parameters} for this method. + * + * @since 3.0 + * + * @see HttpConnectionParams + */ + public void setParams(final HttpConnectionParams params) { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + this.params = params; + } + + /** + * Set the {@link Socket}'s timeout, via {@link Socket#setSoTimeout}. If the + * connection is already open, the SO_TIMEOUT is changed. If no connection + * is open, then subsequent connections will use the timeout value. + *

+ * Note: This is not a connection timeout but a timeout on network traffic! + * + * @param timeout the timeout value + * @throws SocketException - if there is an error in the underlying + * protocol, such as a TCP error. + * + * @deprecated Use {@link HttpConnectionParams#setSoTimeout(int)}, + * {@link HttpConnection#getParams()}. + */ + public void setSoTimeout(int timeout) + throws SocketException, IllegalStateException { + this.params.setSoTimeout(timeout); + if (this.socket != null) { + this.socket.setSoTimeout(timeout); + } + } + + /** + * Sets SO_TIMEOUT value directly on the underlying {@link Socket socket}. + * This method does not change the default read timeout value set via + * {@link HttpConnectionParams}. + * + * @param timeout the timeout value + * @throws SocketException - if there is an error in the underlying + * protocol, such as a TCP error. + * @throws IllegalStateException if not connected + * + * @since 3.0 + */ + public void setSocketTimeout(int timeout) + throws SocketException, IllegalStateException { + assertOpen(); + if (this.socket != null) { + this.socket.setSoTimeout(timeout); + } + } + + /** + * Returns the {@link Socket}'s timeout, via {@link Socket#getSoTimeout}, if the + * connection is already open. If no connection is open, return the value subsequent + * connection will use. + *

+ * Note: This is not a connection timeout but a timeout on network traffic! + * + * @return the timeout value + * + * @deprecated Use {@link HttpConnectionParams#getSoTimeout()}, + * {@link HttpConnection#getParams()}. + */ + public int getSoTimeout() throws SocketException { + return this.params.getSoTimeout(); + } + + /** + * Sets the connection timeout. This is the maximum time that may be spent + * until a connection is established. The connection will fail after this + * amount of time. + * @param timeout The timeout in milliseconds. 0 means timeout is not used. + * + * @deprecated Use {@link HttpConnectionParams#setConnectionTimeout(int)}, + * {@link HttpConnection#getParams()}. + */ + public void setConnectionTimeout(int timeout) { + this.params.setConnectionTimeout(timeout); + } + + /** + * Establishes a connection to the specified host and port + * (via a proxy if specified). + * The underlying socket is created from the {@link ProtocolSocketFactory}. + * + * @throws IOException if an attempt to establish the connection results in an + * I/O error. + */ + public void open() throws IOException { + LOG.trace("enter HttpConnection.open()"); + + final String host = (proxyHostName == null) ? hostName : proxyHostName; + final int port = (proxyHostName == null) ? portNumber : proxyPortNumber; + assertNotOpen(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Open connection to " + host + ":" + port); + } + + try { + if (this.socket == null) { + usingSecureSocket = isSecure() && !isProxied(); + // use the protocol's socket factory unless this is a secure + // proxied connection + ProtocolSocketFactory socketFactory = null; + if (isSecure() && isProxied()) { + Protocol defaultprotocol = Protocol.getProtocol("http"); + socketFactory = defaultprotocol.getSocketFactory(); + } else { + socketFactory = this.protocolInUse.getSocketFactory(); + } + this.socket = socketFactory.createSocket( + host, port, + localAddress, 0, + this.params); + } + + /* + "Nagling has been broadly implemented across networks, + including the Internet, and is generally performed by default + - although it is sometimes considered to be undesirable in + highly interactive environments, such as some client/server + situations. In such cases, nagling may be turned off through + use of the TCP_NODELAY sockets option." */ + + socket.setTcpNoDelay(this.params.getTcpNoDelay()); + socket.setSoTimeout(this.params.getSoTimeout()); + + int linger = this.params.getLinger(); + if (linger >= 0) { + socket.setSoLinger(linger > 0, linger); + } + + int sndBufSize = this.params.getSendBufferSize(); + if (sndBufSize >= 0) { + socket.setSendBufferSize(sndBufSize); + } + int rcvBufSize = this.params.getReceiveBufferSize(); + if (rcvBufSize >= 0) { + socket.setReceiveBufferSize(rcvBufSize); + } + int outbuffersize = socket.getSendBufferSize(); + if ((outbuffersize > 2048) || (outbuffersize <= 0)) { + outbuffersize = 2048; + } + int inbuffersize = socket.getReceiveBufferSize(); + if ((inbuffersize > 2048) || (inbuffersize <= 0)) { + inbuffersize = 2048; + } + inputStream = new BufferedInputStream(socket.getInputStream(), inbuffersize); + outputStream = new BufferedOutputStream(socket.getOutputStream(), outbuffersize); + isOpen = true; + } catch (IOException e) { + // Connection wasn't opened properly + // so close everything out + closeSocketAndStreams(); + throw e; + } + } + + /** + * Instructs the proxy to establish a secure tunnel to the host. The socket will + * be switched to the secure socket. Subsequent communication is done via the secure + * socket. The method can only be called once on a proxied secure connection. + * + * @throws IllegalStateException if connection is not secure and proxied or + * if the socket is already secure. + * @throws IOException if an attempt to establish the secure tunnel results in an + * I/O error. + */ + public void tunnelCreated() throws IllegalStateException, IOException { + LOG.trace("enter HttpConnection.tunnelCreated()"); + + if (!isSecure() || !isProxied()) { + throw new IllegalStateException( + "Connection must be secure " + + "and proxied to use this feature"); + } + + if (usingSecureSocket) { + throw new IllegalStateException("Already using a secure socket"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Secure tunnel to " + this.hostName + ":" + this.portNumber); + } + + SecureProtocolSocketFactory socketFactory = + (SecureProtocolSocketFactory) protocolInUse.getSocketFactory(); + + socket = socketFactory.createSocket(socket, hostName, portNumber, true); + int sndBufSize = this.params.getSendBufferSize(); + if (sndBufSize >= 0) { + socket.setSendBufferSize(sndBufSize); + } + int rcvBufSize = this.params.getReceiveBufferSize(); + if (rcvBufSize >= 0) { + socket.setReceiveBufferSize(rcvBufSize); + } + int outbuffersize = socket.getSendBufferSize(); + if (outbuffersize > 2048) { + outbuffersize = 2048; + } + int inbuffersize = socket.getReceiveBufferSize(); + if (inbuffersize > 2048) { + inbuffersize = 2048; + } + inputStream = new BufferedInputStream(socket.getInputStream(), inbuffersize); + outputStream = new BufferedOutputStream(socket.getOutputStream(), outbuffersize); + usingSecureSocket = true; + tunnelEstablished = true; + } + + /** + * Indicates if the connection is completely transparent from end to end. + * + * @return true if conncetion is not proxied or tunneled through a transparent + * proxy; false otherwise. + */ + public boolean isTransparent() { + return !isProxied() || tunnelEstablished; + } + + /** + * Flushes the output request stream. This method should be called to + * ensure that data written to the request OutputStream is sent to the server. + * + * @throws IOException if an I/O problem occurs + */ + public void flushRequestOutputStream() throws IOException { + LOG.trace("enter HttpConnection.flushRequestOutputStream()"); + assertOpen(); + outputStream.flush(); + } + + /** + * Returns an {@link OutputStream} suitable for writing the request. + * + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + * @return a stream to write the request to + */ + public OutputStream getRequestOutputStream() + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.getRequestOutputStream()"); + assertOpen(); + OutputStream out = this.outputStream; + if (Wire.CONTENT_WIRE.enabled()) { + out = new WireLogOutputStream(out, Wire.CONTENT_WIRE); + } + return out; + } + + /** + * Return a {@link InputStream} suitable for reading the response. + * @return InputStream The response input stream. + * @throws IOException If an IO problem occurs + * @throws IllegalStateException If the connection isn't open. + */ + public InputStream getResponseInputStream() + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.getResponseInputStream()"); + assertOpen(); + return inputStream; + } + + /** + * Tests if input data avaialble. This method returns immediately + * and does not perform any read operations on the input socket + * + * @return boolean true if input data is available, + * false otherwise. + * + * @throws IOException If an IO problem occurs + * @throws IllegalStateException If the connection isn't open. + */ + public boolean isResponseAvailable() + throws IOException { + LOG.trace("enter HttpConnection.isResponseAvailable()"); + if (this.isOpen) { + return this.inputStream.available() > 0; + } else { + return false; + } + } + + /** + * Tests if input data becomes available within the given period time in milliseconds. + * + * @param timeout The number milliseconds to wait for input data to become available + * @return boolean true if input data is availble, + * false otherwise. + * + * @throws IOException If an IO problem occurs + * @throws IllegalStateException If the connection isn't open. + */ + public boolean isResponseAvailable(int timeout) + throws IOException { + LOG.trace("enter HttpConnection.isResponseAvailable(int)"); + assertOpen(); + boolean result = false; + if (this.inputStream.available() > 0) { + result = true; + } else { + try { + this.socket.setSoTimeout(timeout); + inputStream.mark(1); + int byteRead = inputStream.read(); + if (byteRead != -1) { + inputStream.reset(); + LOG.debug("Input data available"); + result = true; + } else { + LOG.debug("Input data not available"); + } + } catch (InterruptedIOException e) { + if (!ExceptionUtil.isSocketTimeoutException(e)) { + throw e; + } + if (LOG.isDebugEnabled()) { + LOG.debug("Input data not available after " + timeout + " ms"); + } + } finally { + try { + socket.setSoTimeout(this.params.getSoTimeout()); + } catch (IOException ioe) { + LOG.debug("An error ocurred while resetting soTimeout, we will assume that" + + " no response is available.", + ioe); + result = false; + } + } + } + return result; + } + + /** + * Writes the specified bytes to the output stream. + * + * @param data the data to be written + * @throws IllegalStateException if not connected + * @throws IOException if an I/O problem occurs + * @see #write(byte[],int,int) + */ + public void write(byte[] data) + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.write(byte[])"); + this.write(data, 0, data.length); + } + + /** + * Writes length bytes in data starting at + * offset to the output stream. + * + * The general contract for + * write(b, off, len) is that some of the bytes in the array b are written + * to the output stream in order; element b[off] is the first byte written + * and b[off+len-1] is the last byte written by this operation. + * + * @param data array containing the data to be written. + * @param offset the start offset in the data. + * @param length the number of bytes to write. + * @throws IllegalStateException if not connected + * @throws IOException if an I/O problem occurs + */ + public void write(byte[] data, int offset, int length) + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.write(byte[], int, int)"); + + if (offset < 0) { + throw new IllegalArgumentException("Array offset may not be negative"); + } + if (length < 0) { + throw new IllegalArgumentException("Array length may not be negative"); + } + if (offset + length > data.length) { + throw new IllegalArgumentException("Given offset and length exceed the array length"); + } + assertOpen(); + this.outputStream.write(data, offset, length); + } + + /** + * Writes the specified bytes, followed by "\r\n".getBytes() to the + * output stream. + * + * @param data the bytes to be written + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + */ + public void writeLine(byte[] data) + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.writeLine(byte[])"); + write(data); + writeLine(); + } + + /** + * Writes "\r\n".getBytes() to the output stream. + * + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + */ + public void writeLine() + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.writeLine()"); + write(CRLF); + } + + /** + * @deprecated Use {@link #print(String, String)} + * + * Writes the specified String (as bytes) to the output stream. + * + * @param data the string to be written + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + */ + public void print(String data) + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.print(String)"); + write(EncodingUtil.getBytes(data, "ISO-8859-1")); + } + + /** + * Writes the specified String (as bytes) to the output stream. + * + * @param data the string to be written + * @param charset the charset to use for writing the data + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + * + * @since 3.0 + */ + public void print(String data, String charset) + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.print(String)"); + write(EncodingUtil.getBytes(data, charset)); + } + + /** + * @deprecated Use {@link #printLine(String, String)} + * + * Writes the specified String (as bytes), followed by + * "\r\n".getBytes() to the output stream. + * + * @param data the data to be written + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + */ + public void printLine(String data) + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.printLine(String)"); + writeLine(EncodingUtil.getBytes(data, "ISO-8859-1")); + } + + /** + * Writes the specified String (as bytes), followed by + * "\r\n".getBytes() to the output stream. + * + * @param data the data to be written + * @param charset the charset to use for writing the data + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + * + * @since 3.0 + */ + public void printLine(String data, String charset) + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.printLine(String)"); + writeLine(EncodingUtil.getBytes(data, charset)); + } + + /** + * Writes "\r\n".getBytes() to the output stream. + * + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + */ + public void printLine() + throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.printLine()"); + writeLine(); + } + + /** + * Reads up to "\n" from the (unchunked) input stream. + * If the stream ends before the line terminator is found, + * the last part of the string will still be returned. + * + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + * @return a line from the response + * + * @deprecated use #readLine(String) + */ + public String readLine() throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.readLine()"); + + assertOpen(); + return HttpParser.readLine(inputStream); + } + + /** + * Reads up to "\n" from the (unchunked) input stream. + * If the stream ends before the line terminator is found, + * the last part of the string will still be returned. + * + * @param charset the charset to use for reading the data + * + * @throws IllegalStateException if the connection is not open + * @throws IOException if an I/O problem occurs + * @return a line from the response + * + * @since 3.0 + */ + public String readLine(final String charset) throws IOException, IllegalStateException { + LOG.trace("enter HttpConnection.readLine()"); + + assertOpen(); + return HttpParser.readLine(inputStream, charset); + } + + /** + * Attempts to shutdown the {@link Socket}'s output, via Socket.shutdownOutput() + * when running on JVM 1.3 or higher. + * + * @deprecated unused + */ + public void shutdownOutput() { + LOG.trace("enter HttpConnection.shutdownOutput()"); + + try { + // Socket.shutdownOutput is a JDK 1.3 + // method. We'll use reflection in case + // we're running in an older VM + Class[] paramsClasses = new Class[0]; + Method shutdownOutput = + socket.getClass().getMethod("shutdownOutput", paramsClasses); + Object[] params = new Object[0]; + shutdownOutput.invoke(socket, params); + } catch (Exception ex) { + LOG.debug("Unexpected Exception caught", ex); + // Ignore, and hope everything goes right + } + // close output stream? + } + + /** + * Closes the socket and streams. + */ + public void close() { + LOG.trace("enter HttpConnection.close()"); + closeSocketAndStreams(); + } + + /** + * Returns the httpConnectionManager. + * @return HttpConnectionManager + */ + public HttpConnectionManager getHttpConnectionManager() { + return httpConnectionManager; + } + + /** + * Sets the httpConnectionManager. + * @param httpConnectionManager The httpConnectionManager to set + */ + public void setHttpConnectionManager(HttpConnectionManager httpConnectionManager) { + this.httpConnectionManager = httpConnectionManager; + } + + /** + * Releases the connection. If the connection is locked or does not have a connection + * manager associated with it, this method has no effect. Note that it is completely safe + * to call this method multiple times. + */ + public void releaseConnection() { + LOG.trace("enter HttpConnection.releaseConnection()"); + if (locked) { + LOG.debug("Connection is locked. Call to releaseConnection() ignored."); + } else if (httpConnectionManager != null) { + LOG.debug("Releasing connection back to connection manager."); + httpConnectionManager.releaseConnection(this); + } else { + LOG.warn("HttpConnectionManager is null. Connection cannot be released."); + } + } + + /** + * Tests if the connection is locked. Locked connections cannot be released. + * An attempt to release a locked connection will have no effect. + * + * @return true if the connection is locked, false otherwise. + * + * @since 3.0 + */ + protected boolean isLocked() { + return locked; + } + + /** + * Locks or unlocks the connection. Locked connections cannot be released. + * An attempt to release a locked connection will have no effect. + * + * @param locked true to lock the connection, false to unlock + * the connection. + * + * @since 3.0 + */ + protected void setLocked(boolean locked) { + this.locked = locked; + } + // ------------------------------------------------------ Protected Methods + + /** + * Closes everything out. + */ + protected void closeSocketAndStreams() { + LOG.trace("enter HttpConnection.closeSockedAndStreams()"); + + isOpen = false; + + // no longer care about previous responses... + lastResponseInputStream = null; + + if (null != outputStream) { + OutputStream temp = outputStream; + outputStream = null; + try { + temp.close(); + } catch (Exception ex) { + LOG.debug("Exception caught when closing output", ex); + // ignored + } + } + + if (null != inputStream) { + InputStream temp = inputStream; + inputStream = null; + try { + temp.close(); + } catch (Exception ex) { + LOG.debug("Exception caught when closing input", ex); + // ignored + } + } + + if (null != socket) { + Socket temp = socket; + socket = null; + try { + temp.close(); + } catch (Exception ex) { + LOG.debug("Exception caught when closing socket", ex); + // ignored + } + } + + tunnelEstablished = false; + usingSecureSocket = false; + } + + /** + * Throws an {@link IllegalStateException} if the connection is already open. + * + * @throws IllegalStateException if connected + */ + protected void assertNotOpen() throws IllegalStateException { + if (isOpen) { + throw new IllegalStateException("Connection is open"); + } + } + + /** + * Throws an {@link IllegalStateException} if the connection is not open. + * + * @throws IllegalStateException if not connected + */ + protected void assertOpen() throws IllegalStateException { + if (!isOpen) { + throw new IllegalStateException("Connection is not open"); + } + } + + /** + * Gets the socket's sendBufferSize. + * + * @return the size of the buffer for the socket OutputStream, -1 if the value + * has not been set and the socket has not been opened + * + * @throws SocketException if an error occurs while getting the socket value + * + * @see Socket#getSendBufferSize() + */ + public int getSendBufferSize() throws SocketException { + if (socket == null) { + return -1; + } else { + return socket.getSendBufferSize(); + } + } + + /** + * Sets the socket's sendBufferSize. + * + * @param sendBufferSize the size to set for the socket OutputStream + * + * @throws SocketException if an error occurs while setting the socket value + * + * @see Socket#setSendBufferSize(int) + * + * @deprecated Use {@link HttpConnectionParams#setSendBufferSize(int)}, + * {@link HttpConnection#getParams()}. + */ + public void setSendBufferSize(int sendBufferSize) throws SocketException { + this.params.setSendBufferSize(sendBufferSize); + } + + // ------------------------------------------------------- Static Variable + + /** "\r\n", as bytes. */ + private static final byte[] CRLF = new byte[] {(byte) 13, (byte) 10}; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpConnection.class); + + // ----------------------------------------------------- Instance Variables + + /** My host. */ + private String hostName = null; + + /** My port. */ + private int portNumber = -1; + + /** My proxy host. */ + private String proxyHostName = null; + + /** My proxy port. */ + private int proxyPortNumber = -1; + + /** My client Socket. */ + private Socket socket = null; + + /** My InputStream. */ + private InputStream inputStream = null; + + /** My OutputStream. */ + private OutputStream outputStream = null; + + /** An {@link InputStream} for the response to an individual request. */ + private InputStream lastResponseInputStream = null; + + /** Whether or not the connection is connected. */ + protected boolean isOpen = false; + + /** the protocol being used */ + private Protocol protocolInUse; + + /** Collection of HTTP parameters associated with this HTTP connection*/ + private HttpConnectionParams params = new HttpConnectionParams(); + + /** flag to indicate if this connection can be released, if locked the connection cannot be + * released */ + private boolean locked = false; + + /** Whether or not the socket is a secure one. */ + private boolean usingSecureSocket = false; + + /** Whether the connection is open via a secure tunnel or not */ + private boolean tunnelEstablished = false; + + /** the connection manager that created this connection or null */ + private HttpConnectionManager httpConnectionManager; + + /** The local interface on which the connection is created, or null for the default */ + private InetAddress localAddress; +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnectionManager.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnectionManager.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnectionManager.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,150 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConnectionManager.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; + +/** + * An interface for classes that manage HttpConnections. + * + * @see org.apache.commons.httpclient.HttpConnection + * @see org.apache.commons.httpclient.HttpClient#HttpClient(HttpConnectionManager) + * + * @author Michael Becke + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @since 2.0 + */ +public interface HttpConnectionManager { + + /** + * Gets an HttpConnection for a given host configuration. If a connection is + * not available this method will block until one is. + * + * The connection manager should be registered with any HttpConnection that + * is created. + * + * @param hostConfiguration the host configuration to use to configure the + * connection + * + * @return an HttpConnection for the given configuration + * + * @see HttpConnection#setHttpConnectionManager(HttpConnectionManager) + */ + HttpConnection getConnection(HostConfiguration hostConfiguration); + + /** + * Gets an HttpConnection for a given host configuration. If a connection is + * not available, this method will block for at most the specified number of + * milliseconds or until a connection becomes available. + * + * The connection manager should be registered with any HttpConnection that + * is created. + * + * @param hostConfiguration the host configuration to use to configure the + * connection + * @param timeout - the time (in milliseconds) to wait for a connection to + * become available, 0 to specify an infinite timeout + * + * @return an HttpConnection for the given configuraiton + * + * @throws HttpException if no connection becomes available before the + * timeout expires + * + * @see HttpConnection#setHttpConnectionManager(HttpConnectionManager) + * + * @deprecated Use #getConnectionWithTimeout(HostConfiguration, long) + */ + HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout) + throws HttpException; + + /** + * Gets an HttpConnection for a given host configuration. If a connection is + * not available, this method will block for at most the specified number of + * milliseconds or until a connection becomes available. + * + * The connection manager should be registered with any HttpConnection that + * is created. + * + * @param hostConfiguration the host configuration to use to configure the + * connection + * @param timeout - the time (in milliseconds) to wait for a connection to + * become available, 0 to specify an infinite timeout + * + * @return an HttpConnection for the given configuraiton + * + * @throws ConnectionPoolTimeoutException if no connection becomes available before the + * timeout expires + * + * @see HttpConnection#setHttpConnectionManager(HttpConnectionManager) + * + * @since 3.0 + */ + HttpConnection getConnectionWithTimeout(HostConfiguration hostConfiguration, long timeout) + throws ConnectionPoolTimeoutException; + + /** + * Releases the given HttpConnection for use by other requests. + * + * @param conn - The HttpConnection to make available. + */ + void releaseConnection(HttpConnection conn); + + /** + * Closes connections that have been idle for at least the given amount of time. Only + * connections that are currently owned, not checked out, are subject to idle timeouts. + * + * @param idleTimeout the minimum idle time, in milliseconds, for connections to be closed + * + * @since 3.0 + */ + void closeIdleConnections(long idleTimeout); + + /** + * Returns {@link HttpConnectionManagerParams parameters} associated + * with this connection manager. + * + * @since 3.0 + * + * @see HttpConnectionManagerParams + */ + HttpConnectionManagerParams getParams(); + + /** + * Assigns {@link HttpConnectionManagerParams parameters} for this + * connection manager. + * + * @since 3.0 + * + * @see HttpConnectionManagerParams + */ + void setParams(final HttpConnectionManagerParams params); +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConstants.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConstants.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConstants.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,327 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpConstants.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.UnsupportedEncodingException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * HTTP content conversion routines. + * + * @author Oleg Kalnichevski + * @author Mike Bowler + * + * @deprecated use EncodingUtil class + */ +public class HttpConstants { + + /** Character set used to encode HTTP protocol elements */ + public static final String HTTP_ELEMENT_CHARSET = "US-ASCII"; + + /** Default content encoding chatset */ + public static final String DEFAULT_CONTENT_CHARSET = "ISO-8859-1"; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpConstants.class); + + /** + * Converts the specified string to a byte array of HTTP element characters. + * This method is to be used when encoding content of HTTP elements (such as + * request headers) + * + * @param data the string to be encoded + * @return The resulting byte array. + */ + public static byte[] getBytes(final String data) { + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + try { + return data.getBytes(HTTP_ELEMENT_CHARSET); + } catch (UnsupportedEncodingException e) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + + HTTP_ELEMENT_CHARSET + + ". System default encoding used"); + } + + return data.getBytes(); + } + } + + /** + * Converts the byte array of HTTP element characters to a string This + * method is to be used when decoding content of HTTP elements (such as + * response headers) + * + * @param data the byte array to be encoded + * @param offset the index of the first byte to encode + * @param length the number of bytes to encode + * @return The resulting string. + */ + public static String getString(final byte[] data, int offset, int length) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + try { + return new String(data, offset, length, HTTP_ELEMENT_CHARSET); + } catch (UnsupportedEncodingException e) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + + HTTP_ELEMENT_CHARSET + + ". System default encoding used"); + } + + return new String(data, offset, length); + } + } + + /** + * Converts the byte array of HTTP element characters to a string This + * method is to be used when decoding content of HTTP elements (such as + * response headers) + * + * @param data the byte array to be encoded + * @return The resulting string. + */ + public static String getString(final byte[] data) { + return getString(data, 0, data.length); + } + + /** + * Converts the specified string to a byte array of HTTP content charachetrs + * This method is to be used when encoding content of HTTP request/response + * If the specified charset is not supported, default HTTP content encoding + * (ISO-8859-1) is applied + * + * @param data the string to be encoded + * @param charset the desired character encoding + * @return The resulting byte array. + */ + public static byte[] getContentBytes(final String data, String charset) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + if ((charset == null) || (charset.equals(""))) { + charset = DEFAULT_CONTENT_CHARSET; + } + + try { + return data.getBytes(charset); + } catch (UnsupportedEncodingException e) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + + charset + + ". HTTP default encoding used"); + } + + try { + return data.getBytes(DEFAULT_CONTENT_CHARSET); + } catch (UnsupportedEncodingException e2) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + + DEFAULT_CONTENT_CHARSET + + ". System encoding used"); + } + + return data.getBytes(); + } + } + } + + /** + * Converts the byte array of HTTP content characters to a string This + * method is to be used when decoding content of HTTP request/response If + * the specified charset is not supported, default HTTP content encoding + * (ISO-8859-1) is applied + * + * @param data the byte array to be encoded + * @param offset the index of the first byte to encode + * @param length the number of bytes to encode + * @param charset the desired character encoding + * @return The result of the conversion. + */ + public static String getContentString( + final byte[] data, + int offset, + int length, + String charset + ) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + if ((charset == null) || (charset.equals(""))) { + charset = DEFAULT_CONTENT_CHARSET; + } + + try { + return new String(data, offset, length, charset); + } catch (UnsupportedEncodingException e) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + charset + ". Default HTTP encoding used"); + } + + try { + return new String(data, offset, length, DEFAULT_CONTENT_CHARSET); + } catch (UnsupportedEncodingException e2) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + + DEFAULT_CONTENT_CHARSET + + ". System encoding used"); + } + + return new String(data, offset, length); + } + } + } + + + /** + * Converts the byte array of HTTP content characters to a string This + * method is to be used when decoding content of HTTP request/response If + * the specified charset is not supported, default HTTP content encoding + * (ISO-8859-1) is applied + * + * @param data the byte array to be encoded + * @param charset the desired character encoding + * @return The result of the conversion. + */ + public static String getContentString(final byte[] data, String charset) { + return getContentString(data, 0, data.length, charset); + } + + /** + * Converts the specified string to a byte array of HTTP content characters + * using default HTTP content encoding (ISO-8859-1) This method is to be + * used when encoding content of HTTP request/response + * + * @param data the string to be encoded + * @return The byte array as above. + */ + public static byte[] getContentBytes(final String data) { + return getContentBytes(data, null); + } + + /** + * Converts the byte array of HTTP content characters to a string using + * default HTTP content encoding (ISO-8859-1) This method is to be used when + * decoding content of HTTP request/response + * + * @param data the byte array to be encoded + * @param offset the index of the first byte to encode + * @param length the number of bytes to encode + * @return The string representation of the byte array. + */ + public static String getContentString(final byte[] data, int offset, int length) { + return getContentString(data, offset, length, null); + } + + /** + * Converts the byte array of HTTP content characters to a string using + * default HTTP content encoding (ISO-8859-1) This method is to be used when + * decoding content of HTTP request/response + * + * @param data the byte array to be encoded + * @return The string representation of the byte array. + */ + public static String getContentString(final byte[] data) { + return getContentString(data, null); + } + + /** + * Converts the specified string to byte array of ASCII characters. + * + * @param data the string to be encoded + * @return The string as a byte array. + */ + public static byte[] getAsciiBytes(final String data) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + try { + return data.getBytes("US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("HttpClient requires ASCII support"); + } + } + + /** + * Converts the byte array of ASCII characters to a string. This method is + * to be used when decoding content of HTTP elements (such as response + * headers) + * + * @param data the byte array to be encoded + * @param offset the index of the first byte to encode + * @param length the number of bytes to encode + * @return The string representation of the byte array + */ + public static String getAsciiString(final byte[] data, int offset, int length) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + try { + return new String(data, offset, length, "US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("HttpClient requires ASCII support"); + } + } + + /** + * Converts the byte array of ASCII characters to a string. This method is + * to be used when decoding content of HTTP elements (such as response + * headers) + * + * @param data the byte array to be encoded + * @return The string representation of the byte array + */ + public static String getAsciiString(final byte[] data) { + return getAsciiString(data, 0, data.length); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpException.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,234 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpException.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.reflect.Method; + +/** + * Signals that an HTTP or HttpClient exception has occurred. + * + * @author Laura Werner + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:34 $ + */ +public class HttpException extends IOException { + + /** + * Creates a new HttpException with a null detail message. + */ + public HttpException() { + super(); + this.cause = null; + } + + /** + * Creates a new HttpException with the specified detail message. + * + * @param message the exception detail message + */ + public HttpException(String message) { + super(message); + this.cause = null; + } + + /** + * Creates a new HttpException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + * + * @since 3.0 + */ + public HttpException(String message, Throwable cause) { + super(message); + this.cause = cause; + + // If we're running on JDK 1.4 or later, tell Throwable what the cause was + try { + Class[] paramsClasses = new Class[] { Throwable.class }; + Method initCause = Throwable.class.getMethod("initCause", paramsClasses); + initCause.invoke(this, new Object[] { cause }); + } catch (Exception e) { + // The setCause method must not be available + } + } + + /** + * Return the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable. + * + * @return the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + * + * @since 3.0 + */ + public Throwable getCause() { + return cause; + } + + /** + * Print this HttpException and its stack trace to the standard error stream. + * + * @since 3.0 + */ + public void printStackTrace() { + printStackTrace(System.err); + } + + /** + * Print this HttpException and its stack trace to the specified print stream. + * + * @param s the PrintStream to which the exception and its stack trace + * should be written + * + * @since 3.0 + */ + public void printStackTrace(PrintStream s) { + try { + // JDK 1.4 has a nice printStackTrace method that prints the cause's stack + // trace too and prunes out duplicate stack frames. Call it if possible, + // which is determined by checking whether JDK 1.4's getStackTrace method is present + Class[] paramsClasses = new Class[] { }; + this.getClass().getMethod("getStackTrace", paramsClasses); + super.printStackTrace(s); + } catch (Exception ex) { + // If that didn't work, print it out ourselves + // First print this exception's stack trace. + super.printStackTrace(s); + if (cause != null) { + // Print out the exception that caused this one. + // This will recurse if the cause is another HttpException. + s.print("Caused by: "); + cause.printStackTrace(s); + } + } + } + + /** + * Print this HttpException and its stack trace to the specified print writer. + * + * @param s the PrintWriter to which the exception and its stack trace + * should be written + * + * @since 3.0 + */ + public void printStackTrace(PrintWriter s) { + try { + // JDK 1.4 has a nice printStackTrace method that prints the cause's stack + // trace too and prunes out duplicate stack frames. Call it if possible, + // which is determined by checking whether JDK 1.4's getStackTrace method is present + Class[] paramsClasses = new Class[] { }; + this.getClass().getMethod("getStackTrace", paramsClasses); + super.printStackTrace(s); + } catch (Exception ex) { + // If that didn't work, print it out ourselves + // First print this exception's stack trace. + super.printStackTrace(s); + if (cause != null) { + // Print out the exception that caused this one. + // This will recurse if the cause is another HttpException. + s.print("Caused by: "); + cause.printStackTrace(s); + } + } + } + + /** + * Sets the text description of the reason for an exception. + * + * @param reason The reason for the exception. + * + * @deprecated HttpClient no longer uses this for itself. It is only + * provided for compatibility with existing clients, and will be removed + * in a future release. + */ + public void setReason(String reason) { + this.reason = reason; + } + + /** + * Get the text description of the reason for an exception. + * + * @deprecated HttpClient no longer uses this for itself. It is only + * provided for compatibility with existing clients, and will be removed + * in a future release. + */ + public String getReason() { + return reason; + } + + /** + * Sets the status code description of the reason for an exception. + * + * @param code The reason for the exception. This is intended to be an + * HTTP status code. + * + * @deprecated HttpClient no longer uses this for itself. It is only + * provided for compatibility with existing clients, and will be removed + * in a future release. + */ + public void setReasonCode(int code) { + reasonCode = code; + } + + /** + * Get the status code description of the reason for an exception. + * + * @deprecated HttpClient no longer uses this for itself. It is only + * provided for compatibility with existing clients, and will be removed + * in a future release. + */ + public int getReasonCode() { + return this.reasonCode; + } + + /** + * A "reason" string provided for compatibility with older clients. + * + * @deprecated HttpClient no longer uses this field for itself. It + * is only provided for compatibility with existing clients. + */ + private String reason; + + /** + * Reason code for compatibility with older clients. + * + * @deprecated HttpClient no longer uses this field for itself. + * It is only provided for compatibility with existing clients. + */ + private int reasonCode = HttpStatus.SC_OK; + + /** The original Throwable representing the cause of this error */ + private final Throwable cause; +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpHost.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpHost.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpHost.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,220 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpHost.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.util.LangUtils; + +/** + * Holds all of the variables needed to describe an HTTP connection to a host. This includes + * remote host, port and protocol. + * + * @author Michael Becke + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author Laura Werner + * + * @since 3.0 + */ +public class HttpHost implements Cloneable { + + /** The host to use. */ + private String hostname = null; + + /** The port to use. */ + private int port = -1; + + /** The protocol */ + private Protocol protocol = null; + + /** + * Constructor for HttpHost. + * + * @param hostname the hostname (IP or DNS name). Can be null. + * @param port the port. Value -1 can be used to set default protocol port + * @param protocol the protocol. Value null can be used to set default protocol + */ + public HttpHost(final String hostname, int port, final Protocol protocol) { + super(); + if (hostname == null) { + throw new IllegalArgumentException("Host name may not be null"); + } + if (protocol == null) { + throw new IllegalArgumentException("Protocol may not be null"); + } + this.hostname = hostname; + this.protocol = protocol; + if (port >= 0) { + this.port = port; + } else { + this.port = this.protocol.getDefaultPort(); + } + } + + /** + * Constructor for HttpHost. + * + * @param hostname the hostname (IP or DNS name). Can be null. + * @param port the port. Value -1 can be used to set default protocol port + */ + public HttpHost(final String hostname, int port) { + this(hostname, port, Protocol.getProtocol("http")); + } + + /** + * Constructor for HttpHost. + * + * @param hostname the hostname (IP or DNS name). Can be null. + */ + public HttpHost(final String hostname) { + this(hostname, -1, Protocol.getProtocol("http")); + } + + /** + * URI constructor for HttpHost. + * + * @param uri the URI. + */ + public HttpHost(final URI uri) throws URIException { + this(uri.getHost(), uri.getPort(), Protocol.getProtocol(uri.getScheme())); + } + + /** + * Copy constructor for HttpHost + * + * @param httphost the HTTP host to copy details from + */ + public HttpHost (final HttpHost httphost) { + super(); + this.hostname = httphost.hostname; + this.port = httphost.port; + this.protocol = httphost.protocol; + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() { + return new HttpHost(this); + } + + /** + * Returns the host name (IP or DNS name). + * + * @return the host name (IP or DNS name), or null if not set + */ + public String getHostName() { + return this.hostname; + } + + /** + * Returns the port. + * + * @return the host port, or -1 if not set + */ + public int getPort() { + return this.port; + } + + /** + * Returns the protocol. + * @return The protocol. + */ + public Protocol getProtocol() { + return this.protocol; + } + + /** + * Return the host uri. + * + * @return The host uri. + */ + public String toURI() { + StringBuffer buffer = new StringBuffer(50); + if (this.protocol != null) { + buffer.append(this.protocol.getScheme()); + buffer.append("://"); + } + buffer.append(this.hostname); + if (this.port != this.protocol.getDefaultPort()) { + buffer.append(':'); + buffer.append(this.port); + } + return buffer.toString(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buffer = new StringBuffer(50); + buffer.append(toURI()); + return buffer.toString(); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(final Object o) { + + if (o instanceof HttpHost) { + // shortcut if we're comparing with ourselves + if (o == this) { + return true; + } + HttpHost that = (HttpHost) o; + if (!this.hostname.equalsIgnoreCase(that.hostname)) { + return false; + } + if (this.port != that.port) { + return false; + } + if (!this.protocol.equals(that.protocol)) { + return false; + } + // everything matches + return true; + } else { + return false; + } + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.hostname); + hash = LangUtils.hashCode(hash, this.port); + hash = LangUtils.hashCode(hash, this.protocol); + return hash; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethod.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,576 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethod.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.httpclient.auth.AuthState; +import org.apache.commons.httpclient.params.HttpMethodParams; + +/** + *

+ * HttpMethod interface represents a request to be sent via a + * {@link HttpConnection HTTP connection} and a corresponding response. + *

+ * @author Remy Maucherat + * @author Rod Waldhoff + * @author Jeff Dever + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:35 $ + * + * @since 1.0 + */ +public interface HttpMethod { + + // ------------------------------------------- Property Setters and Getters + + /** + * Obtains the name of the HTTP method as used in the HTTP request line, + * for example "GET" or "POST". + * + * @return the name of this method + */ + String getName(); + + /** + * Gets the host configuration for this method. The configuration specifies + * the server, port, protocol, and proxy server via which this method will + * send its HTTP request. + * + * @deprecated no longer applicable + * + * @return the HostConfiguration or null if none is set + */ + HostConfiguration getHostConfiguration(); + + /** + * Sets the path of the HTTP method. + * It is responsibility of the caller to ensure that the path is + * properly encoded (URL safe). + * + * @param path The path of the HTTP method. The path is expected + * to be URL encoded. + */ + void setPath(String path); + + /** + * Returns the path of the HTTP method. + * + * Calling this method after the request has been executed will + * return the actual path, following any redirects automatically + * handled by this HTTP method. + * + * @return the path of the HTTP method, in URL encoded form + */ + String getPath(); + + /** + * Returns the URI for this method. The URI will be absolute if the host + * configuration has been set and relative otherwise. + * + * @return the URI for this method + * + * @throws URIException if a URI cannot be constructed + */ + URI getURI() throws URIException; + + /** + * Sets the URI for this method. + * + * @param uri URI to be set + * + * @throws URIException if a URI cannot be set + * + * @since 3.0 + */ + void setURI(URI uri) throws URIException; + + /** + * Defines how strictly the method follows the HTTP protocol specification. + * (See RFC 2616 and other relevant RFCs.) In the strict mode the method precisely + * implements the requirements of the specification, whereas in non-strict mode + * it attempts to mimic the exact behaviour of commonly used HTTP agents, + * which many HTTP servers expect. + * + * @param strictMode true for strict mode, false otherwise + * + * @deprecated Use {@link org.apache.commons.httpclient.params.HttpParams#setParameter(String, Object)} + * to exercise a more granular control over HTTP protocol strictness. + * + * @see #isStrictMode() + */ + void setStrictMode(boolean strictMode); + + /** + * Returns the value of the strict mode flag. + * + * @return true if strict mode is enabled, false otherwise + * + * @deprecated Use {@link org.apache.commons.httpclient.params.HttpParams#setParameter(String, Object)} + * to exercise a more granular control over HTTP protocol strictness. + * + * @see #setStrictMode(boolean) + */ + boolean isStrictMode(); + + /** + * Sets the specified request header, overwriting any + * previous value. + * Note that header-name matching is case insensitive. + * @param headerName the header's name + * @param headerValue the header's value + * + * @see #setRequestHeader(Header) + * @see #getRequestHeader(String) + * @see #removeRequestHeader(String) + */ + void setRequestHeader(String headerName, String headerValue); + + /** + * Sets the specified request header, overwriting any + * previous value. + * Note that header-name matching is case insensitive. + * @param header the header to be set + * + * @see #setRequestHeader(String,String) + * @see #getRequestHeader(String) + * @see #removeRequestHeader(String) + */ + void setRequestHeader(Header header); + + /** + * Adds the specified request header, not overwriting any previous value. + * If the same header is added multiple times, perhaps with different values, + * multiple instances of that header will be sent in the HTTP request. + * Note that header-name matching is case insensitive. + * @param headerName the header's name + * @param headerValue the header's value + * + * @see #addRequestHeader(Header) + * @see #getRequestHeader(String) + * @see #removeRequestHeader(String) + */ + void addRequestHeader(String headerName, String headerValue); + + /** + * Adds the specified request header, not overwriting any previous value. + * If the same header is added multiple times, perhaps with different values, + * multiple instances of that header will be sent in the HTTP request. + * Note that header-name matching is case insensitive. + * @param header the header + * + * @see #addRequestHeader(String,String) + * @see #getRequestHeader(String) + * @see #removeRequestHeader(String) + */ + void addRequestHeader(Header header); + + /** + * Gets the request header with the given name. + * If there are multiple headers with the same name, + * there values will be combined with the ',' separator as specified by RFC2616. + * Note that header-name matching is case insensitive. + * @param headerName the header name + * @return the header + */ + Header getRequestHeader(String headerName); + + /** + * Removes all request headers with the given name. + * Note that header-name matching is case insensitive. + * @param headerName the header name + */ + void removeRequestHeader(String headerName); + + /** + * Removes the given request header. + * + * @param header the header + * + * @since 3.0 + */ + void removeRequestHeader(Header header); + + /** + * Returns true if the HTTP method should automatically follow HTTP redirects + * (status code 302, etc.), false otherwise. + * + * @return true if the method will automatically follow HTTP redirects, + * false otherwise + */ + boolean getFollowRedirects(); + + /** + * Sets whether or not the HTTP method should automatically follow HTTP redirects + * (status code 302, etc.) + * + * @param followRedirects true if the method will automatically follow redirects, + * false otherwise. + */ + void setFollowRedirects(boolean followRedirects); + + /** + * Sets the query string of the HTTP method. + * It is responsibility of the caller to ensure that the path is + * properly encoded (URL safe). The string must not include an initial '?' character. + * + * @param queryString the query to be used in the request, with no leading '?' character + * + * @see #getQueryString() + * @see #setQueryString(NameValuePair[]) + */ + void setQueryString(String queryString); + + /** + * Sets the query string of this HTTP method. The pairs are encoded as UTF-8 characters. + * To use a different charset the parameters can be encoded manually using EncodingUtil + * and set as a single String. + * + * @param params An array of NameValuePairs to use as the query string. + * The name/value pairs will be automatically URL encoded and should not + * have been encoded previously. + * + * @see #getQueryString() + * @see #setQueryString(String) + * @see org.apache.commons.httpclient.util.EncodingUtil#formUrlEncode(NameValuePair[], String) + */ + void setQueryString(NameValuePair[] params); + + /** + * Returns the query string of this HTTP method. + * + * @return the query string in URL encoded form, without a leading '?'. + * + * @see #setQueryString(NameValuePair[]) + * @see #setQueryString(String) + */ + String getQueryString(); + + /** + * Returns the current request headers for this HTTP method. The returned headers + * will be in the same order that they were added with addRequestHeader. + * If there are multiple request headers with the same name (e.g. Cookie), + * they will be returned as multiple entries in the array. + * + * @return an array containing all of the request headers + * + * @see #addRequestHeader(Header) + * @see #addRequestHeader(String,String) + */ + Header[] getRequestHeaders(); + + /** + * Returns the request headers with the given name. Note that header-name matching is + * case insensitive. + * @param headerName the name of the headers to be returned. + * @return an array of zero or more headers + * + * @since 3.0 + */ + Header[] getRequestHeaders(String headerName); + + // ---------------------------------------------------------------- Queries + + /** + * Returns true the method is ready to execute, false otherwise. + * + * @return true if the method is ready to execute, false otherwise. + */ + boolean validate(); + + /** + * Returns the status code associated with the latest response. + * + * @return The status code from the most recent execution of this method. + * If the method has not yet been executed, the result is undefined. + */ + int getStatusCode(); + + /** + * Returns the status text (or "reason phrase") associated with the latest + * response. + * + * @return The status text from the most recent execution of this method. + * If the method has not yet been executed, the result is undefined. + */ + String getStatusText(); + + /** + * Returns the response headers from the most recent execution of this request. + * + * @return A newly-created array containing all of the response headers, + * in the order in which they appeared in the response. + */ + Header[] getResponseHeaders(); + + /** + * Returns the specified response header. Note that header-name matching is + * case insensitive. + * + * @param headerName The name of the header to be returned. + * + * @return The specified response header. If the repsonse contained multiple + * instances of the header, its values will be combined using the ',' + * separator as specified by RFC2616. + */ + Header getResponseHeader(String headerName); + + /** + * Returns the response headers with the given name. Note that header-name matching is + * case insensitive. + * @param headerName the name of the headers to be returned. + * @return an array of zero or more headers + * + * @since 3.0 + */ + Header[] getResponseHeaders(String headerName); + + /** + * Returns the response footers from the most recent execution of this request. + * + * @return an array containing the response footers in the order that they + * appeared in the response. If the response had no footers, + * an empty array will be returned. + */ + Header[] getResponseFooters(); + + /** + * Return the specified response footer. Note that footer-name matching is + * case insensitive. + * + * @param footerName The name of the footer. + * @return The response footer. + */ + Header getResponseFooter(String footerName); + + /** + * Returns the response body of the HTTP method, if any, as an array of bytes. + * If the method has not yet been executed or the response has no body, null + * is returned. Note that this method does not propagate I/O exceptions. + * If an error occurs while reading the body, null will be returned. + * + * @return The response body, or null if the + * body is not available. + * + * @throws IOException if an I/O (transport) problem occurs + */ + byte[] getResponseBody() throws IOException; + + /** + * Returns the response body of the HTTP method, if any, as a {@link String}. + * If response body is not available or cannot be read, null is returned. + * The raw bytes in the body are converted to a String using the + * character encoding specified in the response's Content-Type header, or + * ISO-8859-1 if the response did not specify a character set. + *

+ * Note that this method does not propagate I/O exceptions. + * If an error occurs while reading the body, null will be returned. + * + * @return The response body converted to a String, or null + * if the body is not available. + * + * @throws IOException if an I/O (transport) problem occurs + */ + String getResponseBodyAsString() throws IOException; + + /** + * Returns the response body of the HTTP method, if any, as an InputStream. + * If the response had no body or the method has not yet been executed, + * null is returned. Additionally, null may be returned + * if {@link #releaseConnection} has been called or + * if this method was called previously and the resulting stream was closed. + * + * @return The response body, or null if it is not available + * + * @throws IOException if an I/O (transport) problem occurs + */ + InputStream getResponseBodyAsStream() throws IOException; + + /** + * Returns true if the HTTP method has been already {@link #execute executed}, + * but not {@link #recycle recycled}. + * + * @return true if the method has been executed, false otherwise + */ + boolean hasBeenUsed(); + + // --------------------------------------------------------- Action Methods + + /** + * Executes this method using the specified HttpConnection and + * HttpState. + * + * @param state the {@link HttpState state} information to associate with this method + * @param connection the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException If an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException If a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @return the integer status code if one was obtained, or -1 + */ + int execute(HttpState state, HttpConnection connection) + throws HttpException, IOException; + + /** + * Aborts the execution of the HTTP method. + * + * @see #execute(HttpState, HttpConnection) + * + * @since 3.0 + */ + void abort(); + + /** + * Recycles the HTTP method so that it can be used again. + * Note that all of the instance variables will be reset + * once this method has been called. This method will also + * release the connection being used by this HTTP method. + * + * @see #releaseConnection() + * + * @deprecated no longer supported and will be removed in the future + * version of HttpClient + */ + void recycle(); + + /** + * Releases the connection being used by this HTTP method. In particular the + * connection is used to read the response (if there is one) and will be held + * until the response has been read. If the connection can be reused by other + * HTTP methods it is NOT closed at this point. + *

+ * After this method is called, {@link #getResponseBodyAsStream} will return + * null, and {@link #getResponseBody} and {@link #getResponseBodyAsString} + * may return null. + */ + void releaseConnection(); + + /** + * Add a footer to this method's response. + *

+ * Note: This method is for + * internal use only and should not be called by external clients. + * + * @param footer the footer to add + * + * @since 2.0 + */ + void addResponseFooter(Header footer); + + /** + * Returns the Status-Line from the most recent response for this method, + * or null if the method has not been executed. + * + * @return the status line, or null if the method has not been executed + * + * @since 2.0 + */ + StatusLine getStatusLine(); + + /** + * Returns true if the HTTP method should automatically handle HTTP + * authentication challenges (status code 401, etc.), false otherwise + * + * @return true if authentication challenges will be processed + * automatically, false otherwise. + * + * @since 2.0 + * + * @see #setDoAuthentication(boolean) + */ + boolean getDoAuthentication(); + + /** + * Sets whether or not the HTTP method should automatically handle HTTP + * authentication challenges (status code 401, etc.) + * + * @param doAuthentication true to process authentication challenges + * automatically, false otherwise. + * + * @since 2.0 + * + * @see #getDoAuthentication() + */ + void setDoAuthentication(boolean doAuthentication); + + + /** + * Returns {@link HttpMethodParams HTTP protocol parameters} associated with this method. + * + * @since 3.0 + * + * @see HttpMethodParams + */ + public HttpMethodParams getParams(); + + /** + * Assigns {@link HttpMethodParams HTTP protocol parameters} for this method. + * + * @since 3.0 + * + * @see HttpMethodParams + */ + public void setParams(final HttpMethodParams params); + + /** + * Returns the target host {@link AuthState authentication state} + * + * @return host authentication state + * + * @since 3.0 + */ + public AuthState getHostAuthState(); + + /** + * Returns the proxy {@link AuthState authentication state} + * + * @return host authentication state + * + * @since 3.0 + */ + public AuthState getProxyAuthState(); + + /** + * Returns true if the HTTP has been transmitted to the target + * server in its entirety, false otherwise. This flag can be useful + * for recovery logic. If the request has not been transmitted in its entirety, + * it is safe to retry the failed method. + * + * @return true if the request has been sent, false otherwise + */ + boolean isRequestSent(); + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodBase.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodBase.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,2413 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodBase.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.util.Collection; + +import org.apache.commons.httpclient.auth.AuthState; +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.httpclient.cookie.CookieSpec; +import org.apache.commons.httpclient.cookie.MalformedCookieException; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.httpclient.util.ExceptionUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * An abstract base implementation of HttpMethod. + *

+ * At minimum, subclasses will need to override: + *

    + *
  • {@link #getName} to return the approriate name for this method + *
  • + *
+ *

+ * + *

+ * When a method requires additional request headers, subclasses will typically + * want to override: + *

    + *
  • {@link #addRequestHeaders addRequestHeaders(HttpState,HttpConnection)} + * to write those headers + *
  • + *
+ *

+ * + *

+ * When a method expects specific response headers, subclasses may want to + * override: + *

    + *
  • {@link #processResponseHeaders processResponseHeaders(HttpState,HttpConnection)} + * to handle those headers + *
  • + *
+ *

+ * + * + * @author Remy Maucherat + * @author Rodney Waldhoff + * @author Sean C. Sullivan + * @author dIon Gillard + * @author Jeff Dever + * @author Davanum Srinivas + * @author Ortwin Glueck + * @author Eric Johnson + * @author Michael Becke + * @author Oleg Kalnichevski + * @author Mike Bowler + * @author Gary Gregory + * @author Christian Kohlschuetter + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:35 $ + */ +public abstract class HttpMethodBase implements HttpMethod { + + // -------------------------------------------------------------- Constants + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpMethodBase.class); + + // ----------------------------------------------------- Instance variables + + /** Request headers, if any. */ + private HeaderGroup requestHeaders = new HeaderGroup(); + + /** The Status-Line from the response. */ + private StatusLine statusLine = null; + + /** Response headers, if any. */ + private HeaderGroup responseHeaders = new HeaderGroup(); + + /** Response trailer headers, if any. */ + private HeaderGroup responseTrailerHeaders = new HeaderGroup(); + + /** Path of the HTTP method. */ + private String path = null; + + /** Query string of the HTTP method, if any. */ + private String queryString = null; + + /** The response body of the HTTP method, assuming it has not be + * intercepted by a sub-class. */ + private InputStream responseStream = null; + + /** The connection that the response stream was read from. */ + private HttpConnection responseConnection = null; + + /** Buffer for the response */ + private byte[] responseBody = null; + + /** True if the HTTP method should automatically follow HTTP redirects.*/ + private boolean followRedirects = false; + + /** True if the HTTP method should automatically handle + * HTTP authentication challenges. */ + private boolean doAuthentication = true; + + /** HTTP protocol parameters. */ + private HttpMethodParams params = new HttpMethodParams(); + + /** Host authentication state */ + private AuthState hostAuthState = new AuthState(); + + /** Proxy authentication state */ + private AuthState proxyAuthState = new AuthState(); + + /** True if this method has already been executed. */ + private boolean used = false; + + /** Count of how many times did this HTTP method transparently handle + * a recoverable exception. */ + private int recoverableExceptionCount = 0; + + /** the host for this HTTP method, can be null */ + private HttpHost httphost = null; + + /** + * Handles method retries + * + * @deprecated no loner used + */ + private MethodRetryHandler methodRetryHandler; + + /** True if the connection must be closed when no longer needed */ + private boolean connectionCloseForced = false; + + /** Number of milliseconds to wait for 100-contunue response. */ + private static final int RESPONSE_WAIT_TIME_MS = 3000; + + /** HTTP protocol version used for execution of this method. */ + private HttpVersion effectiveVersion = null; + + /** Whether the execution of this method has been aborted */ + private transient boolean aborted = false; + + /** Whether the HTTP request has been transmitted to the target + * server it its entirety */ + private boolean requestSent = false; + + /** Actual cookie policy */ + private CookieSpec cookiespec = null; + + /** Default initial size of the response buffer if content length is unknown. */ + private static final int DEFAULT_INITIAL_BUFFER_SIZE = 4*1024; // 4 kB + + // ----------------------------------------------------------- Constructors + + /** + * No-arg constructor. + */ + public HttpMethodBase() { + } + + /** + * Constructor specifying a URI. + * It is responsibility of the caller to ensure that URI elements + * (path & query parameters) are properly encoded (URL safe). + * + * @param uri either an absolute or relative URI. The URI is expected + * to be URL-encoded + * + * @throws IllegalArgumentException when URI is invalid + * @throws IllegalStateException when protocol of the absolute URI is not recognised + */ + public HttpMethodBase(String uri) + throws IllegalArgumentException, IllegalStateException { + + try { + + // create a URI and allow for null/empty uri values + if (uri == null || uri.equals("")) { + uri = "/"; + } + setURI(new URI(uri, true)); + } catch (URIException e) { + throw new IllegalArgumentException("Invalid uri '" + + uri + "': " + e.getMessage() + ); + } + } + + // ------------------------------------------- Property Setters and Getters + + /** + * Obtains the name of the HTTP method as used in the HTTP request line, + * for example "GET" or "POST". + * + * @return the name of this method + */ + public abstract String getName(); + + /** + * Returns the URI of the HTTP method + * + * @return The URI + * + * @throws URIException If the URI cannot be created. + * + * @see org.apache.commons.httpclient.HttpMethod#getURI() + */ + public URI getURI() throws URIException { + StringBuffer buffer = new StringBuffer(); + if (this.httphost != null) { + buffer.append(this.httphost.getProtocol().getScheme()); + buffer.append("://"); + buffer.append(this.httphost.getHostName()); + int port = this.httphost.getPort(); + if (port != -1 && port != this.httphost.getProtocol().getDefaultPort()) { + buffer.append(":"); + buffer.append(port); + } + } + buffer.append(this.path); + if (this.queryString != null) { + buffer.append('?'); + buffer.append(this.queryString); + } + return new URI(buffer.toString(), true); + } + + /** + * Sets the URI for this method. + * + * @param uri URI to be set + * + * @throws URIException if a URI cannot be set + * + * @since 3.0 + */ + public void setURI(URI uri) throws URIException { + // only set the host if specified by the URI + if (uri.isAbsoluteURI()) { + this.httphost = new HttpHost(uri); + } + // set the path, defaulting to root + setPath( + uri.getPath() == null + ? "/" + : uri.getEscapedPath() + ); + setQueryString(uri.getEscapedQuery()); + } + + /** + * Sets whether or not the HTTP method should automatically follow HTTP redirects + * (status code 302, etc.) + * + * @param followRedirects true if the method will automatically follow redirects, + * false otherwise. + */ + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + } + + /** + * Returns true if the HTTP method should automatically follow HTTP redirects + * (status code 302, etc.), false otherwise. + * + * @return true if the method will automatically follow HTTP redirects, + * false otherwise. + */ + public boolean getFollowRedirects() { + return this.followRedirects; + } + + /** Sets whether version 1.1 of the HTTP protocol should be used per default. + * + * @param http11 true to use HTTP/1.1, false to use 1.0 + * + * @deprecated Use {@link HttpMethodParams#setVersion(HttpVersion)} + */ + public void setHttp11(boolean http11) { + if (http11) { + this.params.setVersion(HttpVersion.HTTP_1_1); + } else { + this.params.setVersion(HttpVersion.HTTP_1_0); + } + } + + /** + * Returns true if the HTTP method should automatically handle HTTP + * authentication challenges (status code 401, etc.), false otherwise + * + * @return true if authentication challenges will be processed + * automatically, false otherwise. + * + * @since 2.0 + */ + public boolean getDoAuthentication() { + return doAuthentication; + } + + /** + * Sets whether or not the HTTP method should automatically handle HTTP + * authentication challenges (status code 401, etc.) + * + * @param doAuthentication true to process authentication challenges + * authomatically, false otherwise. + * + * @since 2.0 + */ + public void setDoAuthentication(boolean doAuthentication) { + this.doAuthentication = doAuthentication; + } + + // ---------------------------------------------- Protected Utility Methods + + /** + * Returns true if version 1.1 of the HTTP protocol should be + * used per default, false if version 1.0 should be used. + * + * @return true to use HTTP/1.1, false to use 1.0 + * + * @deprecated Use {@link HttpMethodParams#getVersion()} + */ + public boolean isHttp11() { + return this.params.getVersion().equals(HttpVersion.HTTP_1_1); + } + + /** + * Sets the path of the HTTP method. + * It is responsibility of the caller to ensure that the path is + * properly encoded (URL safe). + * + * @param path the path of the HTTP method. The path is expected + * to be URL-encoded + */ + public void setPath(String path) { + this.path = path; + } + + /** + * Adds the specified request header, NOT overwriting any previous value. + * Note that header-name matching is case insensitive. + * + * @param header the header to add to the request + */ + public void addRequestHeader(Header header) { + LOG.trace("HttpMethodBase.addRequestHeader(Header)"); + + if (header == null) { + LOG.debug("null header value ignored"); + } else { + getRequestHeaderGroup().addHeader(header); + } + } + + /** + * Use this method internally to add footers. + * + * @param footer The footer to add. + */ + public void addResponseFooter(Header footer) { + getResponseTrailerHeaderGroup().addHeader(footer); + } + + /** + * Gets the path of this HTTP method. + * Calling this method after the request has been executed will + * return the actual path, following any redirects automatically + * handled by this HTTP method. + * + * @return the path to request or "/" if the path is blank. + */ + public String getPath() { + return (path == null || path.equals("")) ? "/" : path; + } + + /** + * Sets the query string of this HTTP method. The caller must ensure that the string + * is properly URL encoded. The query string should not start with the question + * mark character. + * + * @param queryString the query string + * + * @see EncodingUtil#formUrlEncode(NameValuePair[], String) + */ + public void setQueryString(String queryString) { + this.queryString = queryString; + } + + /** + * Sets the query string of this HTTP method. The pairs are encoded as UTF-8 characters. + * To use a different charset the parameters can be encoded manually using EncodingUtil + * and set as a single String. + * + * @param params an array of {@link NameValuePair}s to add as query string + * parameters. The name/value pairs will be automcatically + * URL encoded + * + * @see EncodingUtil#formUrlEncode(NameValuePair[], String) + * @see #setQueryString(String) + */ + public void setQueryString(NameValuePair[] params) { + LOG.trace("enter HttpMethodBase.setQueryString(NameValuePair[])"); + queryString = EncodingUtil.formUrlEncode(params, "UTF-8"); + } + + /** + * Gets the query string of this HTTP method. + * + * @return The query string + */ + public String getQueryString() { + return queryString; + } + + /** + * Set the specified request header, overwriting any previous value. Note + * that header-name matching is case-insensitive. + * + * @param headerName the header's name + * @param headerValue the header's value + */ + public void setRequestHeader(String headerName, String headerValue) { + Header header = new Header(headerName, headerValue); + setRequestHeader(header); + } + + /** + * Sets the specified request header, overwriting any previous value. + * Note that header-name matching is case insensitive. + * + * @param header the header + */ + public void setRequestHeader(Header header) { + + Header[] headers = getRequestHeaderGroup().getHeaders(header.getName()); + + for (int i = 0; i < headers.length; i++) { + getRequestHeaderGroup().removeHeader(headers[i]); + } + + getRequestHeaderGroup().addHeader(header); + + } + + /** + * Returns the specified request header. Note that header-name matching is + * case insensitive. null will be returned if either + * headerName is null or there is no matching header for + * headerName. + * + * @param headerName The name of the header to be returned. + * + * @return The specified request header. + * + * @since 3.0 + */ + public Header getRequestHeader(String headerName) { + if (headerName == null) { + return null; + } else { + return getRequestHeaderGroup().getCondensedHeader(headerName); + } + } + + /** + * Returns an array of the requests headers that the HTTP method currently has + * + * @return an array of my request headers. + */ + public Header[] getRequestHeaders() { + return getRequestHeaderGroup().getAllHeaders(); + } + + /** + * @see org.apache.commons.httpclient.HttpMethod#getRequestHeaders(java.lang.String) + */ + public Header[] getRequestHeaders(String headerName) { + return getRequestHeaderGroup().getHeaders(headerName); + } + + /** + * Gets the {@link HeaderGroup header group} storing the request headers. + * + * @return a HeaderGroup + * + * @since 2.0beta1 + */ + protected HeaderGroup getRequestHeaderGroup() { + return requestHeaders; + } + + /** + * Gets the {@link HeaderGroup header group} storing the response trailer headers + * as per RFC 2616 section 3.6.1. + * + * @return a HeaderGroup + * + * @since 2.0beta1 + */ + protected HeaderGroup getResponseTrailerHeaderGroup() { + return responseTrailerHeaders; + } + + /** + * Gets the {@link HeaderGroup header group} storing the response headers. + * + * @return a HeaderGroup + * + * @since 2.0beta1 + */ + protected HeaderGroup getResponseHeaderGroup() { + return responseHeaders; + } + + /** + * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders(java.lang.String) + * + * @since 3.0 + */ + public Header[] getResponseHeaders(String headerName) { + return getResponseHeaderGroup().getHeaders(headerName); + } + + /** + * Returns the response status code. + * + * @return the status code associated with the latest response. + */ + public int getStatusCode() { + return statusLine.getStatusCode(); + } + + /** + * Provides access to the response status line. + * + * @return the status line object from the latest response. + * @since 2.0 + */ + public StatusLine getStatusLine() { + return statusLine; + } + + /** + * Checks if response data is available. + * @return true if response data is available, false otherwise. + */ + private boolean responseAvailable() { + return (responseBody != null) || (responseStream != null); + } + + /** + * Returns an array of the response headers that the HTTP method currently has + * in the order in which they were read. + * + * @return an array of response headers. + */ + public Header[] getResponseHeaders() { + return getResponseHeaderGroup().getAllHeaders(); + } + + /** + * Gets the response header associated with the given name. Header name + * matching is case insensitive. null will be returned if either + * headerName is null or there is no matching header for + * headerName. + * + * @param headerName the header name to match + * + * @return the matching header + */ + public Header getResponseHeader(String headerName) { + if (headerName == null) { + return null; + } else { + return getResponseHeaderGroup().getCondensedHeader(headerName); + } + } + + + /** + * Return the length (in bytes) of the response body, as specified in a + * Content-Length header. + * + *

+ * Return -1 when the content-length is unknown. + *

+ * + * @return content length, if Content-Length header is available. + * 0 indicates that the request has no body. + * If Content-Length header is not present, the method + * returns -1. + */ + public long getResponseContentLength() { + Header[] headers = getResponseHeaderGroup().getHeaders("Content-Length"); + if (headers.length == 0) { + return -1; + } + if (headers.length > 1) { + LOG.warn("Multiple content-length headers detected"); + } + for (int i = headers.length - 1; i >= 0; i--) { + Header header = headers[i]; + try { + return Long.parseLong(header.getValue()); + } catch (NumberFormatException e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Invalid content-length value: " + e.getMessage()); + } + } + // See if we can have better luck with another header, if present + } + return -1; + } + + + /** + * Returns the response body of the HTTP method, if any, as an array of bytes. + * If response body is not available or cannot be read, returns null + * + * Note: This will cause the entire response body to be buffered in memory. A + * malicious server may easily exhaust all the VM memory. It is strongly + * recommended, to use getResponseAsStream if the content length of the response + * is unknown or resonably large. + * + * @return The response body. + * + * @throws IOException If an I/O (transport) problem occurs while obtaining the + * response body. + */ + public byte[] getResponseBody() throws IOException { + if (this.responseBody == null) { + InputStream instream = getResponseBodyAsStream(); + if (instream != null) { + long contentLength = getResponseContentLength(); + if (contentLength > Integer.MAX_VALUE) { //guard below cast from overflow + throw new IOException("Content too large to be buffered: "+ contentLength +" bytes"); + } + int limit = getParams().getIntParameter(HttpMethodParams.BUFFER_WARN_TRIGGER_LIMIT, 1024*1024); + if ((contentLength == -1) || (contentLength > limit)) { + LOG.warn("Going to buffer response body of large or unknown size. " + +"Using getResponseBodyAsStream instead is recommended."); + } + LOG.debug("Buffering response body"); + ByteArrayOutputStream outstream = new ByteArrayOutputStream( + contentLength > 0 ? (int) contentLength : DEFAULT_INITIAL_BUFFER_SIZE); + byte[] buffer = new byte[4096]; + int len; + while ((len = instream.read(buffer)) > 0) { + outstream.write(buffer, 0, len); + } + outstream.close(); + setResponseStream(null); + this.responseBody = outstream.toByteArray(); + } + } + return this.responseBody; + } + + /** + * Returns the response body of the HTTP method, if any, as an {@link InputStream}. + * If response body is not available, returns null + * + * @return The response body + * + * @throws IOException If an I/O (transport) problem occurs while obtaining the + * response body. + */ + public InputStream getResponseBodyAsStream() throws IOException { + if (responseStream != null) { + return responseStream; + } + if (responseBody != null) { + InputStream byteResponseStream = new ByteArrayInputStream(responseBody); + LOG.debug("re-creating response stream from byte array"); + return byteResponseStream; + } + return null; + } + + /** + * Returns the response body of the HTTP method, if any, as a {@link String}. + * If response body is not available or cannot be read, returns null + * The string conversion on the data is done using the character encoding specified + * in Content-Type header. + * + * Note: This will cause the entire response body to be buffered in memory. A + * malicious server may easily exhaust all the VM memory. It is strongly + * recommended, to use getResponseAsStream if the content length of the response + * is unknown or resonably large. + * + * @return The response body. + * + * @throws IOException If an I/O (transport) problem occurs while obtaining the + * response body. + */ + public String getResponseBodyAsString() throws IOException { + byte[] rawdata = null; + if (responseAvailable()) { + rawdata = getResponseBody(); + } + if (rawdata != null) { + return EncodingUtil.getString(rawdata, getResponseCharSet()); + } else { + return null; + } + } + + /** + * Returns an array of the response footers that the HTTP method currently has + * in the order in which they were read. + * + * @return an array of footers + */ + public Header[] getResponseFooters() { + return getResponseTrailerHeaderGroup().getAllHeaders(); + } + + /** + * Gets the response footer associated with the given name. + * Footer name matching is case insensitive. + * null will be returned if either footerName is + * null or there is no matching footer for footerName + * or there are no footers available. If there are multiple footers + * with the same name, there values will be combined with the ',' separator + * as specified by RFC2616. + * + * @param footerName the footer name to match + * @return the matching footer + */ + public Header getResponseFooter(String footerName) { + if (footerName == null) { + return null; + } else { + return getResponseTrailerHeaderGroup().getCondensedHeader(footerName); + } + } + + /** + * Sets the response stream. + * @param responseStream The new response stream. + */ + protected void setResponseStream(InputStream responseStream) { + this.responseStream = responseStream; + } + + /** + * Returns a stream from which the body of the current response may be read. + * If the method has not yet been executed, if responseBodyConsumed + * has been called, or if the stream returned by a previous call has been closed, + * null will be returned. + * + * @return the current response stream + */ + protected InputStream getResponseStream() { + return responseStream; + } + + /** + * Returns the status text (or "reason phrase") associated with the latest + * response. + * + * @return The status text. + */ + public String getStatusText() { + return statusLine.getReasonPhrase(); + } + + /** + * Defines how strictly HttpClient follows the HTTP protocol specification + * (RFC 2616 and other relevant RFCs). In the strict mode HttpClient precisely + * implements the requirements of the specification, whereas in non-strict mode + * it attempts to mimic the exact behaviour of commonly used HTTP agents, + * which many HTTP servers expect. + * + * @param strictMode true for strict mode, false otherwise + * + * @deprecated Use {@link org.apache.commons.httpclient.params.HttpParams#setParameter(String, Object)} + * to exercise a more granular control over HTTP protocol strictness. + */ + public void setStrictMode(boolean strictMode) { + if (strictMode) { + this.params.makeStrict(); + } else { + this.params.makeLenient(); + } + } + + /** + * @deprecated Use {@link org.apache.commons.httpclient.params.HttpParams#setParameter(String, Object)} + * to exercise a more granular control over HTTP protocol strictness. + * + * @return false + */ + public boolean isStrictMode() { + return false; + } + + /** + * Adds the specified request header, NOT overwriting any previous value. + * Note that header-name matching is case insensitive. + * + * @param headerName the header's name + * @param headerValue the header's value + */ + public void addRequestHeader(String headerName, String headerValue) { + addRequestHeader(new Header(headerName, headerValue)); + } + + /** + * Tests if the connection should be force-closed when no longer needed. + * + * @return true if the connection must be closed + */ + protected boolean isConnectionCloseForced() { + return this.connectionCloseForced; + } + + /** + * Sets whether or not the connection should be force-closed when no longer + * needed. This value should only be set to true in abnormal + * circumstances, such as HTTP protocol violations. + * + * @param b true if the connection must be closed, false + * otherwise. + */ + protected void setConnectionCloseForced(boolean b) { + if (LOG.isDebugEnabled()) { + LOG.debug("Force-close connection: " + b); + } + this.connectionCloseForced = b; + } + + /** + * Tests if the connection should be closed after the method has been executed. + * The connection will be left open when using HTTP/1.1 or if Connection: + * keep-alive header was sent. + * + * @param conn the connection in question + * + * @return boolean true if we should close the connection. + */ + protected boolean shouldCloseConnection(HttpConnection conn) { + // Connection must be closed due to an abnormal circumstance + if (isConnectionCloseForced()) { + LOG.debug("Should force-close connection."); + return true; + } + + Header connectionHeader = null; + // In case being connected via a proxy server + if (!conn.isTransparent()) { + // Check for 'proxy-connection' directive + connectionHeader = responseHeaders.getFirstHeader("proxy-connection"); + } + // In all cases Check for 'connection' directive + // some non-complaint proxy servers send it instread of + // expected 'proxy-connection' directive + if (connectionHeader == null) { + connectionHeader = responseHeaders.getFirstHeader("connection"); + } + // In case the response does not contain any explict connection + // directives, check whether the request does + if (connectionHeader == null) { + connectionHeader = requestHeaders.getFirstHeader("connection"); + } + if (connectionHeader != null) { + if (connectionHeader.getValue().equalsIgnoreCase("close")) { + if (LOG.isDebugEnabled()) { + LOG.debug("Should close connection in response to directive: " + + connectionHeader.getValue()); + } + return true; + } else if (connectionHeader.getValue().equalsIgnoreCase("keep-alive")) { + if (LOG.isDebugEnabled()) { + LOG.debug("Should NOT close connection in response to directive: " + + connectionHeader.getValue()); + } + return false; + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Unknown directive: " + connectionHeader.toExternalForm()); + } + } + } + LOG.debug("Resorting to protocol version default close connection policy"); + // missing or invalid connection header, do the default + if (this.effectiveVersion.greaterEquals(HttpVersion.HTTP_1_1)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Should NOT close connection, using " + this.effectiveVersion.toString()); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Should close connection, using " + this.effectiveVersion.toString()); + } + } + return this.effectiveVersion.lessEquals(HttpVersion.HTTP_1_0); + } + + /** + * Tests if the this method is ready to be executed. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} to be used + * @throws HttpException If the method is in invalid state. + */ + private void checkExecuteConditions(HttpState state, HttpConnection conn) + throws HttpException { + + if (state == null) { + throw new IllegalArgumentException("HttpState parameter may not be null"); + } + if (conn == null) { + throw new IllegalArgumentException("HttpConnection parameter may not be null"); + } + if (this.aborted) { + throw new IllegalStateException("Method has been aborted"); + } + if (!validate()) { + throw new ProtocolException("HttpMethodBase object not valid"); + } + } + + /** + * Executes this method using the specified HttpConnection and + * HttpState. + * + * @param state {@link HttpState state} information to associate with this + * request. Must be non-null. + * @param conn the {@link HttpConnection connection} to used to execute + * this HTTP method. Must be non-null. + * + * @return the integer status code if one was obtained, or -1 + * + * @throws IOException if an I/O (transport) error occurs + * @throws HttpException if a protocol exception occurs. + */ + public int execute(HttpState state, HttpConnection conn) + throws HttpException, IOException { + + LOG.trace("enter HttpMethodBase.execute(HttpState, HttpConnection)"); + + // this is our connection now, assign it to a local variable so + // that it can be released later + this.responseConnection = conn; + + checkExecuteConditions(state, conn); + this.statusLine = null; + this.connectionCloseForced = false; + + conn.setLastResponseInputStream(null); + + // determine the effective protocol version + if (this.effectiveVersion == null) { + this.effectiveVersion = this.params.getVersion(); + } + + writeRequest(state, conn); + this.requestSent = true; + readResponse(state, conn); + // the method has successfully executed + used = true; + + return statusLine.getStatusCode(); + } + + /** + * Aborts the execution of this method. + * + * @since 3.0 + */ + public void abort() { + if (this.aborted) { + return; + } + this.aborted = true; + HttpConnection conn = this.responseConnection; + if (conn != null) { + conn.close(); + } + } + + /** + * Returns true if the HTTP method has been already {@link #execute executed}, + * but not {@link #recycle recycled}. + * + * @return true if the method has been executed, false otherwise + */ + public boolean hasBeenUsed() { + return used; + } + + /** + * Recycles the HTTP method so that it can be used again. + * Note that all of the instance variables will be reset + * once this method has been called. This method will also + * release the connection being used by this HTTP method. + * + * @see #releaseConnection() + * + * @deprecated no longer supported and will be removed in the future + * version of HttpClient + */ + public void recycle() { + LOG.trace("enter HttpMethodBase.recycle()"); + + releaseConnection(); + + path = null; + followRedirects = false; + doAuthentication = true; + queryString = null; + getRequestHeaderGroup().clear(); + getResponseHeaderGroup().clear(); + getResponseTrailerHeaderGroup().clear(); + statusLine = null; + effectiveVersion = null; + aborted = false; + used = false; + params = new HttpMethodParams(); + responseBody = null; + recoverableExceptionCount = 0; + connectionCloseForced = false; + hostAuthState.invalidate(); + proxyAuthState.invalidate(); + cookiespec = null; + requestSent = false; + } + + /** + * Releases the connection being used by this HTTP method. In particular the + * connection is used to read the response(if there is one) and will be held + * until the response has been read. If the connection can be reused by other + * HTTP methods it is NOT closed at this point. + * + * @since 2.0 + */ + public void releaseConnection() { + try { + if (this.responseStream != null) { + try { + // FYI - this may indirectly invoke responseBodyConsumed. + this.responseStream.close(); + } catch (IOException ignore) { + } + } + } finally { + ensureConnectionRelease(); + } + } + + /** + * Remove the request header associated with the given name. Note that + * header-name matching is case insensitive. + * + * @param headerName the header name + */ + public void removeRequestHeader(String headerName) { + + Header[] headers = getRequestHeaderGroup().getHeaders(headerName); + for (int i = 0; i < headers.length; i++) { + getRequestHeaderGroup().removeHeader(headers[i]); + } + + } + + /** + * Removes the given request header. + * + * @param header the header + */ + public void removeRequestHeader(final Header header) { + if (header == null) { + return; + } + getRequestHeaderGroup().removeHeader(header); + } + + // ---------------------------------------------------------------- Queries + + /** + * Returns true the method is ready to execute, false otherwise. + * + * @return This implementation always returns true. + */ + public boolean validate() { + return true; + } + + + /** + * Returns the actual cookie policy + * + * @param state HTTP state. TODO: to be removed in the future + * + * @return cookie spec + */ + private CookieSpec getCookieSpec(final HttpState state) { + if (this.cookiespec == null) { + int i = state.getCookiePolicy(); + if (i == -1) { + this.cookiespec = CookiePolicy.getCookieSpec(this.params.getCookiePolicy()); + } else { + this.cookiespec = CookiePolicy.getSpecByPolicy(i); + } + this.cookiespec.setValidDateFormats( + (Collection)this.params.getParameter(HttpMethodParams.DATE_PATTERNS)); + } + return this.cookiespec; + } + + /** + * Generates Cookie request headers for those {@link Cookie cookie}s + * that match the given host, port and path. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected void addCookieRequestHeader(HttpState state, HttpConnection conn) + throws IOException, HttpException { + + LOG.trace("enter HttpMethodBase.addCookieRequestHeader(HttpState, " + + "HttpConnection)"); + + Header[] cookieheaders = getRequestHeaderGroup().getHeaders("Cookie"); + for (int i = 0; i < cookieheaders.length; i++) { + Header cookieheader = cookieheaders[i]; + if (cookieheader.isAutogenerated()) { + getRequestHeaderGroup().removeHeader(cookieheader); + } + } + + CookieSpec matcher = getCookieSpec(state); + String host = this.params.getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + Cookie[] cookies = matcher.match(host, conn.getPort(), + getPath(), conn.isSecure(), state.getCookies()); + if ((cookies != null) && (cookies.length > 0)) { + if (getParams().isParameterTrue(HttpMethodParams.SINGLE_COOKIE_HEADER)) { + // In strict mode put all cookies on the same header + String s = matcher.formatCookies(cookies); + getRequestHeaderGroup().addHeader(new Header("Cookie", s, true)); + } else { + // In non-strict mode put each cookie on a separate header + for (int i = 0; i < cookies.length; i++) { + String s = matcher.formatCookie(cookies[i]); + getRequestHeaderGroup().addHeader(new Header("Cookie", s, true)); + } + } + } + } + + /** + * Generates Host request header, as long as no Host request + * header already exists. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected void addHostRequestHeader(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter HttpMethodBase.addHostRequestHeader(HttpState, " + + "HttpConnection)"); + + // Per 19.6.1.1 of RFC 2616, it is legal for HTTP/1.0 based + // applications to send the Host request-header. + // TODO: Add the ability to disable the sending of this header for + // HTTP/1.0 requests. + String host = this.params.getVirtualHost(); + if (host != null) { + LOG.debug("Using virtual host name: " + host); + } else { + host = conn.getHost(); + } + int port = conn.getPort(); + + // Note: RFC 2616 uses the term "internet host name" for what goes on the + // host line. It would seem to imply that host should be blank if the + // host is a number instead of an name. Based on the behavior of web + // browsers, and the fact that RFC 2616 never defines the phrase "internet + // host name", and the bad behavior of HttpClient that follows if we + // send blank, I interpret this as a small misstatement in the RFC, where + // they meant to say "internet host". So IP numbers get sent as host + // entries too. -- Eric Johnson 12/13/2002 + if (LOG.isDebugEnabled()) { + LOG.debug("Adding Host request header"); + } + + //appends the port only if not using the default port for the protocol + if (conn.getProtocol().getDefaultPort() != port) { + host += (":" + port); + } + + setRequestHeader("Host", host); + } + + /** + * Generates Proxy-Connection: Keep-Alive request header when + * communicating via a proxy server. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected void addProxyConnectionHeader(HttpState state, + HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter HttpMethodBase.addProxyConnectionHeader(" + + "HttpState, HttpConnection)"); + if (!conn.isTransparent()) { + if (getRequestHeader("Proxy-Connection") == null) { + addRequestHeader("Proxy-Connection", "Keep-Alive"); + } + } + } + + /** + * Generates all the required request {@link Header header}s + * to be submitted via the given {@link HttpConnection connection}. + * + *

+ * This implementation adds User-Agent, Host, + * Cookie, Authorization, Proxy-Authorization + * and Proxy-Connection headers, when appropriate. + *

+ * + *

+ * Subclasses may want to override this method to to add additional + * headers, and may choose to invoke this implementation (via + * super) to add the "standard" headers. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #writeRequestHeaders + */ + protected void addRequestHeaders(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter HttpMethodBase.addRequestHeaders(HttpState, " + + "HttpConnection)"); + + addUserAgentRequestHeader(state, conn); + addHostRequestHeader(state, conn); + addCookieRequestHeader(state, conn); + addProxyConnectionHeader(state, conn); + } + + /** + * Generates default User-Agent request header, as long as no + * User-Agent request header already exists. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected void addUserAgentRequestHeader(HttpState state, + HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter HttpMethodBase.addUserAgentRequestHeaders(HttpState, " + + "HttpConnection)"); + + if (getRequestHeader("User-Agent") == null) { + String agent = (String)getParams().getParameter(HttpMethodParams.USER_AGENT); + if (agent == null) { + agent = "Jakarta Commons-HttpClient"; + } + setRequestHeader("User-Agent", agent); + } + } + + /** + * Throws an {@link IllegalStateException} if the HTTP method has been already + * {@link #execute executed}, but not {@link #recycle recycled}. + * + * @throws IllegalStateException if the method has been used and not + * recycled + */ + protected void checkNotUsed() throws IllegalStateException { + if (used) { + throw new IllegalStateException("Already used."); + } + } + + /** + * Throws an {@link IllegalStateException} if the HTTP method has not been + * {@link #execute executed} since last {@link #recycle recycle}. + * + * + * @throws IllegalStateException if not used + */ + protected void checkUsed() throws IllegalStateException { + if (!used) { + throw new IllegalStateException("Not Used."); + } + } + + // ------------------------------------------------- Static Utility Methods + + /** + * Generates HTTP request line according to the specified attributes. + * + * @param connection the {@link HttpConnection connection} used to execute + * this HTTP method + * @param name the method name generate a request for + * @param requestPath the path string for the request + * @param query the query string for the request + * @param version the protocol version to use (e.g. HTTP/1.0) + * + * @return HTTP request line + */ + protected static String generateRequestLine(HttpConnection connection, + String name, String requestPath, String query, String version) { + LOG.trace("enter HttpMethodBase.generateRequestLine(HttpConnection, " + + "String, String, String, String)"); + + StringBuffer buf = new StringBuffer(); + // Append method name + buf.append(name); + buf.append(" "); + // Absolute or relative URL? + if (!connection.isTransparent()) { + Protocol protocol = connection.getProtocol(); + buf.append(protocol.getScheme().toLowerCase()); + buf.append("://"); + buf.append(connection.getHost()); + if ((connection.getPort() != -1) + && (connection.getPort() != protocol.getDefaultPort()) + ) { + buf.append(":"); + buf.append(connection.getPort()); + } + } + // Append path, if any + if (requestPath == null) { + buf.append("/"); + } else { + if (!connection.isTransparent() && !requestPath.startsWith("/")) { + buf.append("/"); + } + buf.append(requestPath); + } + // Append query, if any + if (query != null) { + if (query.indexOf("?") != 0) { + buf.append("?"); + } + buf.append(query); + } + // Append protocol + buf.append(" "); + buf.append(version); + buf.append("\r\n"); + + return buf.toString(); + } + + /** + * This method is invoked immediately after + * {@link #readResponseBody(HttpState,HttpConnection)} and can be overridden by + * sub-classes in order to provide custom body processing. + * + *

+ * This implementation does nothing. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @see #readResponse + * @see #readResponseBody + */ + protected void processResponseBody(HttpState state, HttpConnection conn) { + } + + /** + * This method is invoked immediately after + * {@link #readResponseHeaders(HttpState,HttpConnection)} and can be overridden by + * sub-classes in order to provide custom response headers processing. + + *

+ * This implementation will handle the Set-Cookie and + * Set-Cookie2 headers, if any, adding the relevant cookies to + * the given {@link HttpState}. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @see #readResponse + * @see #readResponseHeaders + */ + protected void processResponseHeaders(HttpState state, + HttpConnection conn) { + LOG.trace("enter HttpMethodBase.processResponseHeaders(HttpState, " + + "HttpConnection)"); + + Header[] headers = getResponseHeaderGroup().getHeaders("set-cookie2"); + //Only process old style set-cookie headers if new style headres + //are not present + if (headers.length == 0) { + headers = getResponseHeaderGroup().getHeaders("set-cookie"); + } + + CookieSpec parser = getCookieSpec(state); + String host = this.params.getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + for (int i = 0; i < headers.length; i++) { + Header header = headers[i]; + Cookie[] cookies = null; + try { + cookies = parser.parse( + host, + conn.getPort(), + getPath(), + conn.isSecure(), + header); + } catch (MalformedCookieException e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Invalid cookie header: \"" + + header.getValue() + + "\". " + e.getMessage()); + } + } + if (cookies != null) { + for (int j = 0; j < cookies.length; j++) { + Cookie cookie = cookies[j]; + try { + parser.validate( + host, + conn.getPort(), + getPath(), + conn.isSecure(), + cookie); + state.addCookie(cookie); + if (LOG.isDebugEnabled()) { + LOG.debug("Cookie accepted: \"" + + parser.formatCookie(cookie) + "\""); + } + } catch (MalformedCookieException e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Cookie rejected: \"" + parser.formatCookie(cookie) + + "\". " + e.getMessage()); + } + } + } + } + } + } + + /** + * This method is invoked immediately after + * {@link #readStatusLine(HttpState,HttpConnection)} and can be overridden by + * sub-classes in order to provide custom response status line processing. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @see #readResponse + * @see #readStatusLine + */ + protected void processStatusLine(HttpState state, HttpConnection conn) { + } + + /** + * Reads the response from the given {@link HttpConnection connection}. + * + *

+ * The response is processed as the following sequence of actions: + * + *

    + *
  1. + * {@link #readStatusLine(HttpState,HttpConnection)} is + * invoked to read the request line. + *
  2. + *
  3. + * {@link #processStatusLine(HttpState,HttpConnection)} + * is invoked, allowing the method to process the status line if + * desired. + *
  4. + *
  5. + * {@link #readResponseHeaders(HttpState,HttpConnection)} is invoked to read + * the associated headers. + *
  6. + *
  7. + * {@link #processResponseHeaders(HttpState,HttpConnection)} is invoked, allowing + * the method to process the headers if desired. + *
  8. + *
  9. + * {@link #readResponseBody(HttpState,HttpConnection)} is + * invoked to read the associated body (if any). + *
  10. + *
  11. + * {@link #processResponseBody(HttpState,HttpConnection)} is invoked, allowing the + * method to process the response body if desired. + *
  12. + *
+ * + * Subclasses may want to override one or more of the above methods to to + * customize the processing. (Or they may choose to override this method + * if dramatically different processing is required.) + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected void readResponse(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace( + "enter HttpMethodBase.readResponse(HttpState, HttpConnection)"); + // Status line & line may have already been received + // if 'expect - continue' handshake has been used + while (this.statusLine == null) { + readStatusLine(state, conn); + processStatusLine(state, conn); + readResponseHeaders(state, conn); + processResponseHeaders(state, conn); + + int status = this.statusLine.getStatusCode(); + if ((status >= 100) && (status < 200)) { + if (LOG.isInfoEnabled()) { + LOG.info("Discarding unexpected response: " + this.statusLine.toString()); + } + this.statusLine = null; + } + } + readResponseBody(state, conn); + processResponseBody(state, conn); + } + + /** + * Read the response body from the given {@link HttpConnection}. + * + *

+ * The current implementation wraps the socket level stream with + * an appropriate stream for the type of response (chunked, content-length, + * or auto-close). If there is no response body, the connection associated + * with the request will be returned to the connection manager. + *

+ * + *

+ * Subclasses may want to override this method to to customize the + * processing. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #readResponse + * @see #processResponseBody + */ + protected void readResponseBody(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace( + "enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)"); + + // assume we are not done with the connection if we get a stream + InputStream stream = readResponseBody(conn); + if (stream == null) { + // done using the connection! + responseBodyConsumed(); + } else { + conn.setLastResponseInputStream(stream); + setResponseStream(stream); + } + } + + /** + * Returns the response body as an {@link InputStream input stream} + * corresponding to the values of the Content-Length and + * Transfer-Encoding headers. If no response body is available + * returns null. + *

+ * + * @see #readResponse + * @see #processResponseBody + * + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + private InputStream readResponseBody(HttpConnection conn) + throws HttpException, IOException { + + LOG.trace("enter HttpMethodBase.readResponseBody(HttpConnection)"); + + responseBody = null; + InputStream is = conn.getResponseInputStream(); + if (Wire.CONTENT_WIRE.enabled()) { + is = new WireLogInputStream(is, Wire.CONTENT_WIRE); + } + boolean canHaveBody = canResponseHaveBody(statusLine.getStatusCode()); + InputStream result = null; + Header transferEncodingHeader = responseHeaders.getFirstHeader("Transfer-Encoding"); + // We use Transfer-Encoding if present and ignore Content-Length. + // RFC2616, 4.4 item number 3 + if (transferEncodingHeader != null) { + + String transferEncoding = transferEncodingHeader.getValue(); + if (!"chunked".equalsIgnoreCase(transferEncoding) + && !"identity".equalsIgnoreCase(transferEncoding)) { + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported transfer encoding: " + transferEncoding); + } + } + HeaderElement[] encodings = transferEncodingHeader.getElements(); + // The chunked encoding must be the last one applied + // RFC2616, 14.41 + int len = encodings.length; + if ((len > 0) && ("chunked".equalsIgnoreCase(encodings[len - 1].getName()))) { + // if response body is empty + if (conn.isResponseAvailable(conn.getParams().getSoTimeout())) { + result = new ChunkedInputStream(is, this); + } else { + if (getParams().isParameterTrue(HttpMethodParams.STRICT_TRANSFER_ENCODING)) { + throw new ProtocolException("Chunk-encoded body declared but not sent"); + } else { + LOG.warn("Chunk-encoded body missing"); + } + } + } else { + LOG.info("Response content is not chunk-encoded"); + // The connection must be terminated by closing + // the socket as per RFC 2616, 3.6 + setConnectionCloseForced(true); + result = is; + } + } else { + long expectedLength = getResponseContentLength(); + if (expectedLength == -1) { + if (canHaveBody && this.effectiveVersion.greaterEquals(HttpVersion.HTTP_1_1)) { + Header connectionHeader = responseHeaders.getFirstHeader("Connection"); + String connectionDirective = null; + if (connectionHeader != null) { + connectionDirective = connectionHeader.getValue(); + } + if (!"close".equalsIgnoreCase(connectionDirective)) { + LOG.info("Response content length is not known"); + setConnectionCloseForced(true); + } + } + result = is; + } else { + result = new ContentLengthInputStream(is, expectedLength); + } + } + + // See if the response is supposed to have a response body + if (!canHaveBody) { + result = null; + } + // if there is a result - ALWAYS wrap it in an observer which will + // close the underlying stream as soon as it is consumed, and notify + // the watcher that the stream has been consumed. + if (result != null) { + + result = new AutoCloseInputStream( + result, + new ResponseConsumedWatcher() { + public void responseConsumed() { + responseBodyConsumed(); + } + } + ); + } + + return result; + } + + /** + * Reads the response headers from the given {@link HttpConnection connection}. + * + *

+ * Subclasses may want to override this method to to customize the + * processing. + *

+ * + *

+ * "It must be possible to combine the multiple header fields into one + * "field-name: field-value" pair, without changing the semantics of the + * message, by appending each subsequent field-value to the first, each + * separated by a comma." - HTTP/1.0 (4.3) + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #readResponse + * @see #processResponseHeaders + */ + protected void readResponseHeaders(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter HttpMethodBase.readResponseHeaders(HttpState," + + "HttpConnection)"); + + getResponseHeaderGroup().clear(); + + Header[] headers = HttpParser.parseHeaders( + conn.getResponseInputStream(), getParams().getHttpElementCharset()); + if (Wire.HEADER_WIRE.enabled()) { + for (int i = 0; i < headers.length; i++) { + Wire.HEADER_WIRE.input(headers[i].toExternalForm()); + } + } + getResponseHeaderGroup().setHeaders(headers); + } + + /** + * Read the status line from the given {@link HttpConnection}, setting my + * {@link #getStatusCode status code} and {@link #getStatusText status + * text}. + * + *

+ * Subclasses may want to override this method to to customize the + * processing. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see StatusLine + */ + protected void readStatusLine(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter HttpMethodBase.readStatusLine(HttpState, HttpConnection)"); + + final int maxGarbageLines = getParams(). + getIntParameter(HttpMethodParams.STATUS_LINE_GARBAGE_LIMIT, Integer.MAX_VALUE); + + //read out the HTTP status string + int count = 0; + String s; + do { + s = conn.readLine(getParams().getHttpElementCharset()); + if (s == null && count == 0) { + // The server just dropped connection on us + throw new NoHttpResponseException("The server " + conn.getHost() + + " failed to respond"); + } + if (Wire.HEADER_WIRE.enabled()) { + Wire.HEADER_WIRE.input(s + "\r\n"); + } + if (s != null && StatusLine.startsWithHTTP(s)) { + // Got one + break; + } else if (s == null || count >= maxGarbageLines) { + // Giving up + throw new ProtocolException("The server " + conn.getHost() + + " failed to respond with a valid HTTP response"); + } + count++; + } while(true); + + //create the status line from the status string + statusLine = new StatusLine(s); + + //check for a valid HTTP-Version + String versionStr = statusLine.getHttpVersion(); + if (getParams().isParameterFalse(HttpMethodParams.UNAMBIGUOUS_STATUS_LINE) + && versionStr.equals("HTTP")) { + getParams().setVersion(HttpVersion.HTTP_1_0); + if (LOG.isWarnEnabled()) { + LOG.warn("Ambiguous status line (HTTP protocol version missing):" + + statusLine.toString()); + } + } else { + this.effectiveVersion = HttpVersion.parse(versionStr); + } + + } + + // ------------------------------------------------------ Protected Methods + + /** + *

+ * Sends the request via the given {@link HttpConnection connection}. + *

+ * + *

+ * The request is written as the following sequence of actions: + *

+ * + *
    + *
  1. + * {@link #writeRequestLine(HttpState, HttpConnection)} is invoked to + * write the request line. + *
  2. + *
  3. + * {@link #writeRequestHeaders(HttpState, HttpConnection)} is invoked + * to write the associated headers. + *
  4. + *
  5. + * \r\n is sent to close the head part of the request. + *
  6. + *
  7. + * {@link #writeRequestBody(HttpState, HttpConnection)} is invoked to + * write the body part of the request. + *
  8. + *
+ * + *

+ * Subclasses may want to override one or more of the above methods to to + * customize the processing. (Or they may choose to override this method + * if dramatically different processing is required.) + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected void writeRequest(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace( + "enter HttpMethodBase.writeRequest(HttpState, HttpConnection)"); + writeRequestLine(state, conn); + writeRequestHeaders(state, conn); + conn.writeLine(); // close head + if (Wire.HEADER_WIRE.enabled()) { + Wire.HEADER_WIRE.output("\r\n"); + } + + HttpVersion ver = getParams().getVersion(); + Header expectheader = getRequestHeader("Expect"); + String expectvalue = null; + if (expectheader != null) { + expectvalue = expectheader.getValue(); + } + if ((expectvalue != null) + && (expectvalue.compareToIgnoreCase("100-continue") == 0)) { + if (ver.greaterEquals(HttpVersion.HTTP_1_1)) { + + // make sure the status line and headers have been sent + conn.flushRequestOutputStream(); + + int readTimeout = conn.getParams().getSoTimeout(); + try { + conn.setSocketTimeout(RESPONSE_WAIT_TIME_MS); + readStatusLine(state, conn); + processStatusLine(state, conn); + readResponseHeaders(state, conn); + processResponseHeaders(state, conn); + + if (this.statusLine.getStatusCode() == HttpStatus.SC_CONTINUE) { + // Discard status line + this.statusLine = null; + LOG.debug("OK to continue received"); + } else { + return; + } + } catch (InterruptedIOException e) { + if (!ExceptionUtil.isSocketTimeoutException(e)) { + throw e; + } + // Most probably Expect header is not recongnized + // Remove the header to signal the method + // that it's okay to go ahead with sending data + removeRequestHeader("Expect"); + LOG.info("100 (continue) read timeout. Resume sending the request"); + } finally { + conn.setSocketTimeout(readTimeout); + } + + } else { + removeRequestHeader("Expect"); + LOG.info("'Expect: 100-continue' handshake is only supported by " + + "HTTP/1.1 or higher"); + } + } + + writeRequestBody(state, conn); + // make sure the entire request body has been sent + conn.flushRequestOutputStream(); + } + + /** + * Writes the request body to the given {@link HttpConnection connection}. + * + *

+ * This method should return true if the request body was actually + * sent (or is empty), or false if it could not be sent for some + * reason. + *

+ * + *

+ * This implementation writes nothing and returns true. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @return true + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected boolean writeRequestBody(HttpState state, HttpConnection conn) + throws IOException, HttpException { + return true; + } + + /** + * Writes the request headers to the given {@link HttpConnection connection}. + * + *

+ * This implementation invokes {@link #addRequestHeaders(HttpState,HttpConnection)}, + * and then writes each header to the request stream. + *

+ * + *

+ * Subclasses may want to override this method to to customize the + * processing. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #addRequestHeaders + * @see #getRequestHeaders + */ + protected void writeRequestHeaders(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter HttpMethodBase.writeRequestHeaders(HttpState," + + "HttpConnection)"); + addRequestHeaders(state, conn); + + String charset = getParams().getHttpElementCharset(); + + Header[] headers = getRequestHeaders(); + for (int i = 0; i < headers.length; i++) { + String s = headers[i].toExternalForm(); + if (Wire.HEADER_WIRE.enabled()) { + Wire.HEADER_WIRE.output(s); + } + conn.print(s, charset); + } + } + + /** + * Writes the request line to the given {@link HttpConnection connection}. + * + *

+ * Subclasses may want to override this method to to customize the + * processing. + *

+ * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #generateRequestLine + */ + protected void writeRequestLine(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace( + "enter HttpMethodBase.writeRequestLine(HttpState, HttpConnection)"); + String requestLine = getRequestLine(conn); + if (Wire.HEADER_WIRE.enabled()) { + Wire.HEADER_WIRE.output(requestLine); + } + conn.print(requestLine, getParams().getHttpElementCharset()); + } + + /** + * Returns the request line. + * + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @return The request line. + */ + private String getRequestLine(HttpConnection conn) { + return HttpMethodBase.generateRequestLine(conn, getName(), + getPath(), getQueryString(), this.effectiveVersion.toString()); + } + + /** + * Returns {@link HttpMethodParams HTTP protocol parameters} associated with this method. + * + * @return HTTP parameters. + * + * @since 3.0 + */ + public HttpMethodParams getParams() { + return this.params; + } + + /** + * Assigns {@link HttpMethodParams HTTP protocol parameters} for this method. + * + * @since 3.0 + * + * @see HttpMethodParams + */ + public void setParams(final HttpMethodParams params) { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + this.params = params; + } + + /** + * Returns the HTTP version used with this method (may be null + * if undefined, that is, the method has not been executed) + * + * @return HTTP version. + * + * @since 3.0 + */ + public HttpVersion getEffectiveVersion() { + return this.effectiveVersion; + } + + /** + * Per RFC 2616 section 4.3, some response can never contain a message + * body. + * + * @param status - the HTTP status code + * + * @return true if the message may contain a body, false if it can not + * contain a message body + */ + private static boolean canResponseHaveBody(int status) { + LOG.trace("enter HttpMethodBase.canResponseHaveBody(int)"); + + boolean result = true; + + if ((status >= 100 && status <= 199) || (status == 204) + || (status == 304)) { // NOT MODIFIED + result = false; + } + + return result; + } + + /** + * Returns proxy authentication realm, if it has been used during authentication process. + * Otherwise returns null. + * + * @return proxy authentication realm + * + * @deprecated use #getProxyAuthState() + */ + public String getProxyAuthenticationRealm() { + return this.proxyAuthState.getRealm(); + } + + /** + * Returns authentication realm, if it has been used during authentication process. + * Otherwise returns null. + * + * @return authentication realm + * + * @deprecated use #getHostAuthState() + */ + public String getAuthenticationRealm() { + return this.hostAuthState.getRealm(); + } + + /** + * Returns the character set from the Content-Type header. + * + * @param contentheader The content header. + * @return String The character set. + */ + protected String getContentCharSet(Header contentheader) { + LOG.trace("enter getContentCharSet( Header contentheader )"); + String charset = null; + if (contentheader != null) { + HeaderElement values[] = contentheader.getElements(); + // I expect only one header element to be there + // No more. no less + if (values.length == 1) { + NameValuePair param = values[0].getParameterByName("charset"); + if (param != null) { + // If I get anything "funny" + // UnsupportedEncondingException will result + charset = param.getValue(); + } + } + } + if (charset == null) { + charset = getParams().getContentCharset(); + if (LOG.isDebugEnabled()) { + LOG.debug("Default charset used: " + charset); + } + } + return charset; + } + + + /** + * Returns the character encoding of the request from the Content-Type header. + * + * @return String The character set. + */ + public String getRequestCharSet() { + return getContentCharSet(getRequestHeader("Content-Type")); + } + + + /** + * Returns the character encoding of the response from the Content-Type header. + * + * @return String The character set. + */ + public String getResponseCharSet() { + return getContentCharSet(getResponseHeader("Content-Type")); + } + + /** + * @deprecated no longer used + * + * Returns the number of "recoverable" exceptions thrown and handled, to + * allow for monitoring the quality of the connection. + * + * @return The number of recoverable exceptions handled by the method. + */ + public int getRecoverableExceptionCount() { + return recoverableExceptionCount; + } + + /** + * A response has been consumed. + * + *

The default behavior for this class is to check to see if the connection + * should be closed, and close if need be, and to ensure that the connection + * is returned to the connection manager - if and only if we are not still + * inside the execute call.

+ * + */ + protected void responseBodyConsumed() { + + // make sure this is the initial invocation of the notification, + // ignore subsequent ones. + responseStream = null; + if (responseConnection != null) { + responseConnection.setLastResponseInputStream(null); + + // At this point, no response data should be available. + // If there is data available, regard the connection as being + // unreliable and close it. + + if (shouldCloseConnection(responseConnection)) { + responseConnection.close(); + } else { + try { + if(responseConnection.isResponseAvailable()) { + boolean logExtraInput = + getParams().isParameterTrue(HttpMethodParams.WARN_EXTRA_INPUT); + + if(logExtraInput) { + LOG.warn("Extra response data detected - closing connection"); + } + responseConnection.close(); + } + } + catch (IOException e) { + LOG.warn(e.getMessage()); + responseConnection.close(); + } + } + } + this.connectionCloseForced = false; + ensureConnectionRelease(); + } + + /** + * Insure that the connection is released back to the pool. + */ + private void ensureConnectionRelease() { + if (responseConnection != null) { + responseConnection.releaseConnection(); + responseConnection = null; + } + } + + /** + * Returns the {@link HostConfiguration host configuration}. + * + * @return the host configuration + * + * @deprecated no longer applicable + */ + public HostConfiguration getHostConfiguration() { + HostConfiguration hostconfig = new HostConfiguration(); + hostconfig.setHost(this.httphost); + return hostconfig; + } + /** + * Sets the {@link HostConfiguration host configuration}. + * + * @param hostconfig The hostConfiguration to set + * + * @deprecated no longer applicable + */ + public void setHostConfiguration(final HostConfiguration hostconfig) { + if (hostconfig != null) { + this.httphost = new HttpHost( + hostconfig.getHost(), + hostconfig.getPort(), + hostconfig.getProtocol()); + } else { + this.httphost = null; + } + } + + /** + * Returns the {@link MethodRetryHandler retry handler} for this HTTP method + * + * @return the methodRetryHandler + * + * @deprecated use {@link HttpMethodParams} + */ + public MethodRetryHandler getMethodRetryHandler() { + return methodRetryHandler; + } + + /** + * Sets the {@link MethodRetryHandler retry handler} for this HTTP method + * + * @param handler the methodRetryHandler to use when this method executed + * + * @deprecated use {@link HttpMethodParams} + */ + public void setMethodRetryHandler(MethodRetryHandler handler) { + methodRetryHandler = handler; + } + + /** + * This method is a dirty hack intended to work around + * current (2.0) design flaw that prevents the user from + * obtaining correct status code, headers and response body from the + * preceding HTTP CONNECT method. + * + * TODO: Remove this crap as soon as possible + */ + void fakeResponse( + StatusLine statusline, + HeaderGroup responseheaders, + InputStream responseStream + ) { + // set used so that the response can be read + this.used = true; + this.statusLine = statusline; + this.responseHeaders = responseheaders; + this.responseBody = null; + this.responseStream = responseStream; + } + + /** + * Returns the target host {@link AuthState authentication state} + * + * @return host authentication state + * + * @since 3.0 + */ + public AuthState getHostAuthState() { + return this.hostAuthState; + } + + /** + * Returns the proxy {@link AuthState authentication state} + * + * @return host authentication state + * + * @since 3.0 + */ + public AuthState getProxyAuthState() { + return this.proxyAuthState; + } + + /** + * Tests whether the execution of this method has been aborted + * + * @return true if the execution of this method has been aborted, + * false otherwise + * + * @since 3.0 + */ + public boolean isAborted() { + return this.aborted; + } + + /** + * Returns true if the HTTP has been transmitted to the target + * server in its entirety, false otherwise. This flag can be useful + * for recovery logic. If the request has not been transmitted in its entirety, + * it is safe to retry the failed method. + * + * @return true if the request has been sent, false otherwise + */ + public boolean isRequestSent() { + return this.requestSent; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodDirector.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodDirector.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodDirector.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,933 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodDirector.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.auth.AuthChallengeException; +import org.apache.commons.httpclient.auth.AuthChallengeParser; +import org.apache.commons.httpclient.auth.AuthChallengeProcessor; +import org.apache.commons.httpclient.auth.AuthScheme; +import org.apache.commons.httpclient.auth.AuthState; +import org.apache.commons.httpclient.auth.AuthenticationException; +import org.apache.commons.httpclient.auth.CredentialsProvider; +import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.auth.MalformedChallengeException; +import org.apache.commons.httpclient.params.HostParams; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.httpclient.params.HttpParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Handles the process of executing a method including authentication, redirection and retries. + * + * @since 3.0 + */ +class HttpMethodDirector { + + /** The www authenticate challange header. */ + public static final String WWW_AUTH_CHALLENGE = "WWW-Authenticate"; + + /** The www authenticate response header. */ + public static final String WWW_AUTH_RESP = "Authorization"; + + /** The proxy authenticate challange header. */ + public static final String PROXY_AUTH_CHALLENGE = "Proxy-Authenticate"; + + /** The proxy authenticate response header. */ + public static final String PROXY_AUTH_RESP = "Proxy-Authorization"; + + private static final Log LOG = LogFactory.getLog(HttpMethodDirector.class); + + private ConnectMethod connectMethod; + + private HttpState state; + + private HostConfiguration hostConfiguration; + + private HttpConnectionManager connectionManager; + + private HttpClientParams params; + + private HttpConnection conn; + + /** A flag to indicate if the connection should be released after the method is executed. */ + private boolean releaseConnection = false; + + /** Authentication processor */ + private AuthChallengeProcessor authProcessor = null; + + private Set redirectLocations = null; + + public HttpMethodDirector( + final HttpConnectionManager connectionManager, + final HostConfiguration hostConfiguration, + final HttpClientParams params, + final HttpState state + ) { + super(); + this.connectionManager = connectionManager; + this.hostConfiguration = hostConfiguration; + this.params = params; + this.state = state; + this.authProcessor = new AuthChallengeProcessor(this.params); + } + + + /** + * Executes the method associated with this method director. + * + * @throws IOException + * @throws HttpException + */ + public void executeMethod(final HttpMethod method) throws IOException, HttpException { + if (method == null) { + throw new IllegalArgumentException("Method may not be null"); + } + // Link all parameter collections to form the hierarchy: + // Global -> HttpClient -> HostConfiguration -> HttpMethod + this.hostConfiguration.getParams().setDefaults(this.params); + method.getParams().setDefaults(this.hostConfiguration.getParams()); + + // Generate default request headers + Collection defaults = (Collection)this.hostConfiguration.getParams(). + getParameter(HostParams.DEFAULT_HEADERS); + if (defaults != null) { + Iterator i = defaults.iterator(); + while (i.hasNext()) { + method.addRequestHeader((Header)i.next()); + } + } + + try { + int maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100); + + for (int redirectCount = 0;;) { + + // make sure the connection we have is appropriate + if (this.conn != null && !hostConfiguration.hostEquals(this.conn)) { + this.conn.setLocked(false); + this.conn.releaseConnection(); + this.conn = null; + } + + // get a connection, if we need one + if (this.conn == null) { + this.conn = connectionManager.getConnectionWithTimeout( + hostConfiguration, + this.params.getConnectionManagerTimeout() + ); + this.conn.setLocked(true); + if (this.params.isAuthenticationPreemptive() + || this.state.isAuthenticationPreemptive()) + { + LOG.debug("Preemptively sending default basic credentials"); + method.getHostAuthState().setPreemptive(); + method.getHostAuthState().setAuthAttempted(true); + if (this.conn.isProxied() && !this.conn.isSecure()) { + method.getProxyAuthState().setPreemptive(); + method.getProxyAuthState().setAuthAttempted(true); + } + } + } + authenticate(method); + executeWithRetry(method); + if (this.connectMethod != null) { + fakeResponse(method); + break; + } + + boolean retry = false; + if (isRedirectNeeded(method)) { + if (processRedirectResponse(method)) { + retry = true; + ++redirectCount; + if (redirectCount >= maxRedirects) { + LOG.error("Narrowly avoided an infinite loop in execute"); + throw new RedirectException("Maximum redirects (" + + maxRedirects + ") exceeded"); + } + if (LOG.isDebugEnabled()) { + LOG.debug("Execute redirect " + redirectCount + " of " + maxRedirects); + } + } + } + if (isAuthenticationNeeded(method)) { + if (processAuthenticationResponse(method)) { + LOG.debug("Retry authentication"); + retry = true; + } + } + if (!retry) { + break; + } + // retry - close previous stream. Caution - this causes + // responseBodyConsumed to be called, which may also close the + // connection. + if (method.getResponseBodyAsStream() != null) { + method.getResponseBodyAsStream().close(); + } + + } //end of retry loop + } finally { + if (this.conn != null) { + this.conn.setLocked(false); + } + // If the response has been fully processed, return the connection + // to the pool. Use this flag, rather than other tests (like + // responseStream == null), as subclasses, might reset the stream, + // for example, reading the entire response into a file and then + // setting the file as the stream. + if ( + (releaseConnection || method.getResponseBodyAsStream() == null) + && this.conn != null + ) { + this.conn.releaseConnection(); + } + } + + } + + + private void authenticate(final HttpMethod method) { + try { + if (this.conn.isProxied() && !this.conn.isSecure()) { + authenticateProxy(method); + } + authenticateHost(method); + } catch (AuthenticationException e) { + LOG.error(e.getMessage(), e); + } + } + + + private boolean cleanAuthHeaders(final HttpMethod method, final String name) { + Header[] authheaders = method.getRequestHeaders(name); + boolean clean = true; + for (int i = 0; i < authheaders.length; i++) { + Header authheader = authheaders[i]; + if (authheader.isAutogenerated()) { + method.removeRequestHeader(authheader); + } else { + clean = false; + } + } + return clean; + } + + + private void authenticateHost(final HttpMethod method) throws AuthenticationException { + // Clean up existing authentication headers + if (!cleanAuthHeaders(method, WWW_AUTH_RESP)) { + // User defined authentication header(s) present + return; + } + AuthState authstate = method.getHostAuthState(); + AuthScheme authscheme = authstate.getAuthScheme(); + if (authscheme == null) { + return; + } + if (authstate.isAuthRequested() || !authscheme.isConnectionBased()) { + String host = method.getParams().getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + int port = conn.getPort(); + AuthScope authscope = new AuthScope( + host, port, + authscheme.getRealm(), + authscheme.getSchemeName()); + if (LOG.isDebugEnabled()) { + LOG.debug("Authenticating with " + authscope); + } + Credentials credentials = this.state.getCredentials(authscope); + if (credentials != null) { + String authstring = authscheme.authenticate(credentials, method); + if (authstring != null) { + method.addRequestHeader(new Header(WWW_AUTH_RESP, authstring, true)); + } + } else { + if (LOG.isWarnEnabled()) { + LOG.warn("Required credentials not available for " + authscope); + if (method.getHostAuthState().isPreemptive()) { + LOG.warn("Preemptive authentication requested but no default " + + "credentials available"); + } + } + } + } + } + + + private void authenticateProxy(final HttpMethod method) throws AuthenticationException { + // Clean up existing authentication headers + if (!cleanAuthHeaders(method, PROXY_AUTH_RESP)) { + // User defined authentication header(s) present + return; + } + AuthState authstate = method.getProxyAuthState(); + AuthScheme authscheme = authstate.getAuthScheme(); + if (authscheme == null) { + return; + } + if (authstate.isAuthRequested() || !authscheme.isConnectionBased()) { + AuthScope authscope = new AuthScope( + conn.getProxyHost(), conn.getProxyPort(), + authscheme.getRealm(), + authscheme.getSchemeName()); + if (LOG.isDebugEnabled()) { + LOG.debug("Authenticating with " + authscope); + } + Credentials credentials = this.state.getProxyCredentials(authscope); + if (credentials != null) { + String authstring = authscheme.authenticate(credentials, method); + if (authstring != null) { + method.addRequestHeader(new Header(PROXY_AUTH_RESP, authstring, true)); + } + } else { + if (LOG.isWarnEnabled()) { + LOG.warn("Required proxy credentials not available for " + authscope); + if (method.getProxyAuthState().isPreemptive()) { + LOG.warn("Preemptive authentication requested but no default " + + "proxy credentials available"); + } + } + } + } + } + + + /** + * Applies connection parameters specified for a given method + * + * @param method HTTP method + * + * @throws IOException if an I/O occurs setting connection parameters + */ + private void applyConnectionParams(final HttpMethod method) throws IOException { + int timeout = 0; + // see if a timeout is given for this method + Object param = method.getParams().getParameter(HttpMethodParams.SO_TIMEOUT); + if (param == null) { + // if not, use the default value + param = this.conn.getParams().getParameter(HttpConnectionParams.SO_TIMEOUT); + } + if (param != null) { + timeout = ((Integer)param).intValue(); + } + this.conn.setSocketTimeout(timeout); + } + + /** + * Executes a method with the current hostConfiguration. + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + private void executeWithRetry(final HttpMethod method) + throws IOException, HttpException { + + /** How many times did this transparently handle a recoverable exception? */ + int execCount = 0; + // loop until the method is successfully processed, the retryHandler + // returns false or a non-recoverable exception is thrown + try { + while (true) { + execCount++; + try { + + if (LOG.isTraceEnabled()) { + LOG.trace("Attempt number " + execCount + " to process request"); + } + if (this.conn.getParams().isStaleCheckingEnabled()) { + this.conn.closeIfStale(); + } + if (!this.conn.isOpen()) { + // this connection must be opened before it can be used + // This has nothing to do with opening a secure tunnel + this.conn.open(); + if (this.conn.isProxied() && this.conn.isSecure() + && !(method instanceof ConnectMethod)) { + // we need to create a secure tunnel before we can execute the real method + if (!executeConnect()) { + // abort, the connect method failed + return; + } + } + } + applyConnectionParams(method); + method.execute(state, this.conn); + break; + } catch (HttpException e) { + // filter out protocol exceptions which cannot be recovered from + throw e; + } catch (IOException e) { + LOG.debug("Closing the connection."); + this.conn.close(); + // test if this method should be retried + // ======================================== + // this code is provided for backward compatibility with 2.0 + // will be removed in the next major release + if (method instanceof HttpMethodBase) { + MethodRetryHandler handler = + ((HttpMethodBase)method).getMethodRetryHandler(); + if (handler != null) { + if (!handler.retryMethod( + method, + this.conn, + new HttpRecoverableException(e.getMessage()), + execCount, + method.isRequestSent())) { + LOG.debug("Method retry handler returned false. " + + "Automatic recovery will not be attempted"); + throw e; + } + } + } + // ======================================== + HttpMethodRetryHandler handler = + (HttpMethodRetryHandler)method.getParams().getParameter( + HttpMethodParams.RETRY_HANDLER); + if (handler == null) { + handler = new DefaultHttpMethodRetryHandler(); + } + if (!handler.retryMethod(method, e, execCount)) { + LOG.debug("Method retry handler returned false. " + + "Automatic recovery will not be attempted"); + throw e; + } + if (LOG.isInfoEnabled()) { + LOG.info("I/O exception ("+ e.getClass().getName() +") caught when processing request: " + + e.getMessage()); + } + if (LOG.isDebugEnabled()) { + LOG.debug(e.getMessage(), e); + } + LOG.info("Retrying request"); + } + } + } catch (IOException e) { + if (this.conn.isOpen()) { + LOG.debug("Closing the connection."); + this.conn.close(); + } + releaseConnection = true; + throw e; + } catch (RuntimeException e) { + if (this.conn.isOpen) { + LOG.debug("Closing the connection."); + this.conn.close(); + } + releaseConnection = true; + throw e; + } + } + + /** + * Executes a ConnectMethod to establish a tunneled connection. + * + * @return true if the connect was successful + * + * @throws IOException + * @throws HttpException + */ + private boolean executeConnect() + throws IOException, HttpException { + + this.connectMethod = new ConnectMethod(); + this.connectMethod.getParams().setDefaults(this.hostConfiguration.getParams()); + + int code; + for (;;) { + if (!this.conn.isOpen()) { + this.conn.open(); + } + if (this.params.isAuthenticationPreemptive() + || this.state.isAuthenticationPreemptive()) { + LOG.debug("Preemptively sending default basic credentials"); + this.connectMethod.getProxyAuthState().setPreemptive(); + this.connectMethod.getProxyAuthState().setAuthAttempted(true); + } + try { + authenticateProxy(this.connectMethod); + } catch (AuthenticationException e) { + LOG.error(e.getMessage(), e); + } + applyConnectionParams(this.connectMethod); + this.connectMethod.execute(state, this.conn); + code = this.connectMethod.getStatusCode(); + boolean retry = false; + AuthState authstate = this.connectMethod.getProxyAuthState(); + authstate.setAuthRequested(code == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED); + if (authstate.isAuthRequested()) { + if (processAuthenticationResponse(this.connectMethod)) { + retry = true; + } + } + if (!retry) { + break; + } + if (this.connectMethod.getResponseBodyAsStream() != null) { + this.connectMethod.getResponseBodyAsStream().close(); + } + } + if ((code >= 200) && (code < 300)) { + this.conn.tunnelCreated(); + // Drop the connect method, as it is no longer needed + this.connectMethod = null; + return true; + } else { + return false; + } + } + + /** + * Fake response + * @param method + * @return + */ + + private void fakeResponse(final HttpMethod method) + throws IOException, HttpException { + // What is to follow is an ugly hack. + // I REALLY hate having to resort to such + // an appalling trick + // The only feasible solution is to split monolithic + // HttpMethod into HttpRequest/HttpResponse pair. + // That would allow to execute CONNECT method + // behind the scene and return CONNECT HttpResponse + // object in response to the original request that + // contains the correct status line, headers & + // response body. + LOG.debug("CONNECT failed, fake the response for the original method"); + // Pass the status, headers and response stream to the wrapped + // method. + // To ensure that the connection is not released more than once + // this method is still responsible for releasing the connection. + // This will happen when the response body is consumed, or when + // the wrapped method closes the response connection in + // releaseConnection(). + if (method instanceof HttpMethodBase) { + ((HttpMethodBase) method).fakeResponse( + this.connectMethod.getStatusLine(), + this.connectMethod.getResponseHeaderGroup(), + this.connectMethod.getResponseBodyAsStream() + ); + method.getProxyAuthState().setAuthScheme( + this.connectMethod.getProxyAuthState().getAuthScheme()); + this.connectMethod = null; + } else { + releaseConnection = true; + LOG.warn( + "Unable to fake response on method as it is not derived from HttpMethodBase."); + } + } + + /** + * Process the redirect response. + * + * @return true if the redirect was successful + */ + private boolean processRedirectResponse(final HttpMethod method) + throws RedirectException { + //get the location header to find out where to redirect to + Header locationHeader = method.getResponseHeader("location"); + if (locationHeader == null) { + // got a redirect response, but no location header + LOG.error("Received redirect response " + method.getStatusCode() + + " but no location header"); + return false; + } + String location = locationHeader.getValue(); + if (LOG.isDebugEnabled()) { + LOG.debug("Redirect requested to location '" + location + "'"); + } + + //rfc2616 demands the location value be a complete URI + //Location = "Location" ":" absoluteURI + URI redirectUri = null; + URI currentUri = null; + + try { + currentUri = new URI( + this.conn.getProtocol().getScheme(), + null, + this.conn.getHost(), + this.conn.getPort(), + method.getPath() + ); + redirectUri = new URI(location, true); + if (redirectUri.isRelativeURI()) { + if (this.params.isParameterTrue(HttpClientParams.REJECT_RELATIVE_REDIRECT)) { + LOG.warn("Relative redirect location '" + location + "' not allowed"); + return false; + } else { + //location is incomplete, use current values for defaults + LOG.debug("Redirect URI is not absolute - parsing as relative"); + redirectUri = new URI(currentUri, redirectUri); + } + } + method.setURI(redirectUri); + hostConfiguration.setHost(redirectUri); + } catch (URIException e) { + LOG.warn("Redirected location '" + location + "' is malformed"); + return false; + } + + if (this.params.isParameterFalse(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS)) { + if (this.redirectLocations == null) { + this.redirectLocations = new HashSet(); + } + this.redirectLocations.add(currentUri); + try { + if(redirectUri.hasQuery()) { + redirectUri.setQuery(null); + } + } catch (URIException e) { + // Should never happen + return false; + } + + if (this.redirectLocations.contains(redirectUri)) { + throw new CircularRedirectException("Circular redirect to '" + + redirectUri + "'"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Redirecting from '" + currentUri.getEscapedURI() + + "' to '" + redirectUri.getEscapedURI()); + } + //And finally invalidate the actual authentication scheme + method.getHostAuthState().invalidate(); + return true; + } + + /** + * Processes a response that requires authentication + * + * @param method the current {@link HttpMethod HTTP method} + * + * @return true if the authentication challenge can be responsed to, + * (that is, at least one of the requested authentication scheme is supported, + * and matching credentials have been found), false otherwise. + */ + private boolean processAuthenticationResponse(final HttpMethod method) { + LOG.trace("enter HttpMethodBase.processAuthenticationResponse(" + + "HttpState, HttpConnection)"); + + try { + switch (method.getStatusCode()) { + case HttpStatus.SC_UNAUTHORIZED: + return processWWWAuthChallenge(method); + case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: + return processProxyAuthChallenge(method); + default: + return false; + } + } catch (Exception e) { + if (LOG.isErrorEnabled()) { + LOG.error(e.getMessage(), e); + } + return false; + } + } + + private boolean processWWWAuthChallenge(final HttpMethod method) + throws MalformedChallengeException, AuthenticationException + { + AuthState authstate = method.getHostAuthState(); + Map challenges = AuthChallengeParser.parseChallenges( + method.getResponseHeaders(WWW_AUTH_CHALLENGE)); + if (challenges.isEmpty()) { + LOG.debug("Authentication challenge(s) not found"); + return false; + } + AuthScheme authscheme = null; + try { + authscheme = this.authProcessor.processChallenge(authstate, challenges); + } catch (AuthChallengeException e) { + if (LOG.isWarnEnabled()) { + LOG.warn(e.getMessage()); + } + } + if (authscheme == null) { + return false; + } + String host = method.getParams().getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + int port = conn.getPort(); + AuthScope authscope = new AuthScope( + host, port, + authscheme.getRealm(), + authscheme.getSchemeName()); + + if (LOG.isDebugEnabled()) { + LOG.debug("Authentication scope: " + authscope); + } + if (authstate.isAuthAttempted() && authscheme.isComplete()) { + // Already tried and failed + Credentials credentials = promptForCredentials( + authscheme, method.getParams(), authscope); + if (credentials == null) { + if (LOG.isInfoEnabled()) { + LOG.info("Failure authenticating with " + authscope); + } + return false; + } else { + return true; + } + } else { + authstate.setAuthAttempted(true); + Credentials credentials = this.state.getCredentials(authscope); + if (credentials == null) { + credentials = promptForCredentials( + authscheme, method.getParams(), authscope); + } + if (credentials == null) { + if (LOG.isInfoEnabled()) { + LOG.info("No credentials available for " + authscope); + } + return false; + } else { + return true; + } + } + } + + private boolean processProxyAuthChallenge(final HttpMethod method) + throws MalformedChallengeException, AuthenticationException + { + AuthState authstate = method.getProxyAuthState(); + Map proxyChallenges = AuthChallengeParser.parseChallenges( + method.getResponseHeaders(PROXY_AUTH_CHALLENGE)); + if (proxyChallenges.isEmpty()) { + LOG.debug("Proxy authentication challenge(s) not found"); + return false; + } + AuthScheme authscheme = null; + try { + authscheme = this.authProcessor.processChallenge(authstate, proxyChallenges); + } catch (AuthChallengeException e) { + if (LOG.isWarnEnabled()) { + LOG.warn(e.getMessage()); + } + } + if (authscheme == null) { + return false; + } + AuthScope authscope = new AuthScope( + conn.getProxyHost(), conn.getProxyPort(), + authscheme.getRealm(), + authscheme.getSchemeName()); + + if (LOG.isDebugEnabled()) { + LOG.debug("Proxy authentication scope: " + authscope); + } + if (authstate.isAuthAttempted() && authscheme.isComplete()) { + // Already tried and failed + Credentials credentials = promptForProxyCredentials( + authscheme, method.getParams(), authscope); + if (credentials == null) { + if (LOG.isInfoEnabled()) { + LOG.info("Failure authenticating with " + authscope); + } + return false; + } else { + return true; + } + } else { + authstate.setAuthAttempted(true); + Credentials credentials = this.state.getProxyCredentials(authscope); + if (credentials == null) { + credentials = promptForProxyCredentials( + authscheme, method.getParams(), authscope); + } + if (credentials == null) { + if (LOG.isInfoEnabled()) { + LOG.info("No credentials available for " + authscope); + } + return false; + } else { + return true; + } + } + } + + /** + * Tests if the {@link HttpMethod method} requires a redirect to another location. + * + * @param method HTTP method + * + * @return boolean true if a retry is needed, false otherwise. + */ + private boolean isRedirectNeeded(final HttpMethod method) { + switch (method.getStatusCode()) { + case HttpStatus.SC_MOVED_TEMPORARILY: + case HttpStatus.SC_MOVED_PERMANENTLY: + case HttpStatus.SC_SEE_OTHER: + case HttpStatus.SC_TEMPORARY_REDIRECT: + LOG.debug("Redirect required"); + if (method.getFollowRedirects()) { + return true; + } else { + LOG.info("Redirect requested but followRedirects is " + + "disabled"); + return false; + } + default: + return false; + } //end of switch + } + + /** + * Tests if the {@link HttpMethod method} requires authentication. + * + * @param method HTTP method + * + * @return boolean true if a retry is needed, false otherwise. + */ + private boolean isAuthenticationNeeded(final HttpMethod method) { + method.getHostAuthState().setAuthRequested( + method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED); + method.getProxyAuthState().setAuthRequested( + method.getStatusCode() == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED); + if (method.getHostAuthState().isAuthRequested() || + method.getProxyAuthState().isAuthRequested()) { + LOG.debug("Authorization required"); + if (method.getDoAuthentication()) { //process authentication response + return true; + } else { //let the client handle the authenticaiton + LOG.info("Authentication requested but doAuthentication is " + + "disabled"); + return false; + } + } else { + return false; + } + } + + private Credentials promptForCredentials( + final AuthScheme authScheme, + final HttpParams params, + final AuthScope authscope) + { + LOG.debug("Credentials required"); + Credentials creds = null; + CredentialsProvider credProvider = + (CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER); + if (credProvider != null) { + try { + creds = credProvider.getCredentials( + authScheme, authscope.getHost(), authscope.getPort(), false); + } catch (CredentialsNotAvailableException e) { + LOG.warn(e.getMessage()); + } + if (creds != null) { + this.state.setCredentials(authscope, creds); + if (LOG.isDebugEnabled()) { + LOG.debug(authscope + " new credentials given"); + } + } + } else { + LOG.debug("Credentials provider not available"); + } + return creds; + } + + private Credentials promptForProxyCredentials( + final AuthScheme authScheme, + final HttpParams params, + final AuthScope authscope) + { + LOG.debug("Proxy credentials required"); + Credentials creds = null; + CredentialsProvider credProvider = + (CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER); + if (credProvider != null) { + try { + creds = credProvider.getCredentials( + authScheme, authscope.getHost(), authscope.getPort(), true); + } catch (CredentialsNotAvailableException e) { + LOG.warn(e.getMessage()); + } + if (creds != null) { + this.state.setProxyCredentials(authscope, creds); + if (LOG.isDebugEnabled()) { + LOG.debug(authscope + " new credentials given"); + } + } + } else { + LOG.debug("Proxy credentials provider not available"); + } + return creds; + } + + /** + * @return + */ + public HostConfiguration getHostConfiguration() { + return hostConfiguration; + } + + /** + * @return + */ + public HttpState getState() { + return state; + } + + /** + * @return + */ + public HttpConnectionManager getConnectionManager() { + return connectionManager; + } + + /** + * @return + */ + public HttpParams getParams() { + return this.params; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodRetryHandler.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodRetryHandler.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodRetryHandler.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,64 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpMethodRetryHandler.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; + +/** + * A handler for determining if an HttpMethod should be retried after a + * recoverable exception during execution. + * + *

+ * Classes implementing this interface must synchronize access to shared + * data as methods of this interfrace may be executed from multiple threads + *

+ * + * @see HttpMethod#execute(HttpState, HttpConnection) + * + * @author Michael Becke + * @author Oleg Kalnichevski + */ +public interface HttpMethodRetryHandler { + + /** + * Determines if a method should be retried after an HttpRecoverableException + * occurs during execution. + * + * @param method the method being executed + * @param exception the exception that occurred + * @param executionCount the number of times this method has been + * unsuccessfully executed + * + * @return true if the method should be retried, false + * otherwise + */ + boolean retryMethod(HttpMethod method, IOException exception, int executionCount); + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpParser.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpParser.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpParser.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,224 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpParser.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; + +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A utility class for parsing http header values according to + * RFC-2616 Section 4 and 19.3. + * + * @author Michael Becke + * @author Oleg Kalnichevski + * + * @since 2.0beta1 + */ +public class HttpParser { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpParser.class); + + /** + * Constructor for HttpParser. + */ + private HttpParser() { } + + /** + * Return byte array from an (unchunked) input stream. + * Stop reading when "\n" terminator encountered + * If the stream ends before the line terminator is found, + * the last part of the string will still be returned. + * If no input data available, null is returned. + * + * @param inputStream the stream to read from + * + * @throws IOException if an I/O problem occurs + * @return a byte array from the stream + */ + public static byte[] readRawLine(InputStream inputStream) throws IOException { + LOG.trace("enter HttpParser.readRawLine()"); + + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + int ch; + while ((ch = inputStream.read()) >= 0) { + buf.write(ch); + if (ch == '\n') { // be tolerant (RFC-2616 Section 19.3) + break; + } + } + if (buf.size() == 0) { + return null; + } + return buf.toByteArray(); + } + + /** + * Read up to "\n" from an (unchunked) input stream. + * If the stream ends before the line terminator is found, + * the last part of the string will still be returned. + * If no input data available, null is returned. + * + * @param inputStream the stream to read from + * @param charset charset of HTTP protocol elements + * + * @throws IOException if an I/O problem occurs + * @return a line from the stream + * + * @since 3.0 + */ + public static String readLine(InputStream inputStream, String charset) throws IOException { + LOG.trace("enter HttpParser.readLine(InputStream, String)"); + byte[] rawdata = readRawLine(inputStream); + if (rawdata == null) { + return null; + } + // strip CR and LF from the end + int len = rawdata.length; + int offset = 0; + if (len > 0) { + if (rawdata[len - 1] == '\n') { + offset++; + if (len > 1) { + if (rawdata[len - 2] == '\r') { + offset++; + } + } + } + } + return EncodingUtil.getString(rawdata, 0, len - offset, charset); + } + + /** + * Read up to "\n" from an (unchunked) input stream. + * If the stream ends before the line terminator is found, + * the last part of the string will still be returned. + * If no input data available, null is returned + * + * @param inputStream the stream to read from + * + * @throws IOException if an I/O problem occurs + * @return a line from the stream + * + * @deprecated use #readLine(InputStream, String) + */ + + public static String readLine(InputStream inputStream) throws IOException { + LOG.trace("enter HttpParser.readLine(InputStream)"); + return readLine(inputStream, "US-ASCII"); + } + + /** + * Parses headers from the given stream. Headers with the same name are not + * combined. + * + * @param is the stream to read headers from + * @param charset the charset to use for reading the data + * + * @return an array of headers in the order in which they were parsed + * + * @throws IOException if an IO error occurs while reading from the stream + * @throws HttpException if there is an error parsing a header value + * + * @since 3.0 + */ + public static Header[] parseHeaders(InputStream is, String charset) throws IOException, HttpException { + LOG.trace("enter HeaderParser.parseHeaders(InputStream, String)"); + + ArrayList headers = new ArrayList(); + String name = null; + StringBuffer value = null; + for (; ;) { + String line = HttpParser.readLine(is, charset); + if ((line == null) || (line.trim().length() < 1)) { + break; + } + + // Parse the header name and value + // Check for folded headers first + // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2 + // discussion on folded headers + if ((line.charAt(0) == ' ') || (line.charAt(0) == '\t')) { + // we have continuation folded header + // so append value + if (value != null) { + value.append(' '); + value.append(line.trim()); + } + } else { + // make sure we save the previous name,value pair if present + if (name != null) { + headers.add(new Header(name, value.toString())); + } + + // Otherwise we should have normal HTTP header line + // Parse the header name and value + int colon = line.indexOf(":"); + if (colon < 0) { + throw new ProtocolException("Unable to parse header: " + line); + } + name = line.substring(0, colon).trim(); + value = new StringBuffer(line.substring(colon + 1).trim()); + } + + } + + // make sure we save the last name,value pair if present + if (name != null) { + headers.add(new Header(name, value.toString())); + } + + return (Header[]) headers.toArray(new Header[headers.size()]); + } + + /** + * Parses headers from the given stream. Headers with the same name are not + * combined. + * + * @param is the stream to read headers from + * + * @return an array of headers in the order in which they were parsed + * + * @throws IOException if an IO error occurs while reading from the stream + * @throws HttpException if there is an error parsing a header value + * + * @deprecated use #parseHeaders(InputStream, String) + */ + public static Header[] parseHeaders(InputStream is) throws IOException, HttpException { + LOG.trace("enter HeaderParser.parseHeaders(InputStream, String)"); + return parseHeaders(is, "US-ASCII"); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpRecoverableException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpRecoverableException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpRecoverableException.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,63 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpRecoverableException.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + *

+ * Signals that an HTTP or HttpClient exception has occurred. This + * exception may have been caused by a transient error and the request + * may be retried. It may be possible to retrieve the underlying transient + * error via the inherited {@link HttpException#getCause()} method. + *

+ * + * @deprecated no longer used + * + * @author Unascribed + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:35 $ + */ +public class HttpRecoverableException extends HttpException { + + /** + * Creates a new HttpRecoverableException with a null detail message. + */ + public HttpRecoverableException() { + super(); + } + + /** + * Creates a new HttpRecoverableException with the specified detail message. + * + * @param message exception message + */ + public HttpRecoverableException(String message) { + super(message); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpState.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpState.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpState.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,625 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpState.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.Iterator; +import org.apache.commons.httpclient.cookie.CookieSpec; +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * A container for HTTP attributes that may persist from request + * to request, such as {@link Cookie cookies} and authentication + * {@link Credentials credentials}. + *

+ * + * @author Remy Maucherat + * @author Rodney Waldhoff + * @author Jeff Dever + * @author Sean C. Sullivan + * @author Michael Becke + * @author Oleg Kalnichevski + * @author Mike Bowler + * @author Adrian Sutton + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:33 $ + * + */ +public class HttpState { + + // ----------------------------------------------------- Instance Variables + + /** + * Map of {@link Credentials credentials} by realm that this + * HTTP state contains. + */ + private HashMap credMap = new HashMap(); + + /** + * Map of {@link Credentials proxy credentials} by realm that this + * HTTP state contains + */ + private HashMap proxyCred = new HashMap(); + + /** + * Array of {@link Cookie cookies} that this HTTP state contains. + */ + private ArrayList cookies = new ArrayList(); + + private boolean preemptive = false; + + private int cookiePolicy = -1; + // -------------------------------------------------------- Class Variables + + /** + * The boolean system property name to turn on preemptive authentication. + * @deprecated This field and feature will be removed following HttpClient 3.0. + */ + public static final String PREEMPTIVE_PROPERTY = "httpclient.authentication.preemptive"; + + /** + * The default value for {@link #PREEMPTIVE_PROPERTY}. + * @deprecated This field and feature will be removed following HttpClient 3.0. + */ + public static final String PREEMPTIVE_DEFAULT = "false"; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpState.class); + + /** + * Default constructor. + */ + public HttpState() { + super(); + } + + // ------------------------------------------------------------- Properties + + /** + * Adds an {@link Cookie HTTP 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 + * + * @see #addCookies(Cookie[]) + * + */ + public synchronized void addCookie(Cookie cookie) { + LOG.trace("enter HttpState.addCookie(Cookie)"); + + if (cookie != null) { + // first remove any old cookie that is equivalent + for (Iterator it = cookies.iterator(); it.hasNext();) { + Cookie tmp = (Cookie) it.next(); + if (cookie.equals(tmp)) { + it.remove(); + break; + } + } + if (!cookie.isExpired()) { + cookies.add(cookie); + } + } + } + + /** + * Adds an array of {@link Cookie HTTP cookies}. Cookies are added individually and + * in the given array order. If any of the given cookies has already expired it will + * not be added, but existing values will still be removed. + * + * @param cookies the {@link Cookie cookies} to be added + * + * @see #addCookie(Cookie) + * + * + */ + public synchronized void addCookies(Cookie[] cookies) { + LOG.trace("enter HttpState.addCookies(Cookie[])"); + + if (cookies != null) { + for (int i = 0; i < cookies.length; i++) { + this.addCookie(cookies[i]); + } + } + } + + /** + * Returns an array of {@link Cookie cookies} that this HTTP + * state currently contains. + * + * @return an array of {@link Cookie cookies}. + * + * @see #getCookies(String, int, String, boolean) + * + */ + public synchronized Cookie[] getCookies() { + LOG.trace("enter HttpState.getCookies()"); + return (Cookie[]) (cookies.toArray(new Cookie[cookies.size()])); + } + + /** + * Returns an array of {@link Cookie cookies} in this HTTP + * state that match the given request parameters. + * + * @param domain the request domain + * @param port the request port + * @param path the request path + * @param secure true when using HTTPS + * + * @return an array of {@link Cookie cookies}. + * + * @see #getCookies() + * + * @deprecated use CookieSpec#match(String, int, String, boolean, Cookie) + */ + public synchronized Cookie[] getCookies( + String domain, + int port, + String path, + boolean secure + ) { + LOG.trace("enter HttpState.getCookies(String, int, String, boolean)"); + + CookieSpec matcher = CookiePolicy.getDefaultSpec(); + ArrayList list = new ArrayList(cookies.size()); + for (int i = 0, m = cookies.size(); i < m; i++) { + Cookie cookie = (Cookie) (cookies.get(i)); + if (matcher.match(domain, port, path, secure, cookie)) { + list.add(cookie); + } + } + return (Cookie[]) (list.toArray(new Cookie[list.size()])); + } + + /** + * Removes all of {@link Cookie cookies} in this HTTP state + * that have expired according to the current system time. + * + * @see #purgeExpiredCookies(java.util.Date) + * + */ + public synchronized boolean purgeExpiredCookies() { + LOG.trace("enter HttpState.purgeExpiredCookies()"); + return purgeExpiredCookies(new Date()); + } + + /** + * Removes all of {@link Cookie cookies} in this HTTP state + * that have expired by the specified {@link java.util.Date date}. + * + * @param date The {@link java.util.Date date} to compare against. + * + * @return true if any cookies were purged. + * + * @see Cookie#isExpired(java.util.Date) + * + * @see #purgeExpiredCookies() + */ + public synchronized boolean purgeExpiredCookies(Date date) { + LOG.trace("enter HttpState.purgeExpiredCookies(Date)"); + boolean removed = false; + Iterator it = cookies.iterator(); + while (it.hasNext()) { + if (((Cookie) (it.next())).isExpired(date)) { + it.remove(); + removed = true; + } + } + return removed; + } + + + /** + * Returns the current {@link CookiePolicy cookie policy} for this + * HTTP state. + * + * @return The {@link CookiePolicy cookie policy}. + * + * @deprecated Use + * {@link org.apache.commons.httpclient.params.HttpMethodParams#getCookiePolicy()}, + * {@link HttpMethod#getParams()}. + */ + + public int getCookiePolicy() { + return this.cookiePolicy; + } + + + /** + * Defines whether preemptive authentication should be + * attempted. + * + * @param value true if preemptive authentication should be + * attempted, false otherwise. + * + * @deprecated Use + * {@link org.apache.commons.httpclient.params.HttpClientParams#setAuthenticationPreemptive(boolean)}, + * {@link HttpClient#getParams()}. + */ + + public void setAuthenticationPreemptive(boolean value) { + this.preemptive = value; + } + + + /** + * Returns true if preemptive authentication should be + * attempted, false otherwise. + * + * @return boolean flag. + * + * @deprecated Use + * {@link org.apache.commons.httpclient.params.HttpClientParams#isAuthenticationPreemptive()}, + * {@link HttpClient#getParams()}. + */ + + public boolean isAuthenticationPreemptive() { + return this.preemptive; + } + + + /** + * Sets the current {@link CookiePolicy cookie policy} for this HTTP + * state to one of the following supported policies: + * {@link CookiePolicy#COMPATIBILITY}, + * {@link CookiePolicy#NETSCAPE_DRAFT} or + * {@link CookiePolicy#RFC2109}. + * + * @param policy new {@link CookiePolicy cookie policy} + * + * @deprecated + * Use {@link org.apache.commons.httpclient.params.HttpMethodParams#setCookiePolicy(String)}, + * {@link HttpMethod#getParams()}. + */ + + public void setCookiePolicy(int policy) { + this.cookiePolicy = policy; + } + + /** + * Sets the {@link Credentials credentials} for the given authentication + * realm on the given host. The null realm signifies default + * credentials for the given host, which should be used when no + * {@link Credentials credentials} have been explictly supplied for the + * challenging realm. The null host signifies default + * credentials, which should be used when no {@link Credentials credentials} + * have been explictly supplied for the challenging host. Any previous + * credentials for the given realm on the given host will be overwritten. + * + * @param realm the authentication realm + * @param host the host the realm belongs to + * @param credentials the authentication {@link Credentials credentials} + * for the given realm. + * + * @see #getCredentials(String, String) + * @see #setProxyCredentials(String, String, Credentials) + * + * @deprecated use #setCredentials(AuthScope, Credentials) + */ + + public synchronized void setCredentials(String realm, String host, Credentials credentials) { + LOG.trace("enter HttpState.setCredentials(String, String, Credentials)"); + credMap.put(new AuthScope(host, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME), credentials); + } + + /** + * 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) + * @see #setProxyCredentials(AuthScope, Credentials) + * + * @since 3.0 + */ + public synchronized void setCredentials(final AuthScope authscope, final Credentials credentials) { + if (authscope == null) { + throw new IllegalArgumentException("Authentication scope may not be null"); + } + LOG.trace("enter HttpState.setCredentials(AuthScope, Credentials)"); + credMap.put(authscope, credentials); + } + + /** + * Find matching {@link Credentials credentials} for the given authentication scope. + * + * @param map the credentials hash map + * @param token the {@link AuthScope authentication scope} + * @return the credentials + * + */ + private static Credentials matchCredentials(final HashMap map, final AuthScope authscope) { + // see if we get a direct hit + Credentials creds = (Credentials)map.get(authscope); + if (creds == null) { + // Nope. + // Do a full scan + int bestMatchFactor = -1; + AuthScope bestMatch = null; + Iterator items = map.keySet().iterator(); + while (items.hasNext()) { + AuthScope current = (AuthScope)items.next(); + int factor = authscope.match(current); + if (factor > bestMatchFactor) { + bestMatchFactor = factor; + bestMatch = current; + } + } + if (bestMatch != null) { + creds = (Credentials)map.get(bestMatch); + } + } + return creds; + } + + /** + * Get the {@link Credentials credentials} for the given authentication scope on the + * given host. + * + * If the realm exists on host, return the coresponding credentials. + * If the host exists with a null realm, return the corresponding + * credentials. + * If the realm exists with a null host, return the + * corresponding credentials. If the realm does not exist, return + * the default Credentials. If there are no default credentials, return + * null. + * + * @param realm the authentication realm + * @param host the host the realm is on + * @return the credentials + * + * @see #setCredentials(String, String, Credentials) + * + * @deprecated use #getCredentials(AuthScope) + */ + + public synchronized Credentials getCredentials(String realm, String host) { + LOG.trace("enter HttpState.getCredentials(String, String"); + return matchCredentials(this.credMap, + new AuthScope(host, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME)); + } + + /** + * Get the {@link Credentials credentials} for the given authentication scope. + * + * @param authscope the {@link AuthScope authentication scope} + * @return the credentials + * + * @see #setCredentials(AuthScope, Credentials) + * + * @since 3.0 + */ + public synchronized Credentials getCredentials(final AuthScope authscope) { + if (authscope == null) { + throw new IllegalArgumentException("Authentication scope may not be null"); + } + LOG.trace("enter HttpState.getCredentials(AuthScope)"); + return matchCredentials(this.credMap, authscope); + } + + /** + * Sets the {@link Credentials credentials} for the given proxy authentication + * realm on the given proxy host. The null proxy realm signifies + * default credentials for the given proxy host, which should be used when no + * {@link Credentials credentials} have been explictly supplied for the + * challenging proxy realm. The null proxy host signifies default + * credentials, which should be used when no {@link Credentials credentials} + * have been explictly supplied for the challenging proxy host. Any previous + * credentials for the given proxy realm on the given proxy host will be + * overwritten. + * + * @param realm the authentication realm + * @param proxyHost the proxy host + * @param credentials the authentication credentials for the given realm + * + * @see #getProxyCredentials(AuthScope) + * @see #setCredentials(AuthScope, Credentials) + * + * @deprecated use #setProxyCredentials(AuthScope, Credentials) + */ + public synchronized void setProxyCredentials( + String realm, + String proxyHost, + Credentials credentials + ) { + LOG.trace("enter HttpState.setProxyCredentials(String, String, Credentials"); + proxyCred.put(new AuthScope(proxyHost, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME), credentials); + } + + /** + * Sets the {@link Credentials proxy credentials} for the given authentication + * realm. Any previous credentials for the given realm will be overwritten. + * + * @param authscope the {@link AuthScope authentication scope} + * @param credentials the authentication {@link Credentials credentials} + * for the given realm. + * + * @see #getProxyCredentials(AuthScope) + * @see #setCredentials(AuthScope, Credentials) + * + * @since 3.0 + */ + public synchronized void setProxyCredentials(final AuthScope authscope, + final Credentials credentials) + { + if (authscope == null) { + throw new IllegalArgumentException("Authentication scope may not be null"); + } + LOG.trace("enter HttpState.setProxyCredentials(AuthScope, Credentials)"); + proxyCred.put(authscope, credentials); + } + + /** + * Get the {@link Credentials credentials} for the proxy host with the given + * authentication scope. + * + * If the realm exists on host, return the coresponding credentials. + * If the host exists with a null realm, return the corresponding + * credentials. + * If the realm exists with a null host, return the + * corresponding credentials. If the realm does not exist, return + * the default Credentials. If there are no default credentials, return + * null. + * + * @param realm the authentication realm + * @param proxyHost the proxy host the realm is on + * @return the credentials + * @see #setProxyCredentials(String, String, Credentials) + * + * @deprecated use #getProxyCredentials(AuthScope) + */ + public synchronized Credentials getProxyCredentials(String realm, String proxyHost) { + LOG.trace("enter HttpState.getCredentials(String, String"); + return matchCredentials(this.proxyCred, + new AuthScope(proxyHost, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME)); + } + + /** + * Get the {@link Credentials proxy credentials} for the given authentication scope. + * + * @param authscope the {@link AuthScope authentication scope} + * @return the credentials + * + * @see #setProxyCredentials(AuthScope, Credentials) + * + * @since 3.0 + */ + public synchronized Credentials getProxyCredentials(final AuthScope authscope) { + if (authscope == null) { + throw new IllegalArgumentException("Authentication scope may not be null"); + } + LOG.trace("enter HttpState.getProxyCredentials(AuthScope)"); + return matchCredentials(this.proxyCred, authscope); + } + + /** + * Returns a string representation of this HTTP state. + * + * @return The string representation of the HTTP state. + * + * @see java.lang.Object#toString() + */ + public synchronized String toString() { + StringBuffer sbResult = new StringBuffer(); + + sbResult.append("["); + sbResult.append(getCredentialsStringRepresentation(proxyCred)); + sbResult.append(" | "); + sbResult.append(getCredentialsStringRepresentation(credMap)); + sbResult.append(" | "); + sbResult.append(getCookiesStringRepresentation(cookies)); + sbResult.append("]"); + + String strResult = sbResult.toString(); + + return strResult; + } + + /** + * Returns a string representation of the credentials. + * @param credMap The credentials. + * @return The string representation. + */ + private static String getCredentialsStringRepresentation(final Map credMap) { + StringBuffer sbResult = new StringBuffer(); + Iterator iter = credMap.keySet().iterator(); + while (iter.hasNext()) { + Object key = iter.next(); + Credentials cred = (Credentials) credMap.get(key); + if (sbResult.length() > 0) { + sbResult.append(", "); + } + sbResult.append(key); + sbResult.append("#"); + sbResult.append(cred.toString()); + } + return sbResult.toString(); + } + + /** + * Returns a string representation of the cookies. + * @param cookies The cookies + * @return The string representation. + */ + private static String getCookiesStringRepresentation(final List cookies) { + StringBuffer sbResult = new StringBuffer(); + Iterator iter = cookies.iterator(); + while (iter.hasNext()) { + Cookie ck = (Cookie) iter.next(); + if (sbResult.length() > 0) { + sbResult.append("#"); + } + sbResult.append(ck.toExternalForm()); + } + return sbResult.toString(); + } + + /** + * Clears all credentials. + */ + public void clearCredentials() { + this.credMap.clear(); + } + + /** + * Clears all proxy credentials. + */ + public void clearProxyCredentials() { + this.proxyCred.clear(); + } + + /** + * Clears all cookies. + */ + public void clearCookies() { + this.cookies.clear(); + } + + /** + * Clears the state information (all cookies, credentials and proxy credentials). + */ + public void clear() { + clearCookies(); + clearCredentials(); + clearProxyCredentials(); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpStatus.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpStatus.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpStatus.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,311 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpStatus.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * Constants enumerating the HTTP status codes. + * All status codes defined in RFC1945 (HTTP/1.0, RFC2616 (HTTP/1.1), and + * RFC2518 (WebDAV) are supported. + * + * @see StatusLine + * @author Unascribed + * @author Mike Bowler + * @author Jeff Dever + * + * TODO: Internationalization of reason phrases + * + * @version $Id: HttpStatus.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + */ +public class HttpStatus { + + + // -------------------------------------------------------- Class Variables + + /** Reason phrases lookup table. */ + private static final String[][] REASON_PHRASES = new String[][]{ + new String[0], + new String[3], + new String[8], + new String[8], + new String[25], + new String[8] + }; + + + // --------------------------------------------------------- Public Methods + + /** + * Get the reason phrase for a particular status code. + * + * This method always returns the English text as specified in the + * relevent RFCs and is not internationalized. + * + * @param statusCode the numeric status code + * @return the reason phrase associated with the given status code + * or null if the status code is not recognized. + * + * TODO: getStatusText should be called getReasonPhrase to match RFC + */ + public static String getStatusText(int statusCode) { + + if (statusCode < 0) { + throw new IllegalArgumentException("status code may not be negative"); + } + int classIndex = statusCode / 100; + int codeIndex = statusCode - classIndex * 100; + if (classIndex < 1 || classIndex > (REASON_PHRASES.length - 1) + || codeIndex < 0 || codeIndex > (REASON_PHRASES[classIndex].length - 1)) { + return null; + } + return REASON_PHRASES[classIndex][codeIndex]; + } + + + // -------------------------------------------------------- Private Methods + + /** + * Store the given reason phrase, by status code. + * @param statusCode The status code to lookup + * @param reasonPhrase The reason phrase for this status code + */ + private static void addStatusCodeMap(int statusCode, String reasonPhrase) { + int classIndex = statusCode / 100; + REASON_PHRASES[classIndex][statusCode - classIndex * 100] = reasonPhrase; + } + + + // -------------------------------------------------------------- Constants + + // --- 1xx Informational --- + + /** 100 Continue (HTTP/1.1 - RFC 2616) */ + public static final int SC_CONTINUE = 100; + /** 101 Switching Protocols (HTTP/1.1 - RFC 2616)*/ + public static final int SC_SWITCHING_PROTOCOLS = 101; + /** 102 Processing (WebDAV - RFC 2518) */ + public static final int SC_PROCESSING = 102; + + // --- 2xx Success --- + + /** 200 OK (HTTP/1.0 - RFC 1945) */ + public static final int SC_OK = 200; + /** 201 Created (HTTP/1.0 - RFC 1945) */ + public static final int SC_CREATED = 201; + /** 202 Accepted (HTTP/1.0 - RFC 1945) */ + public static final int SC_ACCEPTED = 202; + /** 203 Non Authoritative Information (HTTP/1.1 - RFC 2616) */ + public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203; + /** 204 No Content (HTTP/1.0 - RFC 1945) */ + public static final int SC_NO_CONTENT = 204; + /** 205 Reset Content (HTTP/1.1 - RFC 2616) */ + public static final int SC_RESET_CONTENT = 205; + /** 206 Partial Content (HTTP/1.1 - RFC 2616) */ + public static final int SC_PARTIAL_CONTENT = 206; + /** + * 207 Multi-Status (WebDAV - RFC 2518) or 207 Partial Update + * OK (HTTP/1.1 - draft-ietf-http-v11-spec-rev-01?) + */ + public static final int SC_MULTI_STATUS = 207; + + // --- 3xx Redirection --- + + /** 300 Mutliple Choices (HTTP/1.1 - RFC 2616) */ + public static final int SC_MULTIPLE_CHOICES = 300; + /** 301 Moved Permanently (HTTP/1.0 - RFC 1945) */ + public static final int SC_MOVED_PERMANENTLY = 301; + /** 302 Moved Temporarily (Sometimes Found) (HTTP/1.0 - RFC 1945) */ + public static final int SC_MOVED_TEMPORARILY = 302; + /** 303 See Other (HTTP/1.1 - RFC 2616) */ + public static final int SC_SEE_OTHER = 303; + /** 304 Not Modified (HTTP/1.0 - RFC 1945) */ + public static final int SC_NOT_MODIFIED = 304; + /** 305 Use Proxy (HTTP/1.1 - RFC 2616) */ + public static final int SC_USE_PROXY = 305; + /** 307 Temporary Redirect (HTTP/1.1 - RFC 2616) */ + public static final int SC_TEMPORARY_REDIRECT = 307; + + // --- 4xx Client Error --- + + /** 400 Bad Request (HTTP/1.1 - RFC 2616) */ + public static final int SC_BAD_REQUEST = 400; + /** 401 Unauthorized (HTTP/1.0 - RFC 1945) */ + public static final int SC_UNAUTHORIZED = 401; + /** 402 Payment Required (HTTP/1.1 - RFC 2616) */ + public static final int SC_PAYMENT_REQUIRED = 402; + /** 403 Forbidden (HTTP/1.0 - RFC 1945) */ + public static final int SC_FORBIDDEN = 403; + /** 404 Not Found (HTTP/1.0 - RFC 1945) */ + public static final int SC_NOT_FOUND = 404; + /** 405 Method Not Allowed (HTTP/1.1 - RFC 2616) */ + public static final int SC_METHOD_NOT_ALLOWED = 405; + /** 406 Not Acceptable (HTTP/1.1 - RFC 2616) */ + public static final int SC_NOT_ACCEPTABLE = 406; + /** 407 Proxy Authentication Required (HTTP/1.1 - RFC 2616)*/ + public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407; + /** 408 Request Timeout (HTTP/1.1 - RFC 2616) */ + public static final int SC_REQUEST_TIMEOUT = 408; + /** 409 Conflict (HTTP/1.1 - RFC 2616) */ + public static final int SC_CONFLICT = 409; + /** 410 Gone (HTTP/1.1 - RFC 2616) */ + public static final int SC_GONE = 410; + /** 411 Length Required (HTTP/1.1 - RFC 2616) */ + public static final int SC_LENGTH_REQUIRED = 411; + /** 412 Precondition Failed (HTTP/1.1 - RFC 2616) */ + public static final int SC_PRECONDITION_FAILED = 412; + /** 413 Request Entity Too Large (HTTP/1.1 - RFC 2616) */ + public static final int SC_REQUEST_TOO_LONG = 413; + /** 414 Request-URI Too Long (HTTP/1.1 - RFC 2616) */ + public static final int SC_REQUEST_URI_TOO_LONG = 414; + /** 415 Unsupported Media Type (HTTP/1.1 - RFC 2616) */ + public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; + /** 416 Requested Range Not Satisfiable (HTTP/1.1 - RFC 2616) */ + public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; + /** 417 Expectation Failed (HTTP/1.1 - RFC 2616) */ + public static final int SC_EXPECTATION_FAILED = 417; + + /** + * Static constant for a 418 error. + * 418 Unprocessable Entity (WebDAV drafts?) + * or 418 Reauthentication Required (HTTP/1.1 drafts?) + */ + // not used + // public static final int SC_UNPROCESSABLE_ENTITY = 418; + + /** + * Static constant for a 419 error. + * 419 Insufficient Space on Resource + * (WebDAV - draft-ietf-webdav-protocol-05?) + * or 419 Proxy Reauthentication Required + * (HTTP/1.1 drafts?) + */ + public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419; + /** + * Static constant for a 420 error. + * 420 Method Failure + * (WebDAV - draft-ietf-webdav-protocol-05?) + */ + public static final int SC_METHOD_FAILURE = 420; + /** 422 Unprocessable Entity (WebDAV - RFC 2518) */ + public static final int SC_UNPROCESSABLE_ENTITY = 422; + /** 423 Locked (WebDAV - RFC 2518) */ + public static final int SC_LOCKED = 423; + /** 424 Failed Dependency (WebDAV - RFC 2518) */ + public static final int SC_FAILED_DEPENDENCY = 424; + + // --- 5xx Server Error --- + + /** 500 Server Error (HTTP/1.0 - RFC 1945) */ + public static final int SC_INTERNAL_SERVER_ERROR = 500; + /** 501 Not Implemented (HTTP/1.0 - RFC 1945) */ + public static final int SC_NOT_IMPLEMENTED = 501; + /** 502 Bad Gateway (HTTP/1.0 - RFC 1945) */ + public static final int SC_BAD_GATEWAY = 502; + /** 503 Service Unavailable (HTTP/1.0 - RFC 1945) */ + public static final int SC_SERVICE_UNAVAILABLE = 503; + /** 504 Gateway Timeout (HTTP/1.1 - RFC 2616) */ + public static final int SC_GATEWAY_TIMEOUT = 504; + /** 505 HTTP Version Not Supported (HTTP/1.1 - RFC 2616) */ + public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505; + + /** 507 Insufficient Storage (WebDAV - RFC 2518) */ + public static final int SC_INSUFFICIENT_STORAGE = 507; + + + // ----------------------------------------------------- Static Initializer + + /** Set up status code to "reason phrase" map. */ + static { + // HTTP 1.0 Server status codes -- see RFC 1945 + addStatusCodeMap(SC_OK, "OK"); + addStatusCodeMap(SC_CREATED, "Created"); + addStatusCodeMap(SC_ACCEPTED, "Accepted"); + addStatusCodeMap(SC_NO_CONTENT, "No Content"); + addStatusCodeMap(SC_MOVED_PERMANENTLY, "Moved Permanently"); + addStatusCodeMap(SC_MOVED_TEMPORARILY, "Moved Temporarily"); + addStatusCodeMap(SC_NOT_MODIFIED, "Not Modified"); + addStatusCodeMap(SC_BAD_REQUEST, "Bad Request"); + addStatusCodeMap(SC_UNAUTHORIZED, "Unauthorized"); + addStatusCodeMap(SC_FORBIDDEN, "Forbidden"); + addStatusCodeMap(SC_NOT_FOUND, "Not Found"); + addStatusCodeMap(SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); + addStatusCodeMap(SC_NOT_IMPLEMENTED, "Not Implemented"); + addStatusCodeMap(SC_BAD_GATEWAY, "Bad Gateway"); + addStatusCodeMap(SC_SERVICE_UNAVAILABLE, "Service Unavailable"); + + // HTTP 1.1 Server status codes -- see RFC 2048 + addStatusCodeMap(SC_CONTINUE, "Continue"); + addStatusCodeMap(SC_TEMPORARY_REDIRECT, "Temporary Redirect"); + addStatusCodeMap(SC_METHOD_NOT_ALLOWED, "Method Not Allowed"); + addStatusCodeMap(SC_CONFLICT, "Conflict"); + addStatusCodeMap(SC_PRECONDITION_FAILED, "Precondition Failed"); + addStatusCodeMap(SC_REQUEST_TOO_LONG, "Request Too Long"); + addStatusCodeMap(SC_REQUEST_URI_TOO_LONG, "Request-URI Too Long"); + addStatusCodeMap(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type"); + addStatusCodeMap(SC_MULTIPLE_CHOICES, "Multiple Choices"); + addStatusCodeMap(SC_SEE_OTHER, "See Other"); + addStatusCodeMap(SC_USE_PROXY, "Use Proxy"); + addStatusCodeMap(SC_PAYMENT_REQUIRED, "Payment Required"); + addStatusCodeMap(SC_NOT_ACCEPTABLE, "Not Acceptable"); + addStatusCodeMap(SC_PROXY_AUTHENTICATION_REQUIRED, + "Proxy Authentication Required"); + addStatusCodeMap(SC_REQUEST_TIMEOUT, + "Request Timeout"); + + addStatusCodeMap(SC_SWITCHING_PROTOCOLS, "Switching Protocols"); + addStatusCodeMap(SC_NON_AUTHORITATIVE_INFORMATION, + "Non Authoritative Information"); + addStatusCodeMap(SC_RESET_CONTENT, "Reset Content"); + addStatusCodeMap(SC_PARTIAL_CONTENT, "Partial Content"); + addStatusCodeMap(SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + addStatusCodeMap(SC_HTTP_VERSION_NOT_SUPPORTED, + "Http Version Not Supported"); + addStatusCodeMap(SC_GONE, + "Gone"); + addStatusCodeMap(SC_LENGTH_REQUIRED, + "Length Required"); + addStatusCodeMap(SC_REQUESTED_RANGE_NOT_SATISFIABLE, + "Requested Range Not Satisfiable"); + addStatusCodeMap(SC_EXPECTATION_FAILED, + "Expectation Failed"); + + // WebDAV Server-specific status codes + addStatusCodeMap(SC_PROCESSING, "Processing"); + addStatusCodeMap(SC_MULTI_STATUS, "Multi-Status"); + addStatusCodeMap(SC_UNPROCESSABLE_ENTITY, "Unprocessable Entity"); + addStatusCodeMap(SC_INSUFFICIENT_SPACE_ON_RESOURCE, + "Insufficient Space On Resource"); + addStatusCodeMap(SC_METHOD_FAILURE, "Method Failure"); + addStatusCodeMap(SC_LOCKED, "Locked"); + addStatusCodeMap(SC_INSUFFICIENT_STORAGE , "Insufficient Storage"); + addStatusCodeMap(SC_FAILED_DEPENDENCY, "Failed Dependency"); + } + + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpURL.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpURL.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpURL.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,832 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpURL.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.util.URIUtil; + +/** + * The HTTP URL. + * + * @author Sung-Gu + * @author Mike Bowler + */ +public class HttpURL extends URI { + + // ----------------------------------------------------------- Constructors + + /** Create an instance as an internal use. */ + protected HttpURL() { + } + + + /** + * Construct a HTTP URL as an escaped form of a character array with the + * given charset to do escape encoding. + * + * @param escaped the HTTP URL character sequence + * @param charset the charset string to do escape encoding + * @throws URIException If {@link #checkValid()} fails + * @throws NullPointerException if escaped is null + * @see #getProtocolCharset + */ + public HttpURL(char[] escaped, String charset) + throws URIException, NullPointerException { + protocolCharset = charset; + parseUriReference(new String(escaped), true); + checkValid(); + } + + + /** + * Construct a HTTP URL as an escaped form of a character array. + * + * @param escaped the HTTP URL character sequence + * @throws URIException If {@link #checkValid()} fails + * @throws NullPointerException if escaped is null + * @see #getDefaultProtocolCharset + */ + public HttpURL(char[] escaped) throws URIException, NullPointerException { + parseUriReference(new String(escaped), true); + checkValid(); + } + + + /** + * Construct a HTTP URL from a given string with the given charset to do + * escape encoding. + * + * @param original the HTTP URL string + * @param charset the charset string to do escape encoding + * @throws URIException If {@link #checkValid()} fails + * @see #getProtocolCharset + */ + public HttpURL(String original, String charset) throws URIException { + protocolCharset = charset; + parseUriReference(original, false); + checkValid(); + } + + + /** + * Construct a HTTP URL from a given string. + * + * @param original the HTTP URL string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String original) throws URIException { + parseUriReference(original, false); + checkValid(); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param host the host string + * @param port the port number + * @param path the path string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String host, int port, String path) throws URIException { + this(null, null, host, port, path, null, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String host, int port, String path, String query) + throws URIException { + + this(null, null, host, port, path, query, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String user, String password, String host) + throws URIException { + + this(user, password, host, -1, null, null, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String user, String password, String host, int port) + throws URIException { + + this(user, password, host, port, null, null, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @param path the path string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String user, String password, String host, int port, + String path) throws URIException { + + this(user, password, host, port, path, null, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @param path the path string + * @param query The query string. + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String user, String password, String host, int port, + String path, String query) throws URIException { + + this(user, password, host, port, path, query, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param host the host string + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String host, String path, String query, String fragment) + throws URIException { + + this(null, null, host, -1, path, query, fragment); + } + + + /** + * Construct a HTTP URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String userinfo, String host, String path, String query, + String fragment) throws URIException { + + this(userinfo, host, -1, path, query, fragment); + } + + + /** + * Construct a HTTP URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param port the port number + * @param path the path string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String userinfo, String host, int port, String path) + throws URIException { + + this(userinfo, host, port, path, null, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String userinfo, String host, int port, String path, + String query) throws URIException { + + this(userinfo, host, port, path, query, null); + } + + + /** + * Construct a HTTP URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String userinfo, String host, int port, String path, + String query, String fragment) throws URIException { + + // validate and contruct the URI character sequence + StringBuffer buff = new StringBuffer(); + if (userinfo != null || host != null || port != -1) { + _scheme = DEFAULT_SCHEME; // in order to verify the own protocol + buff.append(_default_scheme); + buff.append("://"); + if (userinfo != null) { + buff.append(userinfo); + buff.append('@'); + } + if (host != null) { + buff.append(URIUtil.encode(host, URI.allowed_host)); + if (port != -1 || port != DEFAULT_PORT) { + buff.append(':'); + buff.append(port); + } + } + } + if (path != null) { // accept empty path + if (scheme != null && !path.startsWith("/")) { + throw new URIException(URIException.PARSING, + "abs_path requested"); + } + buff.append(URIUtil.encode(path, URI.allowed_abs_path)); + } + if (query != null) { + buff.append('?'); + buff.append(URIUtil.encode(query, URI.allowed_query)); + } + if (fragment != null) { + buff.append('#'); + buff.append(URIUtil.encode(fragment, URI.allowed_fragment)); + } + parseUriReference(buff.toString(), true); + checkValid(); + } + + + /** + * Construct a HTTP URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpURL(String user, String password, String host, int port, + String path, String query, String fragment) throws URIException { + this(toUserinfo(user, password), host, port, path, query, fragment); + } + + protected static String toUserinfo(String user, String password) throws URIException { + if (user == null) return null; + StringBuffer usrinfo = new StringBuffer(20); //sufficient for real world + usrinfo.append(URIUtil.encode(user, URI.allowed_within_userinfo)); + if (password == null) return usrinfo.toString(); + usrinfo.append(':'); + usrinfo.append(URIUtil.encode(password, URI.allowed_within_userinfo)); + return usrinfo.toString(); + } + + + /** + * Construct a HTTP URL with a given relative URL string. + * + * @param base the base HttpURL + * @param relative the relative HTTP URL string + * @throws URIException If {@link #checkValid()} fails + */ + public HttpURL(HttpURL base, String relative) throws URIException { + this(base, new HttpURL(relative)); + } + + + /** + * Construct a HTTP URL with a given relative URL. + * + * @param base the base HttpURL + * @param relative the relative HttpURL + * @throws URIException If {@link #checkValid()} fails + */ + public HttpURL(HttpURL base, HttpURL relative) throws URIException { + super(base, relative); + checkValid(); + } + + // -------------------------------------------------------------- Constants + + /** + * Default scheme for HTTP URL. + */ + public static final char[] DEFAULT_SCHEME = { 'h', 't', 't', 'p' }; + + /** + * Default scheme for HTTP URL. + * @deprecated Use {@link #DEFAULT_SCHEME} instead. This one doesn't + * conform to the project naming conventions. + */ + public static final char[] _default_scheme = DEFAULT_SCHEME; + + /** + * Default port for HTTP URL. + */ + public static final int DEFAULT_PORT = 80; + + /** + * Default port for HTTP URL. + * @deprecated Use {@link #DEFAULT_PORT} instead. This one doesn't conform + * to the project naming conventions. + */ + public static final int _default_port = DEFAULT_PORT; + + /** + * The serialVersionUID. + */ + static final long serialVersionUID = -7158031098595039459L; + + // ------------------------------------------------------------- The scheme + + /** + * Get the scheme. You can get the scheme explicitly. + * + * @return the scheme + */ + public char[] getRawScheme() { + return (_scheme == null) ? null : HttpURL.DEFAULT_SCHEME; + } + + + /** + * Get the scheme. You can get the scheme explicitly. + * + * @return the scheme null if empty or undefined + */ + public String getScheme() { + return (_scheme == null) ? null : new String(HttpURL.DEFAULT_SCHEME); + } + + // --------------------------------------------------------------- The port + + /** + * Get the port number. + * @return the port number + */ + public int getPort() { + return (_port == -1) ? HttpURL.DEFAULT_PORT : _port; + } + + // ----------------------------------------------------------- The userinfo + + /** + * Set the raw-escaped user and password. + * + * @param escapedUser the raw-escaped user + * @param escapedPassword the raw-escaped password; could be null + * @throws URIException escaped user not valid or user required; escaped + * password not valid or username missed + */ + public void setRawUserinfo(char[] escapedUser, char[] escapedPassword) + throws URIException { + + if (escapedUser == null || escapedUser.length == 0) { + throw new URIException(URIException.PARSING, "user required"); + } + if (!validate(escapedUser, within_userinfo) + || ((escapedPassword != null) + && !validate(escapedPassword, within_userinfo))) { + throw new URIException(URIException.ESCAPING, + "escaped userinfo not valid"); + } + String username = new String(escapedUser); + String password = (escapedPassword == null) + ? null : new String(escapedPassword); + String userinfo = username + ((password == null) ? "" : ":" + password); + String hostname = new String(getRawHost()); + String hostport = (_port == -1) ? hostname : hostname + ":" + _port; + String authority = userinfo + "@" + hostport; + _userinfo = userinfo.toCharArray(); + _authority = authority.toCharArray(); + setURI(); + } + + + /** + * Set the raw-escaped user and password. + * + * @param escapedUser the escaped user + * @param escapedPassword the escaped password; could be null + * @throws URIException escaped user not valid or user required; escaped + * password not valid or username missed + * @throws NullPointerException null user + */ + public void setEscapedUserinfo(String escapedUser, String escapedPassword) + throws URIException, NullPointerException { + + setRawUserinfo(escapedUser.toCharArray(), (escapedPassword == null) + ? null : escapedPassword.toCharArray()); + } + + + /** + * Set the user and password. + * + * @param user the user + * @param password the password; could be null + * @throws URIException encoding error or username missed + * @throws NullPointerException null user + */ + public void setUserinfo(String user, String password) + throws URIException, NullPointerException { + // set the charset to do escape encoding + String charset = getProtocolCharset(); + setRawUserinfo(encode(user, within_userinfo, charset), + (password == null) + ? null + : encode(password, within_userinfo, charset)); + } + + + /** + * Set the raw-escaped user. + * + * @param escapedUser the raw-escaped user + * @throws URIException escaped user not valid or user required + */ + public void setRawUser(char[] escapedUser) throws URIException { + if (escapedUser == null || escapedUser.length == 0) { + throw new URIException(URIException.PARSING, "user required"); + } + if (!validate(escapedUser, within_userinfo)) { + throw new URIException(URIException.ESCAPING, + "escaped user not valid"); + } + String username = new String(escapedUser); + String password = new String(getRawPassword()); + String userinfo = username + ((password == null) ? "" : ":" + password); + String hostname = new String(getRawHost()); + String hostport = (_port == -1) ? hostname : hostname + ":" + _port; + String authority = userinfo + "@" + hostport; + _userinfo = userinfo.toCharArray(); + _authority = authority.toCharArray(); + setURI(); + } + + + /** + * Set the escaped user string. + * + * @param escapedUser the escaped user string + * @throws URIException escaped user not valid + * @throws NullPointerException null user + */ + public void setEscapedUser(String escapedUser) + throws URIException, NullPointerException { + setRawUser(escapedUser.toCharArray()); + } + + + /** + * Set the user string. + * + * @param user the user string + * @throws URIException user encoding error + * @throws NullPointerException null user + */ + public void setUser(String user) throws URIException, NullPointerException { + setRawUser(encode(user, allowed_within_userinfo, getProtocolCharset())); + } + + + /** + * Get the raw-escaped user. + * + * @return the raw-escaped user + */ + public char[] getRawUser() { + if (_userinfo == null || _userinfo.length == 0) { + return null; + } + int to = indexFirstOf(_userinfo, ':'); + // String.indexOf(':', 0, _userinfo.length, _userinfo, 0, 1, 0); + if (to == -1) { + return _userinfo; // only user. + } + char[] result = new char[to]; + System.arraycopy(_userinfo, 0, result, 0, to); + return result; + } + + + /** + * Get the escaped user + * + * @return the escaped user + */ + public String getEscapedUser() { + char[] user = getRawUser(); + return (user == null) ? null : new String(user); + } + + + /** + * Get the user. + * + * @return the user name + * @throws URIException If {@link #decode} fails + */ + public String getUser() throws URIException { + char[] user = getRawUser(); + return (user == null) ? null : decode(user, getProtocolCharset()); + } + + + /** + * Set the raw-escaped password. + * + * @param escapedPassword the raw-escaped password; could be null + * @throws URIException escaped password not valid or username missed + */ + public void setRawPassword(char[] escapedPassword) throws URIException { + if (escapedPassword != null + && !validate(escapedPassword, within_userinfo)) { + throw new URIException(URIException.ESCAPING, + "escaped password not valid"); + } + if (getRawUser() == null || getRawUser().length == 0) { + throw new URIException(URIException.PARSING, "username required"); + } + String username = new String(getRawUser()); + String password = new String(escapedPassword); + // an emtpy string is allowed as a password + String userinfo = username + ((password == null) ? "" : ":" + password); + String hostname = new String(getRawHost()); + String hostport = (_port == -1) ? hostname : hostname + ":" + _port; + String authority = userinfo + "@" + hostport; + _userinfo = userinfo.toCharArray(); + _authority = authority.toCharArray(); + setURI(); + } + + + /** + * Set the escaped password string. + * + * @param escapedPassword the escaped password string; could be null + * @throws URIException escaped password not valid or username missed + */ + public void setEscapedPassword(String escapedPassword) throws URIException { + setRawPassword((escapedPassword == null) ? null + : escapedPassword.toCharArray()); + } + + + /** + * Set the password string. + * + * @param password the password string; could be null + * @throws URIException encoding error or username missed + */ + public void setPassword(String password) throws URIException { + setRawPassword((password == null) ? null : encode(password, + allowed_within_userinfo, getProtocolCharset())); + } + + + /** + * Get the raw-escaped password. + * + * @return the raw-escaped password + */ + public char[] getRawPassword() { + int from = indexFirstOf(_userinfo, ':'); + if (from == -1) { + return null; // null or only user. + } + int len = _userinfo.length - from - 1; + char[] result = new char[len]; + System.arraycopy(_userinfo, from + 1, result, 0, len); + return result; + } + + + /** + * Get the escaped password. + * + * @return the escaped password + */ + public String getEscapedPassword() { + char[] password = getRawPassword(); + return (password == null) ? null : new String(password); + } + + + /** + * Get the password. + * + * @return the password + * @throws URIException If {@link #decode(char[],String)} fails. + */ + public String getPassword() throws URIException { + char[] password = getRawPassword(); + return (password == null) ? null : decode(password, + getProtocolCharset()); + } + + // --------------------------------------------------------------- The path + + /** + * Get the raw-escaped current hierarchy level. + * + * @return the raw-escaped current hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + */ + public char[] getRawCurrentHierPath() throws URIException { + return (_path == null || _path.length == 0) ? rootPath + : super.getRawCurrentHierPath(_path); + } + + + /** + * Get the level above the this hierarchy level. + * + * @return the raw above hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + */ + public char[] getRawAboveHierPath() throws URIException { + char[] path = getRawCurrentHierPath(); + return (path == null || path.length == 0) ? rootPath : getRawCurrentHierPath(path); + } + + + /** + * Get the raw escaped path. + * + * @return the path '/' if empty or undefined + */ + public char[] getRawPath() { + char[] path = super.getRawPath(); + return (path == null || path.length == 0) ? rootPath : path; + } + + // -------------------------------------------------------------- The query + + /** + * Set the query as the name and value pair. + * + * @param queryName the query string. + * @param queryValue the query string. + * @throws URIException incomplete trailing escape pattern + * Or unsupported character encoding + * @throws NullPointerException null query + * @see #encode + */ + public void setQuery(String queryName, String queryValue) + throws URIException, NullPointerException { + + StringBuffer buff = new StringBuffer(); + // set the charset to do escape encoding + String charset = getProtocolCharset(); + buff.append(encode(queryName, allowed_within_query, charset)); + buff.append('='); + buff.append(encode(queryValue, allowed_within_query, charset)); + _query = buff.toString().toCharArray(); + setURI(); + } + + + /** + * Set the query as the name and value pairs. + * + * @param queryName the array of the query string. + * @param queryValue the array of the query string. + * @throws URIException incomplete trailing escape pattern, + * unsupported character encoding or wrong array size + * @throws NullPointerException null query + * @see #encode + */ + public void setQuery(String[] queryName, String[] queryValue) + throws URIException, NullPointerException { + + int length = queryName.length; + if (length != queryValue.length) { + throw new URIException("wrong array size of query"); + } + + StringBuffer buff = new StringBuffer(); + // set the charset to do escape encoding + String charset = getProtocolCharset(); + for (int i = 0; i < length; i++) { + buff.append(encode(queryName[i], allowed_within_query, charset)); + buff.append('='); + buff.append(encode(queryValue[i], allowed_within_query, charset)); + if (i + 1 < length) { + buff.append('&'); + } + } + _query = buff.toString().toCharArray(); + setURI(); + } + + // ---------------------------------------------------------------- Utility + + /** + * Verify the valid class use for construction. + * + * @throws URIException the wrong scheme use + */ + protected void checkValid() throws URIException { + // could be explicit protocol or undefined. + if (!(equals(_scheme, DEFAULT_SCHEME) || _scheme == null)) { + throw new URIException(URIException.PARSING, "wrong class use"); + } + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpVersion.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpVersion.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpVersion.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,248 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpVersion.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + *

HTTP version, as specified in RFC 2616.

+ *

+ * HTTP uses a "<major>.<minor>" numbering scheme to indicate + * versions of the protocol. The protocol versioning policy is intended to + * allow the sender to indicate the format of a message and its capacity for + * understanding further HTTP communication, rather than the features + * obtained via that communication. No change is made to the version + * number for the addition of message components which do not affect + * communication behavior or which only add to extensible field values. + * The <minor> number is incremented when the changes made to the + * protocol add features which do not change the general message parsing + * algorithm, but which may add to the message semantics and imply + * additional capabilities of the sender. The <major> number is + * incremented when the format of a message within the protocol is + * changed. See RFC 2145 [36] for a fuller explanation. + *

+ *

+ * The version of an HTTP message is indicated by an HTTP-Version field + * in the first line of the message. + *

+ *
+ *     HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+ *  
+ *

+ * Note that the major and minor numbers MUST be treated as separate + * integers and that each MAY be incremented higher than a single digit. + * Thus, HTTP/2.4 is a lower version than HTTP/2.13, which in turn is + * lower than HTTP/12.3. Leading zeros MUST be ignored by recipients and + * MUST NOT be sent. + *

+ * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:34 $ + * + * @since 3.0 + */ +public class HttpVersion implements Comparable { + + /** Major version number of the HTTP protocol */ + private int major = 0; + + /** Minor version number of the HTTP protocol */ + private int minor = 0; + + /** HTTP protocol version 0.9 */ + public static final HttpVersion HTTP_0_9 = new HttpVersion(0, 9); + + /** HTTP protocol version 1.0 */ + public static final HttpVersion HTTP_1_0 = new HttpVersion(1, 0); + + /** HTTP protocol version 1.1 */ + public static final HttpVersion HTTP_1_1 = new HttpVersion(1, 1); + + /** + * Create an HTTP protocol version designator. + * + * @param major the major version number of the HTTP protocol + * @param minor the minor version number of the HTTP protocol + * + * @throws IllegalArgumentException if either major or minor version number is negative + */ + public HttpVersion(int major, int minor) { + if (major < 0) { + throw new IllegalArgumentException("HTTP major version number may not be negative"); + } + this.major = major; + if (minor < 0) { + throw new IllegalArgumentException("HTTP minor version number may not be negative"); + } + this.minor = minor; + } + + /** + * Returns the major version number of the HTTP protocol. + * + * @return the major version number. + */ + public int getMajor() { + return major; + } + + /** + * Returns the minor version number of the HTTP protocol. + * + * @return the minor version number. + */ + public int getMinor() { + return minor; + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.major * 100000 + this.minor; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof HttpVersion)) { + return false; + } + return equals((HttpVersion)obj); + } + + /** + * Compares this HTTP protocol version with another one. + * + * @param anotherVer the version to be compared with. + * + * @return a negative integer, zero, or a positive integer as this version is less than, + * equal to, or greater than the specified version. + */ + public int compareTo(HttpVersion anotherVer) { + if (anotherVer == null) { + throw new IllegalArgumentException("Version parameter may not be null"); + } + int delta = getMajor() - anotherVer.getMajor(); + if (delta == 0) { + delta = getMinor() - anotherVer.getMinor(); + } + return delta; + } + + /** + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Object o) { + return compareTo((HttpVersion)o); + } + + /** + * Test if the HTTP protocol version is equal to the given number. + * + * @return true if HTTP protocol version is given to the given number, + * false otherwise. + */ + public boolean equals(HttpVersion version) { + return compareTo(version) == 0; + } + + /** + * Test if the HTTP protocol version is greater or equal to the given number. + * + * @return true if HTTP protocol version is greater or equal given to the + * given number, false otherwise. + */ + public boolean greaterEquals(HttpVersion version) { + return compareTo(version) >= 0; + } + + /** + * Test if the HTTP protocol version is less or equal to the given number. + * + * @return true if HTTP protocol version is less or equal to given to the + * given number, false otherwise. + */ + public boolean lessEquals(HttpVersion version) { + return compareTo(version) <= 0; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("HTTP/"); + buffer.append(this.major); + buffer.append('.'); + buffer.append(this.minor); + return buffer.toString(); + } + + /** + * Parses the textual representation of the given HTTP protocol version. + * + * @return HTTP protocol version. + * + * @throws ProtocolException if the string is not a valid HTTP protocol version. + */ + public static HttpVersion parse(final String s) throws ProtocolException { + if (s == null) { + throw new IllegalArgumentException("String may not be null"); + } + if (!s.startsWith("HTTP/")) { + throw new ProtocolException("Invalid HTTP version string: " + s); + } + int major, minor; + + int i1 = "HTTP/".length(); + int i2 = s.indexOf(".", i1); + if (i2 == -1) { + throw new ProtocolException("Invalid HTTP version number: " + s); + } + try { + major = Integer.parseInt(s.substring(i1, i2)); + } catch (NumberFormatException e) { + throw new ProtocolException("Invalid HTTP major version number: " + s); + } + i1 = i2 + 1; + i2 = s.length(); + try { + minor = Integer.parseInt(s.substring(i1, i2)); + } catch (NumberFormatException e) { + throw new ProtocolException("Invalid HTTP minor version number: " + s); + } + return new HttpVersion(major, minor); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpsURL.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpsURL.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpsURL.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,472 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/HttpsURL.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.util.URIUtil; + +/** + * The HTTPS URL. + * + * @author Sung-Gu + * @author Mike Bowler + */ +public class HttpsURL extends HttpURL { + + // ----------------------------------------------------------- Constructors + + /** + * Create an instance as an internal use. + */ + protected HttpsURL() { + } + + + /** + * Construct a HTTPS URL as an escaped form of a character array with the + * given charset to do escape encoding. + * + * @param escaped the HTTPS URL character sequence + * @param charset the charset to do escape encoding + * @throws URIException If {@link #checkValid()} fails + * @throws NullPointerException if escaped is null + * @see #getProtocolCharset + */ + public HttpsURL(char[] escaped, String charset) + throws URIException, NullPointerException { + protocolCharset = charset; + parseUriReference(new String(escaped), true); + checkValid(); + } + + + /** + * Construct a HTTPS URL as an escaped form of a character array. + * + * @param escaped the HTTPS URL character sequence + * @throws URIException If {@link #checkValid()} fails + * @throws NullPointerException if escaped is null + * @see #getDefaultProtocolCharset + */ + public HttpsURL(char[] escaped) throws URIException, NullPointerException { + parseUriReference(new String(escaped), true); + checkValid(); + } + + + /** + * Construct a HTTPS URL from a given string with the given charset to do + * escape encoding. + * + * @param original the HTTPS URL string + * @param charset the charset to do escape encoding + * @throws URIException If {@link #checkValid()} fails + * @see #getProtocolCharset + */ + public HttpsURL(String original, String charset) throws URIException { + protocolCharset = charset; + parseUriReference(original, false); + checkValid(); + } + + + /** + * Construct a HTTPS URL from a given string. + * + * @param original the HTTPS URL string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String original) throws URIException { + parseUriReference(original, false); + checkValid(); + } + + + /** + * Construct a HTTPS URL from given components. + * + * @param host the host string + * @param port the port number + * @param path the path string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String host, int port, String path) throws URIException { + this(null, host, port, path, null, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String host, int port, String path, String query) + throws URIException { + + this(null, host, port, path, query, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String user, String password, String host) + throws URIException { + + this(user, password, host, -1, null, null, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String user, String password, String host, int port) + throws URIException { + + this(user, password, host, port, null, null, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @param path the path string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String user, String password, String host, int port, + String path) throws URIException { + + this(user, password, host, port, path, null, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @param path the path string + * @param query The query string. + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String user, String password, String host, int port, + String path, String query) throws URIException { + + this(user, password, host, port, path, query, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * @param host the host string + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String host, String path, String query, String fragment) + throws URIException { + + this(null, host, -1, path, query, fragment); + } + + + /** + * Construct a HTTPS URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String userinfo, String host, String path, String query, + String fragment) throws URIException { + + this(userinfo, host, -1, path, query, fragment); + } + + + /** + * Construct a HTTPS URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param port the port number + * @param path the path string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String userinfo, String host, int port, String path) + throws URIException { + + this(userinfo, host, port, path, null, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String userinfo, String host, int port, String path, + String query) throws URIException { + + this(userinfo, host, port, path, query, null); + } + + + /** + * Construct a HTTPS URL from given components. + * + * Note: The userinfo format is normally + * <username>:<password> where + * username and password must both be URL escaped. + * + * @param userinfo the userinfo string whose parts are URL escaped + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String userinfo, String host, int port, String path, + String query, String fragment) throws URIException { + + // validate and contruct the URI character sequence + StringBuffer buff = new StringBuffer(); + if (userinfo != null || host != null || port != -1) { + _scheme = DEFAULT_SCHEME; // in order to verify the own protocol + buff.append(_default_scheme); + buff.append("://"); + if (userinfo != null) { + buff.append(userinfo); + buff.append('@'); + } + if (host != null) { + buff.append(URIUtil.encode(host, URI.allowed_host)); + if (port != -1 || port != DEFAULT_PORT) { + buff.append(':'); + buff.append(port); + } + } + } + if (path != null) { // accept empty path + if (scheme != null && !path.startsWith("/")) { + throw new URIException(URIException.PARSING, + "abs_path requested"); + } + buff.append(URIUtil.encode(path, URI.allowed_abs_path)); + } + if (query != null) { + buff.append('?'); + buff.append(URIUtil.encode(query, URI.allowed_query)); + } + if (fragment != null) { + buff.append('#'); + buff.append(URIUtil.encode(fragment, URI.allowed_fragment)); + } + parseUriReference(buff.toString(), true); + checkValid(); + } + + /** + * Construct a HTTP URL from given components. + * + * @param user the user name + * @param password his or her password + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If {@link #checkValid()} fails + * @see #getDefaultProtocolCharset + */ + public HttpsURL(String user, String password, String host, int port, + String path, String query, String fragment) throws URIException { + this(HttpURL.toUserinfo(user, password), host, port, path, query, fragment); + } + + /** + * Construct a HTTPS URL with a given relative HTTPS URL string. + * + * @param base the base HttpsURL + * @param relative the relative HTTPS URL string + * @throws URIException If {@link #checkValid()} fails + */ + public HttpsURL(HttpsURL base, String relative) throws URIException { + this(base, new HttpsURL(relative)); + } + + + /** + * Construct a HTTPS URL with a given relative URL. + * + * @param base the base HttpsURL + * @param relative the relative HttpsURL + * @throws URIException If {@link #checkValid()} fails + */ + public HttpsURL(HttpsURL base, HttpsURL relative) throws URIException { + super(base, relative); + checkValid(); + } + + // -------------------------------------------------------------- Constants + + /** + * Default scheme for HTTPS URL. + */ + public static final char[] DEFAULT_SCHEME = { 'h', 't', 't', 'p', 's' }; + + /** + * Default scheme for HTTPS URL. + * @deprecated Use {@link #DEFAULT_SCHEME} instead. This one doesn't + * conform to the project naming conventions. + */ + public static final char[] _default_scheme = DEFAULT_SCHEME; + + + /** + * Default port for HTTPS URL. + */ + public static final int DEFAULT_PORT = 443; + + /** + * Default port for HTTPS URL. + * @deprecated Use {@link #DEFAULT_PORT} instead. This one doesn't conform + * to the project naming conventions. + */ + public static final int _default_port = DEFAULT_PORT; + + + /** + * The serialVersionUID. + */ + static final long serialVersionUID = 887844277028676648L; + + // ------------------------------------------------------------- The scheme + + /** + * Get the scheme. You can get the scheme explicitly. + * + * @return the scheme + */ + public char[] getRawScheme() { + return (_scheme == null) ? null : HttpsURL.DEFAULT_SCHEME; + } + + + /** + * Get the scheme. You can get the scheme explicitly. + * + * @return the scheme null if empty or undefined + */ + public String getScheme() { + return (_scheme == null) ? null : new String(HttpsURL.DEFAULT_SCHEME); + } + + // --------------------------------------------------------------- The port + + /** + * Get the port number. + * @return the port number + */ + public int getPort() { + return (_port == -1) ? HttpsURL.DEFAULT_PORT : _port; + } + + // ---------------------------------------------------------------- Utility + + /** + * Verify the valid class use for construction. + * + * @throws URIException the wrong scheme use + */ + protected void checkValid() throws URIException { + // could be explicit protocol or undefined. + if (!(equals(_scheme, DEFAULT_SCHEME) || _scheme == null)) { + throw new URIException(URIException.PARSING, "wrong class use"); + } + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MethodRetryHandler.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MethodRetryHandler.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MethodRetryHandler.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,67 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MethodRetryHandler.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * A handler for determining if an HttpMethod should be retried after a + * recoverable exception during execution. + * + * @see HttpMethod#execute(HttpState, HttpConnection) + * @see HttpRecoverableException + * + * @deprecated use {@link HttpMethodRetryHandler} + * + * @author Michael Becke + */ +public interface MethodRetryHandler { + + /** + * Determines if a method should be retried after an HttpRecoverableException + * occurs during execution. + * + * @param method the method being executed + * @param connection the connection the method is using + * @param recoverableException the exception that occurred + * @param executionCount the number of times this method has been + * unsuccessfully executed + * @param requestSent this argument is unused and will be removed in the future. + * {@link HttpMethod#isRequestSent()} should be used instead + * + * @return true if the method should be retried, false + * otherwise + */ + boolean retryMethod( + HttpMethod method, + HttpConnection connection, + HttpRecoverableException recoverableException, + int executionCount, + boolean requestSent); + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,1636 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.net.InetAddress; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.WeakHashMap; + +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.util.IdleConnectionHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Manages a set of HttpConnections for various HostConfigurations. + * + * @author Michael Becke + * @author Eric Johnson + * @author Mike Bowler + * @author Carl A. Dunham + * + * @since 2.0 + */ +public class MultiThreadedHttpConnectionManager implements HttpConnectionManager { + + // -------------------------------------------------------- Class Variables + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(MultiThreadedHttpConnectionManager.class); + + /** The default maximum number of connections allowed per host */ + public static final int DEFAULT_MAX_HOST_CONNECTIONS = 2; // Per RFC 2616 sec 8.1.4 + + /** The default maximum number of connections allowed overall */ + public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; + + /** + * A mapping from Reference to ConnectionSource. Used to reclaim resources when connections + * are lost to the garbage collector. + */ + private static final Map REFERENCE_TO_CONNECTION_SOURCE = new HashMap(); + + /** + * The reference queue used to track when HttpConnections are lost to the + * garbage collector + */ + private static final ReferenceQueue REFERENCE_QUEUE = new ReferenceQueue(); + + /** + * The thread responsible for handling lost connections. + */ + private static ReferenceQueueThread REFERENCE_QUEUE_THREAD; + + /** + * Holds references to all active instances of this class. + */ + private static WeakHashMap ALL_CONNECTION_MANAGERS = new WeakHashMap(); + + + // ---------------------------------------------------------- Class Methods + + /** + * Shuts down and cleans up resources used by all instances of + * MultiThreadedHttpConnectionManager. All static resources are released, all threads are + * stopped, and {@link #shutdown()} is called on all live instances of + * MultiThreadedHttpConnectionManager. + * + * @see #shutdown() + */ + public static void shutdownAll() { + + synchronized (REFERENCE_TO_CONNECTION_SOURCE) { + // shutdown all connection managers + synchronized (ALL_CONNECTION_MANAGERS) { + Iterator connIter = ALL_CONNECTION_MANAGERS.keySet().iterator(); + while (connIter.hasNext()) { + MultiThreadedHttpConnectionManager connManager = + (MultiThreadedHttpConnectionManager) connIter.next(); + connIter.remove(); + connManager.shutdown(); + } + } + + // shutdown static resources + if (REFERENCE_QUEUE_THREAD != null) { + REFERENCE_QUEUE_THREAD.shutdown(); + REFERENCE_QUEUE_THREAD = null; + } + REFERENCE_TO_CONNECTION_SOURCE.clear(); + } + } + + /** + * Stores the reference to the given connection along with the host config and connection pool. + * These values will be used to reclaim resources if the connection is lost to the garbage + * collector. This method should be called before a connection is released from the connection + * manager. + * + *

A static reference to the connection manager will also be stored. To ensure that + * the connection manager can be GCed {@link #removeReferenceToConnection(HttpConnection)} + * should be called for all connections that the connection manager is storing a reference + * to.

+ * + * @param connection the connection to create a reference for + * @param hostConfiguration the connection's host config + * @param connectionPool the connection pool that created the connection + * + * @see #removeReferenceToConnection(HttpConnection) + */ + private static void storeReferenceToConnection( + HttpConnectionWithReference connection, + HostConfiguration hostConfiguration, + ConnectionPool connectionPool + ) { + + ConnectionSource source = new ConnectionSource(); + source.connectionPool = connectionPool; + source.hostConfiguration = hostConfiguration; + + synchronized (REFERENCE_TO_CONNECTION_SOURCE) { + + // start the reference queue thread if needed + if (REFERENCE_QUEUE_THREAD == null) { + REFERENCE_QUEUE_THREAD = new ReferenceQueueThread(); + REFERENCE_QUEUE_THREAD.start(); + } + + REFERENCE_TO_CONNECTION_SOURCE.put( + connection.reference, + source + ); + } + } + + /** + * Closes and releases all connections currently checked out of the given connection pool. + * @param connectionPool the connection pool to shutdown the connections for + */ + private static void shutdownCheckedOutConnections(ConnectionPool connectionPool) { + + // keep a list of the connections to be closed + ArrayList connectionsToClose = new ArrayList(); + + synchronized (REFERENCE_TO_CONNECTION_SOURCE) { + + Iterator referenceIter = REFERENCE_TO_CONNECTION_SOURCE.keySet().iterator(); + while (referenceIter.hasNext()) { + Reference ref = (Reference) referenceIter.next(); + ConnectionSource source = + (ConnectionSource) REFERENCE_TO_CONNECTION_SOURCE.get(ref); + if (source.connectionPool == connectionPool) { + referenceIter.remove(); + HttpConnection connection = (HttpConnection) ref.get(); + if (connection != null) { + connectionsToClose.add(connection); + } + } + } + } + + // close and release the connections outside of the synchronized block to + // avoid holding the lock for too long + for (Iterator i = connectionsToClose.iterator(); i.hasNext();) { + HttpConnection connection = (HttpConnection) i.next(); + connection.close(); + // remove the reference to the connection manager. this ensures + // that the we don't accidentally end up here again + connection.setHttpConnectionManager(null); + connection.releaseConnection(); + } + } + + /** + * Removes the reference being stored for the given connection. This method should be called + * when the connection manager again has a direct reference to the connection. + * + * @param connection the connection to remove the reference for + * + * @see #storeReferenceToConnection(HttpConnection, HostConfiguration, ConnectionPool) + */ + private static void removeReferenceToConnection(HttpConnectionWithReference connection) { + + synchronized (REFERENCE_TO_CONNECTION_SOURCE) { + REFERENCE_TO_CONNECTION_SOURCE.remove(connection.reference); + } + } + + + // ----------------------------------------------------- Instance Variables + + /** + * Collection of parameters associated with this connection manager. + */ + private HttpConnectionManagerParams params = new HttpConnectionManagerParams(); + + /** Connection Pool */ + private ConnectionPool connectionPool; + + private boolean shutdown = false; + + + // ----------------------------------------------------------- Constructors + + /** + * No-args constructor + */ + public MultiThreadedHttpConnectionManager() { + this.connectionPool = new ConnectionPool(); + synchronized(ALL_CONNECTION_MANAGERS) { + ALL_CONNECTION_MANAGERS.put(this, null); + } + } + + + // ------------------------------------------------------- Instance Methods + + /** + * Shuts down the connection manager and releases all resources. All connections associated + * with this class will be closed and released. + * + *

The connection manager can no longer be used once shutdown. + * + *

Calling this method more than once will have no effect. + */ + public synchronized void shutdown() { + synchronized (connectionPool) { + if (!shutdown) { + shutdown = true; + connectionPool.shutdown(); + } + } + } + + /** + * Gets the staleCheckingEnabled value to be set on HttpConnections that are created. + * + * @return true if stale checking will be enabled on HttpConnections + * + * @see HttpConnection#isStaleCheckingEnabled() + * + * @deprecated Use {@link HttpConnectionManagerParams#isStaleCheckingEnabled()}, + * {@link HttpConnectionManager#getParams()}. + */ + public boolean isConnectionStaleCheckingEnabled() { + return this.params.isStaleCheckingEnabled(); + } + + /** + * Sets the staleCheckingEnabled value to be set on HttpConnections that are created. + * + * @param connectionStaleCheckingEnabled true if stale checking will be enabled + * on HttpConnections + * + * @see HttpConnection#setStaleCheckingEnabled(boolean) + * + * @deprecated Use {@link HttpConnectionManagerParams#setStaleCheckingEnabled(boolean)}, + * {@link HttpConnectionManager#getParams()}. + */ + public void setConnectionStaleCheckingEnabled(boolean connectionStaleCheckingEnabled) { + this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled); + } + + /** + * Sets the maximum number of connections allowed for a given + * HostConfiguration. Per RFC 2616 section 8.1.4, this value defaults to 2. + * + * @param maxHostConnections the number of connections allowed for each + * hostConfiguration + * + * @deprecated Use {@link HttpConnectionManagerParams#setDefaultMaxConnectionsPerHost(int)}, + * {@link HttpConnectionManager#getParams()}. + */ + public void setMaxConnectionsPerHost(int maxHostConnections) { + this.params.setDefaultMaxConnectionsPerHost(maxHostConnections); + } + + /** + * Gets the maximum number of connections allowed for a given + * hostConfiguration. + * + * @return The maximum number of connections allowed for a given + * hostConfiguration. + * + * @deprecated Use {@link HttpConnectionManagerParams#getDefaultMaxConnectionsPerHost()}, + * {@link HttpConnectionManager#getParams()}. + */ + public int getMaxConnectionsPerHost() { + return this.params.getDefaultMaxConnectionsPerHost(); + } + + /** + * Sets the maximum number of connections allowed for this connection manager. + * + * @param maxTotalConnections the maximum number of connections allowed + * + * @deprecated Use {@link HttpConnectionManagerParams#setMaxTotalConnections(int)}, + * {@link HttpConnectionManager#getParams()}. + */ + public void setMaxTotalConnections(int maxTotalConnections) { + this.params.getMaxTotalConnections(); + } + + /** + * Gets the maximum number of connections allowed for this connection manager. + * + * @return The maximum number of connections allowed + * + * @deprecated Use {@link HttpConnectionManagerParams#getMaxTotalConnections()}, + * {@link HttpConnectionManager#getParams()}. + */ + public int getMaxTotalConnections() { + return this.params.getMaxTotalConnections(); + } + + /** + * @see HttpConnectionManager#getConnection(HostConfiguration) + */ + public HttpConnection getConnection(HostConfiguration hostConfiguration) { + + while (true) { + try { + return getConnectionWithTimeout(hostConfiguration, 0); + } catch (ConnectionPoolTimeoutException e) { + // we'll go ahead and log this, but it should never happen. HttpExceptions + // are only thrown when the timeout occurs and since we have no timeout + // it should never happen. + LOG.debug( + "Unexpected exception while waiting for connection", + e + ); + } + } + } + + /** + * @see HttpConnectionManager#getConnectionWithTimeout(HostConfiguration, long) + * + * @since 3.0 + */ + public HttpConnection getConnectionWithTimeout(HostConfiguration hostConfiguration, + long timeout) throws ConnectionPoolTimeoutException { + + LOG.trace("enter HttpConnectionManager.getConnectionWithTimeout(HostConfiguration, long)"); + + if (hostConfiguration == null) { + throw new IllegalArgumentException("hostConfiguration is null"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("HttpConnectionManager.getConnection: config = " + + hostConfiguration + ", timeout = " + timeout); + } + + final HttpConnection conn = doGetConnection(hostConfiguration, timeout); + + // wrap the connection in an adapter so we can ensure it is used + // only once + return new HttpConnectionAdapter(conn); + } + + /** + * @see HttpConnectionManager#getConnection(HostConfiguration, long) + * + * @deprecated Use #getConnectionWithTimeout(HostConfiguration, long) + */ + public HttpConnection getConnection(HostConfiguration hostConfiguration, + long timeout) throws HttpException { + + LOG.trace("enter HttpConnectionManager.getConnection(HostConfiguration, long)"); + try { + return getConnectionWithTimeout(hostConfiguration, timeout); + } catch(ConnectionPoolTimeoutException e) { + throw new HttpException(e.getMessage()); + } + } + + /** + * Gets a connection or waits if one is not available. A connection is + * available if one exists that is not being used or if fewer than + * maxHostConnections have been created in the connectionPool, and fewer + * than maxTotalConnections have been created in all connectionPools. + * + * @param hostConfiguration The host configuration. + * @param timeout the number of milliseconds to wait for a connection, 0 to + * wait indefinitely + * + * @return HttpConnection an available connection + * + * @throws HttpException if a connection does not become available in + * 'timeout' milliseconds + */ + private HttpConnection doGetConnection(HostConfiguration hostConfiguration, + long timeout) throws ConnectionPoolTimeoutException { + + HttpConnection connection = null; + + int maxHostConnections = this.params.getMaxConnectionsPerHost(hostConfiguration); + int maxTotalConnections = this.params.getMaxTotalConnections(); + + synchronized (connectionPool) { + + // we clone the hostConfiguration + // so that it cannot be changed once the connection has been retrieved + hostConfiguration = new HostConfiguration(hostConfiguration); + HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration); + WaitingThread waitingThread = null; + + boolean useTimeout = (timeout > 0); + long timeToWait = timeout; + long startWait = 0; + long endWait = 0; + + while (connection == null) { + + if (shutdown) { + throw new IllegalStateException("Connection factory has been shutdown."); + } + + // happen to have a free connection with the right specs + // + if (hostPool.freeConnections.size() > 0) { + connection = connectionPool.getFreeConnection(hostConfiguration); + + // have room to make more + // + } else if ((hostPool.numConnections < maxHostConnections) + && (connectionPool.numConnections < maxTotalConnections)) { + + connection = connectionPool.createConnection(hostConfiguration); + + // have room to add host connection, and there is at least one free + // connection that can be liberated to make overall room + // + } else if ((hostPool.numConnections < maxHostConnections) + && (connectionPool.freeConnections.size() > 0)) { + + connectionPool.deleteLeastUsedConnection(); + connection = connectionPool.createConnection(hostConfiguration); + + // otherwise, we have to wait for one of the above conditions to + // become true + // + } else { + // TODO: keep track of which hostConfigurations have waiting + // threads, so they avoid being sacrificed before necessary + + try { + + if (useTimeout && timeToWait <= 0) { + throw new ConnectionPoolTimeoutException("Timeout waiting for connection"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Unable to get a connection, waiting..., hostConfig=" + hostConfiguration); + } + + if (waitingThread == null) { + waitingThread = new WaitingThread(); + waitingThread.hostConnectionPool = hostPool; + waitingThread.thread = Thread.currentThread(); + } + + if (useTimeout) { + startWait = System.currentTimeMillis(); + } + + hostPool.waitingThreads.addLast(waitingThread); + connectionPool.waitingThreads.addLast(waitingThread); + connectionPool.wait(timeToWait); + + // we have not been interrupted so we need to remove ourselves from the + // wait queue + hostPool.waitingThreads.remove(waitingThread); + connectionPool.waitingThreads.remove(waitingThread); + } catch (InterruptedException e) { + // do nothing + } finally { + if (useTimeout) { + endWait = System.currentTimeMillis(); + timeToWait -= (endWait - startWait); + } + } + } + } + } + return connection; + } + + /** + * Gets the total number of pooled connections for the given host configuration. This + * is the total number of connections that have been created and are still in use + * by this connection manager for the host configuration. This value will + * not exceed the {@link #getMaxConnectionsPerHost() maximum number of connections per + * host}. + * + * @param hostConfiguration The host configuration + * @return The total number of pooled connections + */ + public int getConnectionsInPool(HostConfiguration hostConfiguration) { + synchronized (connectionPool) { + HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration); + return hostPool.numConnections; + } + } + + /** + * Gets the total number of pooled connections. This is the total number of + * connections that have been created and are still in use by this connection + * manager. This value will not exceed the {@link #getMaxTotalConnections() + * maximum number of connections}. + * + * @return the total number of pooled connections + */ + public int getConnectionsInPool() { + synchronized (connectionPool) { + return connectionPool.numConnections; + } + } + + /** + * Gets the number of connections in use for this configuration. + * + * @param hostConfiguration the key that connections are tracked on + * @return the number of connections in use + * + * @deprecated Use {@link #getConnectionsInPool(HostConfiguration)} + */ + public int getConnectionsInUse(HostConfiguration hostConfiguration) { + return getConnectionsInPool(hostConfiguration); + } + + /** + * Gets the total number of connections in use. + * + * @return the total number of connections in use + * + * @deprecated Use {@link #getConnectionsInPool()} + */ + public int getConnectionsInUse() { + return getConnectionsInPool(); + } + + /** + * Deletes all closed connections. Only connections currently owned by the connection + * manager are processed. + * + * @see HttpConnection#isOpen() + * + * @since 3.0 + */ + public void deleteClosedConnections() { + connectionPool.deleteClosedConnections(); + } + + /** + * @since 3.0 + */ + public void closeIdleConnections(long idleTimeout) { + connectionPool.closeIdleConnections(idleTimeout); + } + + /** + * Make the given HttpConnection available for use by other requests. + * If another thread is blocked in getConnection() that could use this + * connection, it will be woken up. + * + * @param conn the HttpConnection to make available. + */ + public void releaseConnection(HttpConnection conn) { + LOG.trace("enter HttpConnectionManager.releaseConnection(HttpConnection)"); + + if (conn instanceof HttpConnectionAdapter) { + // connections given out are wrapped in an HttpConnectionAdapter + conn = ((HttpConnectionAdapter) conn).getWrappedConnection(); + } else { + // this is okay, when an HttpConnectionAdapter is released + // is releases the real connection + } + + // make sure that the response has been read. + SimpleHttpConnectionManager.finishLastResponse(conn); + + connectionPool.freeConnection(conn); + } + + /** + * Gets the host configuration for a connection. + * @param conn the connection to get the configuration of + * @return a new HostConfiguration + */ + private HostConfiguration configurationForConnection(HttpConnection conn) { + + HostConfiguration connectionConfiguration = new HostConfiguration(); + + connectionConfiguration.setHost( + conn.getHost(), + conn.getPort(), + conn.getProtocol() + ); + if (conn.getLocalAddress() != null) { + connectionConfiguration.setLocalAddress(conn.getLocalAddress()); + } + if (conn.getProxyHost() != null) { + connectionConfiguration.setProxy(conn.getProxyHost(), conn.getProxyPort()); + } + + return connectionConfiguration; + } + + /** + * Returns {@link HttpConnectionManagerParams parameters} associated + * with this connection manager. + * + * @since 3.0 + * + * @see HttpConnectionManagerParams + */ + public HttpConnectionManagerParams getParams() { + return this.params; + } + + /** + * Assigns {@link HttpConnectionManagerParams parameters} for this + * connection manager. + * + * @since 3.0 + * + * @see HttpConnectionManagerParams + */ + public void setParams(final HttpConnectionManagerParams params) { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + this.params = params; + } + + /** + * Global Connection Pool, including per-host pools + */ + private class ConnectionPool { + + /** The list of free connections */ + private LinkedList freeConnections = new LinkedList(); + + /** The list of WaitingThreads waiting for a connection */ + private LinkedList waitingThreads = new LinkedList(); + + /** + * Map where keys are {@link HostConfiguration}s and values are {@link + * HostConnectionPool}s + */ + private final Map mapHosts = new HashMap(); + + private IdleConnectionHandler idleConnectionHandler = new IdleConnectionHandler(); + + /** The number of created connections */ + private int numConnections = 0; + + /** + * Cleans up all connection pool resources. + */ + public synchronized void shutdown() { + + // close all free connections + Iterator iter = freeConnections.iterator(); + while (iter.hasNext()) { + HttpConnection conn = (HttpConnection) iter.next(); + iter.remove(); + conn.close(); + } + + // close all connections that have been checked out + shutdownCheckedOutConnections(this); + + // interrupt all waiting threads + iter = waitingThreads.iterator(); + while (iter.hasNext()) { + WaitingThread waiter = (WaitingThread) iter.next(); + iter.remove(); + waiter.thread.interrupt(); + } + + // clear out map hosts + mapHosts.clear(); + + // remove all references to connections + idleConnectionHandler.removeAll(); + } + + /** + * Creates a new connection and returns it for use of the calling method. + * + * @param hostConfiguration the configuration for the connection + * @return a new connection or null if none are available + */ + public synchronized HttpConnection createConnection(HostConfiguration hostConfiguration) { + HostConnectionPool hostPool = getHostPool(hostConfiguration); + if (LOG.isDebugEnabled()) { + LOG.debug("Allocating new connection, hostConfig=" + hostConfiguration); + } + HttpConnectionWithReference connection = new HttpConnectionWithReference( + hostConfiguration); + connection.getParams().setDefaults(MultiThreadedHttpConnectionManager.this.params); + connection.setHttpConnectionManager(MultiThreadedHttpConnectionManager.this); + numConnections++; + hostPool.numConnections++; + + // store a reference to this connection so that it can be cleaned up + // in the event it is not correctly released + storeReferenceToConnection(connection, hostConfiguration, this); + return connection; + } + + /** + * Handles cleaning up for a lost connection with the given config. Decrements any + * connection counts and notifies waiting threads, if appropriate. + * + * @param config the host configuration of the connection that was lost + */ + public synchronized void handleLostConnection(HostConfiguration config) { + HostConnectionPool hostPool = getHostPool(config); + hostPool.numConnections--; + + numConnections--; + notifyWaitingThread(config); + } + + /** + * Get the pool (list) of connections available for the given hostConfig. + * + * @param hostConfiguration the configuraton for the connection pool + * @return a pool (list) of connections available for the given config + */ + public synchronized HostConnectionPool getHostPool(HostConfiguration hostConfiguration) { + LOG.trace("enter HttpConnectionManager.ConnectionPool.getHostPool(HostConfiguration)"); + + // Look for a list of connections for the given config + HostConnectionPool listConnections = (HostConnectionPool) + mapHosts.get(hostConfiguration); + if (listConnections == null) { + // First time for this config + listConnections = new HostConnectionPool(); + listConnections.hostConfiguration = hostConfiguration; + mapHosts.put(hostConfiguration, listConnections); + } + + return listConnections; + } + + /** + * If available, get a free connection for this host + * + * @param hostConfiguration the configuraton for the connection pool + * @return an available connection for the given config + */ + public synchronized HttpConnection getFreeConnection(HostConfiguration hostConfiguration) { + + HttpConnectionWithReference connection = null; + + HostConnectionPool hostPool = getHostPool(hostConfiguration); + + if (hostPool.freeConnections.size() > 0) { + connection = (HttpConnectionWithReference) hostPool.freeConnections.removeFirst(); + freeConnections.remove(connection); + // store a reference to this connection so that it can be cleaned up + // in the event it is not correctly released + storeReferenceToConnection(connection, hostConfiguration, this); + if (LOG.isDebugEnabled()) { + LOG.debug("Getting free connection, hostConfig=" + hostConfiguration); + } + + // remove the connection from the timeout handler + idleConnectionHandler.remove(connection); + } else if (LOG.isDebugEnabled()) { + LOG.debug("There were no free connections to get, hostConfig=" + + hostConfiguration); + } + return connection; + } + + /** + * Deletes all closed connections. + */ + public synchronized void deleteClosedConnections() { + + Iterator iter = freeConnections.iterator(); + + while (iter.hasNext()) { + HttpConnection conn = (HttpConnection) iter.next(); + if (!conn.isOpen()) { + iter.remove(); + deleteConnection(conn); + } + } + } + + /** + * Closes idle connections. + * @param idleTimeout + */ + public synchronized void closeIdleConnections(long idleTimeout) { + idleConnectionHandler.closeIdleConnections(idleTimeout); + } + + /** + * Deletes the given connection. This will remove all reference to the connection + * so that it can be GCed. + * + *

Note: Does not remove the connection from the freeConnections list. It + * is assumed that the caller has already handled this case.

+ * + * @param connection The connection to delete + */ + private synchronized void deleteConnection(HttpConnection connection) { + + HostConfiguration connectionConfiguration = configurationForConnection(connection); + + if (LOG.isDebugEnabled()) { + LOG.debug("Reclaiming connection, hostConfig=" + connectionConfiguration); + } + + connection.close(); + + HostConnectionPool hostPool = getHostPool(connectionConfiguration); + + hostPool.freeConnections.remove(connection); + hostPool.numConnections--; + numConnections--; + + // remove the connection from the timeout handler + idleConnectionHandler.remove(connection); + } + + /** + * Close and delete an old, unused connection to make room for a new one. + */ + public synchronized void deleteLeastUsedConnection() { + + HttpConnection connection = (HttpConnection) freeConnections.removeFirst(); + + if (connection != null) { + deleteConnection(connection); + } else if (LOG.isDebugEnabled()) { + LOG.debug("Attempted to reclaim an unused connection but there were none."); + } + } + + /** + * Notifies a waiting thread that a connection for the given configuration is + * available. + * @param configuration the host config to use for notifying + * @see #notifyWaitingThread(HostConnectionPool) + */ + public synchronized void notifyWaitingThread(HostConfiguration configuration) { + notifyWaitingThread(getHostPool(configuration)); + } + + /** + * Notifies a waiting thread that a connection for the given configuration is + * available. This will wake a thread waiting in this host pool or if there is not + * one a thread in the connection pool will be notified. + * + * @param hostPool the host pool to use for notifying + */ + public synchronized void notifyWaitingThread(HostConnectionPool hostPool) { + + // find the thread we are going to notify, we want to ensure that each + // waiting thread is only interrupted once so we will remove it from + // all wait queues before interrupting it + WaitingThread waitingThread = null; + + if (hostPool.waitingThreads.size() > 0) { + if (LOG.isDebugEnabled()) { + LOG.debug("Notifying thread waiting on host pool, hostConfig=" + + hostPool.hostConfiguration); + } + waitingThread = (WaitingThread) hostPool.waitingThreads.removeFirst(); + waitingThreads.remove(waitingThread); + } else if (waitingThreads.size() > 0) { + if (LOG.isDebugEnabled()) { + LOG.debug("No-one waiting on host pool, notifying next waiting thread."); + } + waitingThread = (WaitingThread) waitingThreads.removeFirst(); + waitingThread.hostConnectionPool.waitingThreads.remove(waitingThread); + } else if (LOG.isDebugEnabled()) { + LOG.debug("Notifying no-one, there are no waiting threads"); + } + + if (waitingThread != null) { + waitingThread.thread.interrupt(); + } + } + + /** + * Marks the given connection as free. + * @param conn a connection that is no longer being used + */ + public void freeConnection(HttpConnection conn) { + + HostConfiguration connectionConfiguration = configurationForConnection(conn); + + if (LOG.isDebugEnabled()) { + LOG.debug("Freeing connection, hostConfig=" + connectionConfiguration); + } + + synchronized (this) { + + if (shutdown) { + // the connection manager has been shutdown, release the connection's + // resources and get out of here + conn.close(); + return; + } + + HostConnectionPool hostPool = getHostPool(connectionConfiguration); + + // Put the connect back in the available list and notify a waiter + hostPool.freeConnections.add(conn); + if (hostPool.numConnections == 0) { + // for some reason this connection pool didn't already exist + LOG.error("Host connection pool not found, hostConfig=" + + connectionConfiguration); + hostPool.numConnections = 1; + } + + freeConnections.add(conn); + // we can remove the reference to this connection as we have control over + // it again. this also ensures that the connection manager can be GCed + removeReferenceToConnection((HttpConnectionWithReference) conn); + if (numConnections == 0) { + // for some reason this connection pool didn't already exist + LOG.error("Host connection pool not found, hostConfig=" + + connectionConfiguration); + numConnections = 1; + } + + // register the connection with the timeout handler + idleConnectionHandler.add(conn); + + notifyWaitingThread(hostPool); + } + } + } + + /** + * A simple struct-like class to combine the objects needed to release a connection's + * resources when claimed by the garbage collector. + */ + private static class ConnectionSource { + + /** The connection pool that created the connection */ + public ConnectionPool connectionPool; + + /** The connection's host configuration */ + public HostConfiguration hostConfiguration; + } + + /** + * A simple struct-like class to combine the connection list and the count + * of created connections. + */ + private static class HostConnectionPool { + /** The hostConfig this pool is for */ + public HostConfiguration hostConfiguration; + + /** The list of free connections */ + public LinkedList freeConnections = new LinkedList(); + + /** The list of WaitingThreads for this host */ + public LinkedList waitingThreads = new LinkedList(); + + /** The number of created connections */ + public int numConnections = 0; + } + + /** + * A simple struct-like class to combine the waiting thread and the connection + * pool it is waiting on. + */ + private static class WaitingThread { + /** The thread that is waiting for a connection */ + public Thread thread; + + /** The connection pool the thread is waiting for */ + public HostConnectionPool hostConnectionPool; + } + + /** + * A thread for listening for HttpConnections reclaimed by the garbage + * collector. + */ + private static class ReferenceQueueThread extends Thread { + + private boolean shutdown = false; + + /** + * Create an instance and make this a daemon thread. + */ + public ReferenceQueueThread() { + setDaemon(true); + setName("MultiThreadedHttpConnectionManager cleanup"); + } + + public void shutdown() { + this.shutdown = true; + } + + /** + * Handles cleaning up for the given connection reference. + * + * @param ref the reference to clean up + */ + private void handleReference(Reference ref) { + + ConnectionSource source = null; + + synchronized (REFERENCE_TO_CONNECTION_SOURCE) { + source = (ConnectionSource) REFERENCE_TO_CONNECTION_SOURCE.remove(ref); + } + // only clean up for this reference if it is still associated with + // a ConnectionSource + if (source != null) { + if (LOG.isDebugEnabled()) { + LOG.debug( + "Connection reclaimed by garbage collector, hostConfig=" + + source.hostConfiguration); + } + + source.connectionPool.handleLostConnection(source.hostConfiguration); + } + } + + /** + * Start execution. + */ + public void run() { + while (!shutdown) { + try { + // remove the next reference and process it, a timeout + // is used so that the thread does not block indefinitely + // and therefore keep the thread from shutting down + Reference ref = REFERENCE_QUEUE.remove(1000); + if (ref != null) { + handleReference(ref); + } + } catch (InterruptedException e) { + LOG.debug("ReferenceQueueThread interrupted", e); + } + } + } + + } + + /** + * A connection that keeps a reference to itself. + */ + private static class HttpConnectionWithReference extends HttpConnection { + + public WeakReference reference = new WeakReference(this, REFERENCE_QUEUE); + + /** + * @param hostConfiguration + */ + public HttpConnectionWithReference(HostConfiguration hostConfiguration) { + super(hostConfiguration); + } + + } + + /** + * An HttpConnection wrapper that ensures a connection cannot be used + * once released. + */ + private static class HttpConnectionAdapter extends HttpConnection { + + // the wrapped connection + private HttpConnection wrappedConnection; + + /** + * Creates a new HttpConnectionAdapter. + * @param connection the connection to be wrapped + */ + public HttpConnectionAdapter(HttpConnection connection) { + super(connection.getHost(), connection.getPort(), connection.getProtocol()); + this.wrappedConnection = connection; + } + + /** + * Tests if the wrapped connection is still available. + * @return boolean + */ + protected boolean hasConnection() { + return wrappedConnection != null; + } + + /** + * @return HttpConnection + */ + HttpConnection getWrappedConnection() { + return wrappedConnection; + } + + public void close() { + if (hasConnection()) { + wrappedConnection.close(); + } else { + // do nothing + } + } + + public InetAddress getLocalAddress() { + if (hasConnection()) { + return wrappedConnection.getLocalAddress(); + } else { + return null; + } + } + + /** + * @deprecated + */ + public boolean isStaleCheckingEnabled() { + if (hasConnection()) { + return wrappedConnection.isStaleCheckingEnabled(); + } else { + return false; + } + } + + public void setLocalAddress(InetAddress localAddress) { + if (hasConnection()) { + wrappedConnection.setLocalAddress(localAddress); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public void setStaleCheckingEnabled(boolean staleCheckEnabled) { + if (hasConnection()) { + wrappedConnection.setStaleCheckingEnabled(staleCheckEnabled); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public String getHost() { + if (hasConnection()) { + return wrappedConnection.getHost(); + } else { + return null; + } + } + + public HttpConnectionManager getHttpConnectionManager() { + if (hasConnection()) { + return wrappedConnection.getHttpConnectionManager(); + } else { + return null; + } + } + + public InputStream getLastResponseInputStream() { + if (hasConnection()) { + return wrappedConnection.getLastResponseInputStream(); + } else { + return null; + } + } + + public int getPort() { + if (hasConnection()) { + return wrappedConnection.getPort(); + } else { + return -1; + } + } + + public Protocol getProtocol() { + if (hasConnection()) { + return wrappedConnection.getProtocol(); + } else { + return null; + } + } + + public String getProxyHost() { + if (hasConnection()) { + return wrappedConnection.getProxyHost(); + } else { + return null; + } + } + + public int getProxyPort() { + if (hasConnection()) { + return wrappedConnection.getProxyPort(); + } else { + return -1; + } + } + + public OutputStream getRequestOutputStream() + throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.getRequestOutputStream(); + } else { + return null; + } + } + + public InputStream getResponseInputStream() + throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.getResponseInputStream(); + } else { + return null; + } + } + + public boolean isOpen() { + if (hasConnection()) { + return wrappedConnection.isOpen(); + } else { + return false; + } + } + + public boolean closeIfStale() throws IOException { + if (hasConnection()) { + return wrappedConnection.closeIfStale(); + } else { + return false; + } + } + + public boolean isProxied() { + if (hasConnection()) { + return wrappedConnection.isProxied(); + } else { + return false; + } + } + + public boolean isResponseAvailable() throws IOException { + if (hasConnection()) { + return wrappedConnection.isResponseAvailable(); + } else { + return false; + } + } + + public boolean isResponseAvailable(int timeout) throws IOException { + if (hasConnection()) { + return wrappedConnection.isResponseAvailable(timeout); + } else { + return false; + } + } + + public boolean isSecure() { + if (hasConnection()) { + return wrappedConnection.isSecure(); + } else { + return false; + } + } + + public boolean isTransparent() { + if (hasConnection()) { + return wrappedConnection.isTransparent(); + } else { + return false; + } + } + + public void open() throws IOException { + if (hasConnection()) { + wrappedConnection.open(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public void print(String data) + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.print(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void printLine() + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.printLine(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public void printLine(String data) + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.printLine(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public String readLine() throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.readLine(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public String readLine(String charset) throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.readLine(charset); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void releaseConnection() { + if (!isLocked() && hasConnection()) { + HttpConnection wrappedConnection = this.wrappedConnection; + this.wrappedConnection = null; + wrappedConnection.releaseConnection(); + } else { + // do nothing + } + } + + /** + * @deprecated + */ + public void setConnectionTimeout(int timeout) { + if (hasConnection()) { + wrappedConnection.setConnectionTimeout(timeout); + } else { + // do nothing + } + } + + public void setHost(String host) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setHost(host); + } else { + // do nothing + } + } + + public void setHttpConnectionManager(HttpConnectionManager httpConnectionManager) { + if (hasConnection()) { + wrappedConnection.setHttpConnectionManager(httpConnectionManager); + } else { + // do nothing + } + } + + public void setLastResponseInputStream(InputStream inStream) { + if (hasConnection()) { + wrappedConnection.setLastResponseInputStream(inStream); + } else { + // do nothing + } + } + + public void setPort(int port) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setPort(port); + } else { + // do nothing + } + } + + public void setProtocol(Protocol protocol) { + if (hasConnection()) { + wrappedConnection.setProtocol(protocol); + } else { + // do nothing + } + } + + public void setProxyHost(String host) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setProxyHost(host); + } else { + // do nothing + } + } + + public void setProxyPort(int port) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setProxyPort(port); + } else { + // do nothing + } + } + + /** + * @deprecated + */ + public void setSoTimeout(int timeout) + throws SocketException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.setSoTimeout(timeout); + } else { + // do nothing + } + } + + /** + * @deprecated + */ + public void shutdownOutput() { + if (hasConnection()) { + wrappedConnection.shutdownOutput(); + } else { + // do nothing + } + } + + public void tunnelCreated() throws IllegalStateException, IOException { + if (hasConnection()) { + wrappedConnection.tunnelCreated(); + } else { + // do nothing + } + } + + public void write(byte[] data, int offset, int length) + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.write(data, offset, length); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void write(byte[] data) + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.write(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void writeLine() + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.writeLine(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void writeLine(byte[] data) + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.writeLine(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void flushRequestOutputStream() throws IOException { + if (hasConnection()) { + wrappedConnection.flushRequestOutputStream(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public int getSoTimeout() throws SocketException { + if (hasConnection()) { + return wrappedConnection.getSoTimeout(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public String getVirtualHost() { + if (hasConnection()) { + return wrappedConnection.getVirtualHost(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public void setVirtualHost(String host) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setVirtualHost(host); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public int getSendBufferSize() throws SocketException { + if (hasConnection()) { + return wrappedConnection.getSendBufferSize(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /** + * @deprecated + */ + public void setSendBufferSize(int sendBufferSize) throws SocketException { + if (hasConnection()) { + wrappedConnection.setSendBufferSize(sendBufferSize); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public HttpConnectionParams getParams() { + if (hasConnection()) { + return wrappedConnection.getParams(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void setParams(final HttpConnectionParams params) { + if (hasConnection()) { + wrappedConnection.setParams(params); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.HttpConnection#print(java.lang.String, java.lang.String) + */ + public void print(String data, String charset) throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.print(data, charset); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.HttpConnection#printLine(java.lang.String, java.lang.String) + */ + public void printLine(String data, String charset) + throws IOException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.printLine(data, charset); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.HttpConnection#setSocketTimeout(int) + */ + public void setSocketTimeout(int timeout) throws SocketException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.setSocketTimeout(timeout); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NTCredentials.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NTCredentials.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NTCredentials.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,191 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NTCredentials.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.util.LangUtils; + +/** {@link Credentials} for use with the NTLM authentication scheme which requires additional + * information. + * + * @author Adrian Sutton + * @author Mike Bowler + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:34 $ + * + * @since 2.0 + */ +public class NTCredentials extends UsernamePasswordCredentials { + + // ----------------------------------------------------- Instance Variables + + /** The Domain to authenticate with. */ + private String domain; + + /** The host the authentication request is originating from. */ + private String host; + + + // ----------------------------------------------------------- Constructors + + /** + * Default constructor. + * + * @deprecated Do not use. Null user name, domain & host no longer allowed + */ + public NTCredentials() { + super(); + } + + /** + * Constructor. + * @param userName The user name. This should not include the domain to authenticate with. + * For example: "user" is correct whereas "DOMAIN\\user" is not. + * @param password The password. + * @param host The host the authentication request is originating from. Essentially, the + * computer name for this machine. + * @param domain The domain to authenticate within. + */ + public NTCredentials(String userName, String password, String host, + String domain) { + super(userName, password); + if (domain == null) { + throw new IllegalArgumentException("Domain may not be null"); + } + this.domain = domain; + if (host == null) { + throw new IllegalArgumentException("Host may not be null"); + } + this.host = host; + } + // ------------------------------------------------------- Instance Methods + + + /** + * Sets the domain to authenticate with. The domain may not be null. + * + * @param domain the NT domain to authenticate in. + * + * @see #getDomain() + * + * @deprecated Do not use. The NTCredentials objects should be immutable + */ + public void setDomain(String domain) { + if (domain == null) { + throw new IllegalArgumentException("Domain may not be null"); + } + this.domain = domain; + } + + /** + * Retrieves the name to authenticate with. + * + * @return String the domain these credentials are intended to authenticate with. + * + * @see #setDomain(String) + * + */ + public String getDomain() { + return domain; + } + + /** + * Sets the host name of the computer originating the request. The host name may + * not be null. + * + * @param host the Host the user is logged into. + * + * @deprecated Do not use. The NTCredentials objects should be immutable + */ + public void setHost(String host) { + if (host == null) { + throw new IllegalArgumentException("Host may not be null"); + } + this.host = host; + } + + /** + * Retrieves the host name of the computer originating the request. + * + * @return String the host the user is logged into. + */ + public String getHost() { + return this.host; + } + + /** + * Return a string representation of this object. + * @return A string represenation of this object. + */ + public String toString() { + final StringBuffer sbResult = new StringBuffer(super.toString()); + + sbResult.append("@"); + sbResult.append(this.host); + sbResult.append("."); + sbResult.append(this.domain); + + return sbResult.toString(); + } + + /** + * Computes a hash code based on all the case-sensitive parts of the credentials object. + * + * @return The hash code for the credentials. + */ + public int hashCode() { + int hash = super.hashCode(); + hash = LangUtils.hashCode(hash, this.host); + hash = LangUtils.hashCode(hash, this.domain); + return hash; + } + + /** + * Performs a case-sensitive check to see if the components of the credentials + * are the same. + * + * @param o The object to match. + * + * @return true if all of the credentials match. + */ + public boolean equals(Object o) { + if (o == null) return false; + if (this == o) return true; + if (super.equals(o) ) { + if (o instanceof NTCredentials) { + NTCredentials that = (NTCredentials) o; + + return LangUtils.equals(this.domain, that.domain) + && LangUtils.equals(this.host, that.host); + } + } + + return false; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NameValuePair.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NameValuePair.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NameValuePair.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,151 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NameValuePair.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.Serializable; + +import org.apache.commons.httpclient.util.LangUtils; + +/** + *

A simple class encapsulating a name/value pair.

+ * + * @author B.C. Holmes + * @author Sean C. Sullivan + * @author Mike Bowler + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:35 $ + * + */ +public class NameValuePair implements Serializable { + + // ----------------------------------------------------------- Constructors + + /** + * Default constructor. + * + */ + public NameValuePair() { + this (null, null); + } + + /** + * Constructor. + * @param name The name. + * @param value The value. + */ + public NameValuePair(String name, String value) { + this.name = name; + this.value = value; + } + + // ----------------------------------------------------- Instance Variables + + /** + * Name. + */ + private String name = null; + + /** + * Value. + */ + private String value = null; + + // ------------------------------------------------------------- Properties + + /** + * Set the name. + * + * @param name The new name + * @see #getName() + */ + public void setName(String name) { + this.name = name; + } + + + /** + * Return the name. + * + * @return String name The name + * @see #setName(String) + */ + public String getName() { + return name; + } + + + /** + * Set the value. + * + * @param value The new value. + */ + public void setValue(String value) { + this.value = value; + } + + + /** + * Return the current value. + * + * @return String value The current value. + */ + public String getValue() { + return value; + } + + // --------------------------------------------------------- Public Methods + + /** + * Get a String representation of this pair. + * @return A string representation. + */ + public String toString() { + return ("name=" + name + ", " + "value=" + value); + } + + public boolean equals(final Object object) { + if (object == null) return false; + if (this == object) return true; + if (object instanceof NameValuePair) { + NameValuePair that = (NameValuePair) object; + return LangUtils.equals(this.name, that.name) + && LangUtils.equals(this.value, that.value); + } else { + return false; + } + } + + public int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.name); + hash = LangUtils.hashCode(hash, this.value); + return hash; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NoHttpResponseException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NoHttpResponseException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NoHttpResponseException.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,77 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/NoHttpResponseException.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; + +import org.apache.commons.httpclient.util.ExceptionUtil; + +/** + *

+ * Signals that the target server failed to respond with a valid HTTP response. + *

+ * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + */ +public class NoHttpResponseException extends IOException { + + /** + * Creates a new NoHttpResponseException with a null detail message. + */ + public NoHttpResponseException() { + super(); + } + + /** + * Creates a new NoHttpResponseException with the specified detail message. + * + * @param message exception message + */ + public NoHttpResponseException(String message) { + super(message); + } + + /** + * Creates a new NoHttpResponseException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + * + * @since 3.0 + */ + public NoHttpResponseException(String message, Throwable cause) { + super(message); + // If we're running on JDK 1.4 or later, tell Throwable what the cause was + ExceptionUtil.initCause(this, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProtocolException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProtocolException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProtocolException.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,68 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProtocolException.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * Signals that an HTTP protocol violation has occurred. For example, HttpClient + * detected a malformed status line or headers, a missing message body, etc. + * + * @author Laura Werner + * + * @since 3.0 + */ +public class ProtocolException extends HttpException { + + /** + * Creates a new ProtocolException with a null detail message. + */ + public ProtocolException() { + super(); + } + + /** + * Creates a new ProtocolException with the specified detail message. + * + * @param message The exception detail message + */ + public ProtocolException(String message) { + super(message); + } + + /** + * Creates a new ProtocolException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public ProtocolException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyClient.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyClient.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyClient.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,312 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyClient.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.net.Socket; + +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; +import org.apache.commons.httpclient.params.HttpParams; + + +/** + * A client that provides {@link java.net.Socket sockets} for communicating through HTTP proxies + * via the HTTP CONNECT method. This is primarily needed for non-HTTP protocols that wish to + * communicate via an HTTP proxy. + * + * @author Oleg Kalnichevski + * @author Michael Becke + * + * @since 3.0 + * + * @version $Revision: 1.1 $ + */ +public class ProxyClient { + + // ----------------------------------------------------- Instance Variables + + /** + * The {@link HttpState HTTP state} associated with this ProxyClient. + */ + private HttpState state = new HttpState(); + + /** + * The {@link HttpClientParams collection of parameters} associated with this ProxyClient. + */ + private HttpClientParams params = null; + + /** + * The {@link HostConfiguration host configuration} associated with + * the ProxyClient + */ + private HostConfiguration hostConfiguration = new HostConfiguration(); + + /** + * Creates an instance of ProxyClient using default {@link HttpClientParams parameter set}. + * + * @see HttpClientParams + */ + public ProxyClient() { + this(new HttpClientParams()); + } + + /** + * Creates an instance of ProxyClient using the given + * {@link HttpClientParams parameter set}. + * + * @param params The {@link HttpClientParams parameters} to use. + * + * @see HttpClientParams + */ + public ProxyClient(HttpClientParams params) { + super(); + if (params == null) { + throw new IllegalArgumentException("Params may not be null"); + } + this.params = params; + } + + // ------------------------------------------------------------- Properties + + /** + * Returns {@link HttpState HTTP state} associated with the ProxyClient. + * + * @see #setState(HttpState) + * @return the shared client state + */ + public synchronized HttpState getState() { + return state; + } + + /** + * Assigns {@link HttpState HTTP state} for the ProxyClient. + * + * @see #getState() + * @param state the new {@link HttpState HTTP state} for the client + */ + public synchronized void setState(HttpState state) { + this.state = state; + } + + /** + * Returns the {@link HostConfiguration host configuration} associated with the + * ProxyClient. + * + * @return {@link HostConfiguration host configuration} + */ + public synchronized HostConfiguration getHostConfiguration() { + return hostConfiguration; + } + + /** + * Assigns the {@link HostConfiguration host configuration} to use with the + * ProxyClient. + * + * @param hostConfiguration The {@link HostConfiguration host configuration} to set + */ + public synchronized void setHostConfiguration(HostConfiguration hostConfiguration) { + this.hostConfiguration = hostConfiguration; + } + + /** + * Returns {@link HttpClientParams HTTP protocol parameters} associated with this ProxyClient. + * + * @see HttpClientParams + */ + public synchronized HttpClientParams getParams() { + return this.params; + } + + /** + * Assigns {@link HttpClientParams HTTP protocol parameters} for this ProxyClient. + * + * @see HttpClientParams + */ + public synchronized void setParams(final HttpClientParams params) { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + this.params = params; + } + + /** + * Creates a socket that is connected, via the HTTP CONNECT method, to a proxy. + * + *

+ * Even though HTTP CONNECT proxying is generally used for HTTPS tunneling, the returned + * socket will not have been wrapped in an SSL socket. + *

+ * + *

+ * Both the proxy and destination hosts must be set via the + * {@link #getHostConfiguration() host configuration} prior to calling this method. + *

+ * + * @return the connect response + * + * @throws IOException + * @throws HttpException + * + * @see #getHostConfiguration() + */ + public ConnectResponse connect() throws IOException, HttpException { + + if (getHostConfiguration().getProxyHost() == null) { + throw new IllegalStateException("proxy host must be configured"); + } + if (getHostConfiguration().getHost() == null) { + throw new IllegalStateException("destination host must be configured"); + } + + ConnectMethod method = new ConnectMethod(); + method.getParams().setDefaults(getParams()); + + DummyConnectionManager connectionManager = new DummyConnectionManager(); + connectionManager.setConnectionParams(getParams()); + + HttpMethodDirector director = new HttpMethodDirector( + connectionManager, + getHostConfiguration(), + getParams(), + getState() + ); + + director.executeMethod(method); + + ConnectResponse response = new ConnectResponse(); + response.setConnectMethod(method); + + // only set the socket if the connect was successful + if (method.getStatusCode() == HttpStatus.SC_OK) { + response.setSocket(connectionManager.getConnection().getSocket()); + } else { + connectionManager.getConnection().close(); + } + + return response; + } + + /** + * Contains the method used to execute the connect along with the created socket. + */ + public static class ConnectResponse { + + private ConnectMethod connectMethod; + + private Socket socket; + + private ConnectResponse() {} + + /** + * Gets the method that was used to execute the connect. This method is useful for + * analyzing the proxy's response when a connect fails. + * + * @return the connectMethod. + */ + public ConnectMethod getConnectMethod() { + return connectMethod; + } + /** + * @param connectMethod The connectMethod to set. + */ + private void setConnectMethod(ConnectMethod connectMethod) { + this.connectMethod = connectMethod; + } + /** + * Gets the socket connected and authenticated (if appropriate) to the configured + * HTTP proxy, or null if a connection could not be made. It is the + * responsibility of the user to close this socket when it is no longer needed. + * + * @return the socket. + */ + public Socket getSocket() { + return socket; + } + /** + * @param socket The socket to set. + */ + private void setSocket(Socket socket) { + this.socket = socket; + } + } + + /** + * A connection manager that creates a single connection. Meant to be used only once. + */ + static class DummyConnectionManager implements HttpConnectionManager { + + private HttpConnection httpConnection; + + private HttpParams connectionParams; + + public void closeIdleConnections(long idleTimeout) { + } + + public HttpConnection getConnection() { + return httpConnection; + } + + public void setConnectionParams(HttpParams httpParams) { + this.connectionParams = httpParams; + } + + public HttpConnection getConnectionWithTimeout( + HostConfiguration hostConfiguration, long timeout) { + + httpConnection = new HttpConnection(hostConfiguration); + httpConnection.setHttpConnectionManager(this); + httpConnection.getParams().setDefaults(connectionParams); + return httpConnection; + } + + /** + * @deprecated + */ + public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout) + throws HttpException { + return getConnectionWithTimeout(hostConfiguration, timeout); + } + + public HttpConnection getConnection(HostConfiguration hostConfiguration) { + return getConnectionWithTimeout(hostConfiguration, -1); + } + + public void releaseConnection(HttpConnection conn) { + } + + public HttpConnectionManagerParams getParams() { + return null; + } + + public void setParams(HttpConnectionManagerParams params) { + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyHost.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyHost.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyHost.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,82 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ProxyHost.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.protocol.Protocol; + +/** + * Holds all of the variables needed to describe an HTTP connection to a proxy. Proxy hosts + * always use plain HTTP connection when communicating with clients. + * + * @author Michael Becke + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author Laura Werner + * + * @since 3.0 + */ +public class ProxyHost extends HttpHost { + + /** + * Copy constructor for HttpHost + * + * @param httpproxy the HTTP host to copy details from + */ + public ProxyHost (final ProxyHost httpproxy) { + super(httpproxy); + } + + /** + * Constructor for ProxyHost. + * + * @param hostname the hostname (IP or DNS name). Can be null. + * @param port the port. Value -1 can be used to set default protocol port + */ + public ProxyHost(final String hostname, int port) { + super(hostname, port, Protocol.getProtocol("http")); + } + + /** + * Constructor for HttpHost. + * + * @param hostname the hostname (IP or DNS name). Can be null. + */ + public ProxyHost(final String hostname) { + this(hostname, -1); + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() { + return new ProxyHost(this); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/RedirectException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/RedirectException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/RedirectException.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,67 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/RedirectException.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * Signals violation of HTTP specification caused by an invalid redirect + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class RedirectException extends ProtocolException { + + /** + * Creates a new RedirectException with a null detail message. + */ + public RedirectException() { + super(); + } + + /** + * Creates a new RedirectException with the specified detail message. + * + * @param message The exception detail message + */ + public RedirectException(String message) { + super(message); + } + + /** + * Creates a new RedirectException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public RedirectException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ResponseConsumedWatcher.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ResponseConsumedWatcher.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ResponseConsumedWatcher.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,52 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/ResponseConsumedWatcher.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * When a response stream has been consumed, various parts of the HttpClient + * implementation need to respond appropriately. + * + *

When one of the three types of {@link java.io.InputStream}, one of + * AutoCloseInputStream (package), {@link ContentLengthInputStream}, or + * {@link ChunkedInputStream} finishes with its content, either because + * all content has been consumed, or because it was explicitly closed, + * it notifies its corresponding method via this interface.

+ * + * @see ContentLengthInputStream + * @see ChunkedInputStream + * @author Eric Johnson + */ +interface ResponseConsumedWatcher { + + /** + * A response has been consumed. + */ + void responseConsumed(); +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/SimpleHttpConnectionManager.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/SimpleHttpConnectionManager.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/SimpleHttpConnectionManager.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,246 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/SimpleHttpConnectionManager.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A connection manager that provides access to a single HttpConnection. This + * manager makes no attempt to provide exclusive access to the contained + * HttpConnection. + * + * @author Michael Becke + * @author Eric Johnson + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author Laura Werner + * + * @since 2.0 + */ +public class SimpleHttpConnectionManager implements HttpConnectionManager { + + private static final Log LOG = LogFactory.getLog(SimpleHttpConnectionManager.class); + + private static final String MISUSE_MESSAGE = + "SimpleHttpConnectionManager being used incorrectly. Be sure that" + + " HttpMethod.releaseConnection() is always called and that only one thread" + + " and/or method is using this connection manager at a time."; + + /** + * Since the same connection is about to be reused, make sure the + * previous request was completely processed, and if not + * consume it now. + * @param conn The connection + */ + static void finishLastResponse(HttpConnection conn) { + InputStream lastResponse = conn.getLastResponseInputStream(); + if (lastResponse != null) { + conn.setLastResponseInputStream(null); + try { + lastResponse.close(); + } catch (IOException ioe) { + //FIXME: badness - close to force reconnect. + conn.close(); + } + } + } + + /** The http connection */ + protected HttpConnection httpConnection; + + /** + * Collection of parameters associated with this connection manager. + */ + private HttpConnectionManagerParams params = new HttpConnectionManagerParams(); + + /** + * The time the connection was made idle. + */ + private long idleStartTime = Long.MAX_VALUE; + + /** + * Used to test if {@link #httpConnection} is currently in use + * (i.e. checked out). This is only used as a sanity check to help + * debug cases where this connection manager is being used incorrectly. + * It will not be used to enforce thread safety. + */ + private volatile boolean inUse = false; + + public SimpleHttpConnectionManager() { + } + + /** + * @see HttpConnectionManager#getConnection(HostConfiguration) + */ + public HttpConnection getConnection(HostConfiguration hostConfiguration) { + return getConnection(hostConfiguration, 0); + } + + /** + * Gets the staleCheckingEnabled value to be set on HttpConnections that are created. + * + * @return true if stale checking will be enabled on HttpConections + * + * @see HttpConnection#isStaleCheckingEnabled() + * + * @deprecated Use {@link HttpConnectionManagerParams#isStaleCheckingEnabled()}, + * {@link HttpConnectionManager#getParams()}. + */ + public boolean isConnectionStaleCheckingEnabled() { + return this.params.isStaleCheckingEnabled(); + } + + /** + * Sets the staleCheckingEnabled value to be set on HttpConnections that are created. + * + * @param connectionStaleCheckingEnabled true if stale checking will be enabled + * on HttpConections + * + * @see HttpConnection#setStaleCheckingEnabled(boolean) + * + * @deprecated Use {@link HttpConnectionManagerParams#setStaleCheckingEnabled(boolean)}, + * {@link HttpConnectionManager#getParams()}. + */ + public void setConnectionStaleCheckingEnabled(boolean connectionStaleCheckingEnabled) { + this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled); + } + + /** + * @see HttpConnectionManager#getConnectionWithTimeout(HostConfiguration, long) + * + * @since 3.0 + */ + public HttpConnection getConnectionWithTimeout( + HostConfiguration hostConfiguration, long timeout) { + + if (httpConnection == null) { + httpConnection = new HttpConnection(hostConfiguration); + httpConnection.setHttpConnectionManager(this); + httpConnection.getParams().setDefaults(this.params); + } else { + + // make sure the host and proxy are correct for this connection + // close it and set the values if they are not + if (!hostConfiguration.hostEquals(httpConnection) + || !hostConfiguration.proxyEquals(httpConnection)) { + + if (httpConnection.isOpen()) { + httpConnection.close(); + } + + httpConnection.setHost(hostConfiguration.getHost()); + httpConnection.setPort(hostConfiguration.getPort()); + httpConnection.setProtocol(hostConfiguration.getProtocol()); + httpConnection.setLocalAddress(hostConfiguration.getLocalAddress()); + + httpConnection.setProxyHost(hostConfiguration.getProxyHost()); + httpConnection.setProxyPort(hostConfiguration.getProxyPort()); + } else { + finishLastResponse(httpConnection); + } + } + + // remove the connection from the timeout handler + idleStartTime = Long.MAX_VALUE; + + if (inUse) LOG.warn(MISUSE_MESSAGE); + inUse = true; + + return httpConnection; + } + + /** + * @see HttpConnectionManager#getConnection(HostConfiguration, long) + * + * @deprecated Use #getConnectionWithTimeout(HostConfiguration, long) + */ + public HttpConnection getConnection( + HostConfiguration hostConfiguration, long timeout) { + return getConnectionWithTimeout(hostConfiguration, timeout); + } + + /** + * @see HttpConnectionManager#releaseConnection(org.apache.commons.httpclient.HttpConnection) + */ + public void releaseConnection(HttpConnection conn) { + if (conn != httpConnection) { + throw new IllegalStateException("Unexpected release of an unknown connection."); + } + + finishLastResponse(httpConnection); + + inUse = false; + + // track the time the connection was made idle + idleStartTime = System.currentTimeMillis(); + } + + /** + * Returns {@link HttpConnectionManagerParams parameters} associated + * with this connection manager. + * + * @since 2.1 + * + * @see HttpConnectionManagerParams + */ + public HttpConnectionManagerParams getParams() { + return this.params; + } + + /** + * Assigns {@link HttpConnectionManagerParams parameters} for this + * connection manager. + * + * @since 2.1 + * + * @see HttpConnectionManagerParams + */ + public void setParams(final HttpConnectionManagerParams params) { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + this.params = params; + } + + /** + * @since 3.0 + */ + public void closeIdleConnections(long idleTimeout) { + long maxIdleTime = System.currentTimeMillis() - idleTimeout; + if (idleStartTime <= maxIdleTime) { + httpConnection.close(); + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/StatusLine.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/StatusLine.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/StatusLine.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,184 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/StatusLine.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * Represents a Status-Line as returned from a HTTP server. + * + * RFC2616 states + * the following regarding the Status-Line: + *
+ * 6.1 Status-Line
+ *
+ *  The first line of a Response message is the Status-Line, consisting
+ *  of the protocol version followed by a numeric status code and its
+ *  associated textual phrase, with each element separated by SP
+ *  characters. No CR or LF is allowed except in the final CRLF sequence.
+ *
+ *      Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+ * 
+ *

+ * This class is immutable and is inherently thread safe. + * + * @see HttpStatus + * @author Jeff Dever + * @author Mike Bowler + * @version $Id: StatusLine.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * @since 2.0 + */ +public class StatusLine { + + // ----------------------------------------------------- Instance Variables + + /** The original Status-Line. */ + private final String statusLine; + + /** The HTTP-Version. */ + private final String httpVersion; + + /** The Status-Code. */ + private final int statusCode; + + /** The Reason-Phrase. */ + private final String reasonPhrase; + + + // ----------------------------------------------------------- Constructors + + /** + * Default constructor. + * + * @param statusLine the status line returned from the HTTP server + * @throws HttpException if the status line is invalid + */ + public StatusLine(final String statusLine) throws HttpException { + + int length = statusLine.length(); + int at = 0; + int start = 0; + try { + while (Character.isWhitespace(statusLine.charAt(at))) { + ++at; + ++start; + } + if (!"HTTP".equals(statusLine.substring(at, at += 4))) { + throw new HttpException("Status-Line '" + statusLine + + "' does not start with HTTP"); + } + //handle the HTTP-Version + at = statusLine.indexOf(" ", at); + if (at <= 0) { + throw new ProtocolException( + "Unable to parse HTTP-Version from the status line: '" + + statusLine + "'"); + } + this.httpVersion = (statusLine.substring(start, at)).toUpperCase(); + + //advance through spaces + while (statusLine.charAt(at) == ' ') { + at++; + } + + //handle the Status-Code + int to = statusLine.indexOf(" ", at); + if (to < 0) { + to = length; + } + try { + this.statusCode = Integer.parseInt(statusLine.substring(at, to)); + } catch (NumberFormatException e) { + throw new ProtocolException( + "Unable to parse status code from status line: '" + + statusLine + "'"); + } + //handle the Reason-Phrase + at = to + 1; + if (at < length) { + this.reasonPhrase = statusLine.substring(at).trim(); + } else { + this.reasonPhrase = ""; + } + } catch (StringIndexOutOfBoundsException e) { + throw new HttpException("Status-Line '" + statusLine + "' is not valid"); + } + //save the original Status-Line + this.statusLine = statusLine; + } + + + // --------------------------------------------------------- Public Methods + + /** + * @return the Status-Code + */ + public final int getStatusCode() { + return statusCode; + } + + /** + * @return the HTTP-Version + */ + public final String getHttpVersion() { + return httpVersion; + } + + /** + * @return the Reason-Phrase + */ + public final String getReasonPhrase() { + return reasonPhrase; + } + + /** + * Return a string representation of this object. + * @return a string represenation of this object. + */ + public final String toString() { + return statusLine; + } + + /** + * Tests if the string starts with 'HTTP' signature. + * @param s string to test + * @return true if the line starts with 'HTTP' + * signature, false otherwise. + */ + public static boolean startsWithHTTP(final String s) { + try { + int at = 0; + while (Character.isWhitespace(s.charAt(at))) { + ++at; + } + return ("HTTP".equals(s.substring(at, at + 4))); + } catch (StringIndexOutOfBoundsException e) { + return false; + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URI.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URI.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URI.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,3956 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URI.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Locale; +import java.util.BitSet; +import java.util.Hashtable; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.net.URLCodec; +import org.apache.commons.httpclient.util.EncodingUtil; + +/** + * The interface for the URI(Uniform Resource Identifiers) version of RFC 2396. + * This class has the purpose of supportting of parsing a URI reference to + * extend any specific protocols, the character encoding of the protocol to + * be transported and the charset of the document. + *

+ * A URI is always in an "escaped" form, since escaping or unescaping a + * completed URI might change its semantics. + *

+ * Implementers should be careful not to escape or unescape the same string + * more than once, since unescaping an already unescaped string might lead to + * misinterpreting a percent data character as another escaped character, + * or vice versa in the case of escaping an already escaped string. + *

+ * In order to avoid these problems, data types used as follows: + *

+ *   URI character sequence: char
+ *   octet sequence: byte
+ *   original character sequence: String
+ * 

+ * + * So, a URI is a sequence of characters as an array of a char type, which + * is not always represented as a sequence of octets as an array of byte. + *

+ * + * URI Syntactic Components + *

+ * - In general, written as follows:
+ *   Absolute URI = <scheme>:<scheme-specific-part>
+ *   Generic URI = <scheme>://<authority><path>?<query>
+ *
+ * - Syntax
+ *   absoluteURI   = scheme ":" ( hier_part | opaque_part )
+ *   hier_part     = ( net_path | abs_path ) [ "?" query ]
+ *   net_path      = "//" authority [ abs_path ]
+ *   abs_path      = "/"  path_segments
+ * 

+ * + * The following examples illustrate URI that are in common use. + *

+ * ftp://ftp.is.co.za/rfc/rfc1808.txt
+ *    -- ftp scheme for File Transfer Protocol services
+ * gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
+ *    -- gopher scheme for Gopher and Gopher+ Protocol services
+ * http://www.math.uio.no/faq/compression-faq/part1.html
+ *    -- http scheme for Hypertext Transfer Protocol services
+ * mailto:mduerst@ifi.unizh.ch
+ *    -- mailto scheme for electronic mail addresses
+ * news:comp.infosystems.www.servers.unix
+ *    -- news scheme for USENET news groups and articles
+ * telnet://melvyl.ucop.edu/
+ *    -- telnet scheme for interactive services via the TELNET Protocol
+ * 
+ * Please, notice that there are many modifications from URL(RFC 1738) and + * relative URL(RFC 1808). + *

+ * The expressions for a URI + *

+ * For escaped URI forms
+ *  - URI(char[]) // constructor
+ *  - char[] getRawXxx() // method
+ *  - String getEscapedXxx() // method
+ *  - String toString() // method
+ * 

+ * For unescaped URI forms + * - URI(String) // constructor + * - String getXXX() // method + *

+ * + * @author Sung-Gu + * @author Mike Bowler + * @version $Revision: 1.1 $ $Date: 2002/03/14 15:14:01 + */ +public class URI implements Cloneable, Comparable, Serializable { + + + // ----------------------------------------------------------- Constructors + + /** Create an instance as an internal use */ + protected URI() { + } + + /** + * Construct a URI from a string with the given charset. The input string can + * be either in escaped or unescaped form. + * + * @param s URI character sequence + * @param escaped true if URI character sequence is in escaped form. + * false otherwise. + * @param charset the charset string to do escape encoding, if required + * + * @throws URIException If the URI cannot be created. + * @throws NullPointerException if input string is null + * + * @see #getProtocolCharset + * + * @since 3.0 + */ + public URI(String s, boolean escaped, String charset) + throws URIException, NullPointerException { + protocolCharset = charset; + parseUriReference(s, escaped); + } + + /** + * Construct a URI from a string with the given charset. The input string can + * be either in escaped or unescaped form. + * + * @param s URI character sequence + * @param escaped true if URI character sequence is in escaped form. + * false otherwise. + * + * @throws URIException If the URI cannot be created. + * @throws NullPointerException if input string is null + * + * @see #getProtocolCharset + * + * @since 3.0 + */ + public URI(String s, boolean escaped) + throws URIException, NullPointerException { + parseUriReference(s, escaped); + } + + /** + * Construct a URI as an escaped form of a character array with the given + * charset. + * + * @param escaped the URI character sequence + * @param charset the charset string to do escape encoding + * @throws URIException If the URI cannot be created. + * @throws NullPointerException if escaped is null + * @see #getProtocolCharset + * + * @deprecated Use #URI(String, boolean, String) + */ + public URI(char[] escaped, String charset) + throws URIException, NullPointerException { + protocolCharset = charset; + parseUriReference(new String(escaped), true); + } + + + /** + * Construct a URI as an escaped form of a character array. + * An URI can be placed within double-quotes or angle brackets like + * "http://test.com/" and <http://test.com/> + * + * @param escaped the URI character sequence + * @throws URIException If the URI cannot be created. + * @throws NullPointerException if escaped is null + * @see #getDefaultProtocolCharset + * + * @deprecated Use #URI(String, boolean) + */ + public URI(char[] escaped) + throws URIException, NullPointerException { + parseUriReference(new String(escaped), true); + } + + + /** + * Construct a URI from the given string with the given charset. + * + * @param original the string to be represented to URI character sequence + * It is one of absoluteURI and relativeURI. + * @param charset the charset string to do escape encoding + * @throws URIException If the URI cannot be created. + * @see #getProtocolCharset + * + * @deprecated Use #URI(String, boolean, String) + */ + public URI(String original, String charset) throws URIException { + protocolCharset = charset; + parseUriReference(original, false); + } + + + /** + * Construct a URI from the given string. + *

+     *   URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+     * 

+ * An URI can be placed within double-quotes or angle brackets like + * "http://test.com/" and <http://test.com/> + * + * @param original the string to be represented to URI character sequence + * It is one of absoluteURI and relativeURI. + * @throws URIException If the URI cannot be created. + * @see #getDefaultProtocolCharset + * + * @deprecated Use #URI(String, boolean) + */ + public URI(String original) throws URIException { + parseUriReference(original, false); + } + + + /** + * Construct a general URI from the given components. + *

+     *   URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+     *   absoluteURI   = scheme ":" ( hier_part | opaque_part )
+     *   opaque_part   = uric_no_slash *uric
+     * 

+ * It's for absolute URI = <scheme>:<scheme-specific-part># + * <fragment>. + * + * @param scheme the scheme string + * @param schemeSpecificPart scheme_specific_part + * @param fragment the fragment string + * @throws URIException If the URI cannot be created. + * @see #getDefaultProtocolCharset + */ + public URI(String scheme, String schemeSpecificPart, String fragment) + throws URIException { + + // validate and contruct the URI character sequence + if (scheme == null) { + throw new URIException(URIException.PARSING, "scheme required"); + } + char[] s = scheme.toLowerCase().toCharArray(); + if (validate(s, URI.scheme)) { + _scheme = s; // is_absoluteURI + } else { + throw new URIException(URIException.PARSING, "incorrect scheme"); + } + _opaque = encode(schemeSpecificPart, allowed_opaque_part, + getProtocolCharset()); + // Set flag + _is_opaque_part = true; + _fragment = fragment.toCharArray(); + + setURI(); + } + + + /** + * Construct a general URI from the given components. + *

+     *   URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+     *   absoluteURI   = scheme ":" ( hier_part | opaque_part )
+     *   relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
+     *   hier_part     = ( net_path | abs_path ) [ "?" query ]
+     * 

+ * It's for absolute URI = <scheme>:<path>?<query>#< + * fragment> and relative URI = <path>?<query>#<fragment + * >. + * + * @param scheme the scheme string + * @param authority the authority string + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If the new URI cannot be created. + * @see #getDefaultProtocolCharset + */ + public URI(String scheme, String authority, String path, String query, + String fragment) throws URIException { + + // validate and contruct the URI character sequence + StringBuffer buff = new StringBuffer(); + if (scheme != null) { + buff.append(scheme); + buff.append(':'); + } + if (authority != null) { + buff.append("//"); + buff.append(authority); + } + if (path != null) { // accept empty path + if ((scheme != null || authority != null) + && !path.startsWith("/")) { + throw new URIException(URIException.PARSING, + "abs_path requested"); + } + buff.append(path); + } + if (query != null) { + buff.append('?'); + buff.append(query); + } + if (fragment != null) { + buff.append('#'); + buff.append(fragment); + } + parseUriReference(buff.toString(), false); + } + + + /** + * Construct a general URI from the given components. + * + * @param scheme the scheme string + * @param userinfo the userinfo string + * @param host the host string + * @param port the port number + * @throws URIException If the new URI cannot be created. + * @see #getDefaultProtocolCharset + */ + public URI(String scheme, String userinfo, String host, int port) + throws URIException { + + this(scheme, userinfo, host, port, null, null, null); + } + + + /** + * Construct a general URI from the given components. + * + * @param scheme the scheme string + * @param userinfo the userinfo string + * @param host the host string + * @param port the port number + * @param path the path string + * @throws URIException If the new URI cannot be created. + * @see #getDefaultProtocolCharset + */ + public URI(String scheme, String userinfo, String host, int port, + String path) throws URIException { + + this(scheme, userinfo, host, port, path, null, null); + } + + + /** + * Construct a general URI from the given components. + * + * @param scheme the scheme string + * @param userinfo the userinfo string + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @throws URIException If the new URI cannot be created. + * @see #getDefaultProtocolCharset + */ + public URI(String scheme, String userinfo, String host, int port, + String path, String query) throws URIException { + + this(scheme, userinfo, host, port, path, query, null); + } + + + /** + * Construct a general URI from the given components. + * + * @param scheme the scheme string + * @param userinfo the userinfo string + * @param host the host string + * @param port the port number + * @param path the path string + * @param query the query string + * @param fragment the fragment string + * @throws URIException If the new URI cannot be created. + * @see #getDefaultProtocolCharset + */ + public URI(String scheme, String userinfo, String host, int port, + String path, String query, String fragment) throws URIException { + + this(scheme, (host == null) ? null + : ((userinfo != null) ? userinfo + '@' : "") + host + + ((port != -1) ? ":" + port : ""), path, query, fragment); + } + + + /** + * Construct a general URI from the given components. + * + * @param scheme the scheme string + * @param host the host string + * @param path the path string + * @param fragment the fragment string + * @throws URIException If the new URI cannot be created. + * @see #getDefaultProtocolCharset + */ + public URI(String scheme, String host, String path, String fragment) + throws URIException { + + this(scheme, host, path, null, fragment); + } + + + /** + * Construct a general URI with the given relative URI string. + * + * @param base the base URI + * @param relative the relative URI string + * @throws URIException If the new URI cannot be created. + * + * @deprecated Use #URI(URI, String, boolean) + */ + public URI(URI base, String relative) throws URIException { + this(base, new URI(relative)); + } + + + /** + * Construct a general URI with the given relative URI string. + * + * @param base the base URI + * @param relative the relative URI string + * @param escaped true if URI character sequence is in escaped form. + * false otherwise. + * + * @throws URIException If the new URI cannot be created. + * + * @since 3.0 + */ + public URI(URI base, String relative, boolean escaped) throws URIException { + this(base, new URI(relative, escaped)); + } + + + /** + * Construct a general URI with the given relative URI. + *

+     *   URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+     *   relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
+     * 

+ * Resolving Relative References to Absolute Form. + * + * Examples of Resolving Relative URI References + * + * Within an object with a well-defined base URI of + *

+     *   http://a/b/c/d;p?q
+     * 

+ * the relative URI would be resolved as follows: + * + * Normal Examples + * + *

+     *   g:h           =  g:h
+     *   g             =  http://a/b/c/g
+     *   ./g           =  http://a/b/c/g
+     *   g/            =  http://a/b/c/g/
+     *   /g            =  http://a/g
+     *   //g           =  http://g
+     *   ?y            =  http://a/b/c/?y
+     *   g?y           =  http://a/b/c/g?y
+     *   #s            =  (current document)#s
+     *   g#s           =  http://a/b/c/g#s
+     *   g?y#s         =  http://a/b/c/g?y#s
+     *   ;x            =  http://a/b/c/;x
+     *   g;x           =  http://a/b/c/g;x
+     *   g;x?y#s       =  http://a/b/c/g;x?y#s
+     *   .             =  http://a/b/c/
+     *   ./            =  http://a/b/c/
+     *   ..            =  http://a/b/
+     *   ../           =  http://a/b/
+     *   ../g          =  http://a/b/g
+     *   ../..         =  http://a/
+     *   ../../        =  http://a/ 
+     *   ../../g       =  http://a/g
+     * 

+ * + * Some URI schemes do not allow a hierarchical syntax matching the + * syntax, and thus cannot use relative references. + * + * @param base the base URI + * @param relative the relative URI + * @throws URIException If the new URI cannot be created. + */ + public URI(URI base, URI relative) throws URIException { + + if (base._scheme == null) { + throw new URIException(URIException.PARSING, "base URI required"); + } + if (base._scheme != null) { + this._scheme = base._scheme; + this._authority = base._authority; + } + if (base._is_opaque_part || relative._is_opaque_part) { + this._scheme = base._scheme; + this._is_opaque_part = base._is_opaque_part + || relative._is_opaque_part; + this._opaque = relative._opaque; + this._fragment = relative._fragment; + this.setURI(); + return; + } + if (relative._scheme != null) { + this._scheme = relative._scheme; + this._is_net_path = relative._is_net_path; + this._authority = relative._authority; + if (relative._is_server) { + this._is_server = relative._is_server; + this._userinfo = relative._userinfo; + this._host = relative._host; + this._port = relative._port; + } else if (relative._is_reg_name) { + this._is_reg_name = relative._is_reg_name; + } + this._is_abs_path = relative._is_abs_path; + this._is_rel_path = relative._is_rel_path; + this._path = relative._path; + } else if (base._authority != null && relative._scheme == null) { + this._is_net_path = base._is_net_path; + this._authority = base._authority; + if (base._is_server) { + this._is_server = base._is_server; + this._userinfo = base._userinfo; + this._host = base._host; + this._port = base._port; + } else if (base._is_reg_name) { + this._is_reg_name = base._is_reg_name; + } + } + if (relative._authority != null) { + this._is_net_path = relative._is_net_path; + this._authority = relative._authority; + if (relative._is_server) { + this._is_server = relative._is_server; + this._userinfo = relative._userinfo; + this._host = relative._host; + this._port = relative._port; + } else if (relative._is_reg_name) { + this._is_reg_name = relative._is_reg_name; + } + this._is_abs_path = relative._is_abs_path; + this._is_rel_path = relative._is_rel_path; + this._path = relative._path; + } + // resolve the path and query if necessary + if (relative._scheme == null && relative._authority == null) { + if ((relative._path == null || relative._path.length == 0) + && relative._query == null) { + // handle a reference to the current document, see RFC 2396 + // section 5.2 step 2 + this._path = base._path; + this._query = base._query; + } else { + this._path = resolvePath(base._path, relative._path); + } + } + // base._query removed + if (relative._query != null) { + this._query = relative._query; + } + // base._fragment removed + if (relative._fragment != null) { + this._fragment = relative._fragment; + } + this.setURI(); + // reparse the newly built URI, this will ensure that all flags are set correctly. + // TODO there must be a better way to do this + parseUriReference(new String(_uri), true); + } + + // --------------------------------------------------- Instance Variables + + /** Version ID for serialization */ + static final long serialVersionUID = 604752400577948726L; + + + /** + * Cache the hash code for this URI. + */ + protected int hash = 0; + + + /** + * This Uniform Resource Identifier (URI). + * The URI is always in an "escaped" form, since escaping or unescaping + * a completed URI might change its semantics. + */ + protected char[] _uri = null; + + + /** + * The charset of the protocol used by this URI instance. + */ + protected String protocolCharset = null; + + + /** + * The default charset of the protocol. RFC 2277, 2396 + */ + protected static String defaultProtocolCharset = "UTF-8"; + + + /** + * The default charset of the document. RFC 2277, 2396 + * The platform's charset is used for the document by default. + */ + protected static String defaultDocumentCharset = null; + protected static String defaultDocumentCharsetByLocale = null; + protected static String defaultDocumentCharsetByPlatform = null; + // Static initializer for defaultDocumentCharset + static { + Locale locale = Locale.getDefault(); + // in order to support backward compatiblity + if (locale != null) { + defaultDocumentCharsetByLocale = + LocaleToCharsetMap.getCharset(locale); + // set the default document charset + defaultDocumentCharset = defaultDocumentCharsetByLocale; + } + // in order to support platform encoding + try { + defaultDocumentCharsetByPlatform = System.getProperty("file.encoding"); + } catch (SecurityException ignore) { + } + if (defaultDocumentCharset == null) { + // set the default document charset + defaultDocumentCharset = defaultDocumentCharsetByPlatform; + } + } + + + /** + * The scheme. + */ + protected char[] _scheme = null; + + + /** + * The opaque. + */ + protected char[] _opaque = null; + + + /** + * The authority. + */ + protected char[] _authority = null; + + + /** + * The userinfo. + */ + protected char[] _userinfo = null; + + + /** + * The host. + */ + protected char[] _host = null; + + + /** + * The port. + */ + protected int _port = -1; + + + /** + * The path. + */ + protected char[] _path = null; + + + /** + * The query. + */ + protected char[] _query = null; + + + /** + * The fragment. + */ + protected char[] _fragment = null; + + + /** + * The root path. + */ + protected static char[] rootPath = { '/' }; + + // ---------------------- Generous characters for each component validation + + /** + * The percent "%" character always has the reserved purpose of being the + * escape indicator, it must be escaped as "%25" in order to be used as + * data within a URI. + */ + protected static final BitSet percent = new BitSet(256); + // Static initializer for percent + static { + percent.set('%'); + } + + + /** + * BitSet for digit. + *

+     * digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+     *            "8" | "9"
+     * 

+ */ + protected static final BitSet digit = new BitSet(256); + // Static initializer for digit + static { + for (int i = '0'; i <= '9'; i++) { + digit.set(i); + } + } + + + /** + * BitSet for alpha. + *

+     * alpha         = lowalpha | upalpha
+     * 

+ */ + protected static final BitSet alpha = new BitSet(256); + // Static initializer for alpha + static { + for (int i = 'a'; i <= 'z'; i++) { + alpha.set(i); + } + for (int i = 'A'; i <= 'Z'; i++) { + alpha.set(i); + } + } + + + /** + * BitSet for alphanum (join of alpha & digit). + *

+     *  alphanum      = alpha | digit
+     * 

+ */ + protected static final BitSet alphanum = new BitSet(256); + // Static initializer for alphanum + static { + alphanum.or(alpha); + alphanum.or(digit); + } + + + /** + * BitSet for hex. + *

+     * hex           = digit | "A" | "B" | "C" | "D" | "E" | "F" |
+     *                         "a" | "b" | "c" | "d" | "e" | "f"
+     * 

+ */ + protected static final BitSet hex = new BitSet(256); + // Static initializer for hex + static { + hex.or(digit); + for (int i = 'a'; i <= 'f'; i++) { + hex.set(i); + } + for (int i = 'A'; i <= 'F'; i++) { + hex.set(i); + } + } + + + /** + * BitSet for escaped. + *

+     * escaped       = "%" hex hex
+     * 

+ */ + protected static final BitSet escaped = new BitSet(256); + // Static initializer for escaped + static { + escaped.or(percent); + escaped.or(hex); + } + + + /** + * BitSet for mark. + *

+     * mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
+     *                 "(" | ")"
+     * 

+ */ + protected static final BitSet mark = new BitSet(256); + // Static initializer for mark + static { + mark.set('-'); + mark.set('_'); + mark.set('.'); + mark.set('!'); + mark.set('~'); + mark.set('*'); + mark.set('\''); + mark.set('('); + mark.set(')'); + } + + + /** + * Data characters that are allowed in a URI but do not have a reserved + * purpose are called unreserved. + *

+     * unreserved    = alphanum | mark
+     * 

+ */ + protected static final BitSet unreserved = new BitSet(256); + // Static initializer for unreserved + static { + unreserved.or(alphanum); + unreserved.or(mark); + } + + + /** + * BitSet for reserved. + *

+     * reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+     *                 "$" | ","
+     * 

+ */ + protected static final BitSet reserved = new BitSet(256); + // Static initializer for reserved + static { + reserved.set(';'); + reserved.set('/'); + reserved.set('?'); + reserved.set(':'); + reserved.set('@'); + reserved.set('&'); + reserved.set('='); + reserved.set('+'); + reserved.set('$'); + reserved.set(','); + } + + + /** + * BitSet for uric. + *

+     * uric          = reserved | unreserved | escaped
+     * 

+ */ + protected static final BitSet uric = new BitSet(256); + // Static initializer for uric + static { + uric.or(reserved); + uric.or(unreserved); + uric.or(escaped); + } + + + /** + * BitSet for fragment (alias for uric). + *

+     * fragment      = *uric
+     * 

+ */ + protected static final BitSet fragment = uric; + + + /** + * BitSet for query (alias for uric). + *

+     * query         = *uric
+     * 

+ */ + protected static final BitSet query = uric; + + + /** + * BitSet for pchar. + *

+     * pchar         = unreserved | escaped |
+     *                 ":" | "@" | "&" | "=" | "+" | "$" | ","
+     * 

+ */ + protected static final BitSet pchar = new BitSet(256); + // Static initializer for pchar + static { + pchar.or(unreserved); + pchar.or(escaped); + pchar.set(':'); + pchar.set('@'); + pchar.set('&'); + pchar.set('='); + pchar.set('+'); + pchar.set('$'); + pchar.set(','); + } + + + /** + * BitSet for param (alias for pchar). + *

+     * param         = *pchar
+     * 

+ */ + protected static final BitSet param = pchar; + + + /** + * BitSet for segment. + *

+     * segment       = *pchar *( ";" param )
+     * 

+ */ + protected static final BitSet segment = new BitSet(256); + // Static initializer for segment + static { + segment.or(pchar); + segment.set(';'); + segment.or(param); + } + + + /** + * BitSet for path segments. + *

+     * path_segments = segment *( "/" segment )
+     * 

+ */ + protected static final BitSet path_segments = new BitSet(256); + // Static initializer for path_segments + static { + path_segments.set('/'); + path_segments.or(segment); + } + + + /** + * URI absolute path. + *

+     * abs_path      = "/"  path_segments
+     * 

+ */ + protected static final BitSet abs_path = new BitSet(256); + // Static initializer for abs_path + static { + abs_path.set('/'); + abs_path.or(path_segments); + } + + + /** + * URI bitset for encoding typical non-slash characters. + *

+     * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
+     *                 "&" | "=" | "+" | "$" | ","
+     * 

+ */ + protected static final BitSet uric_no_slash = new BitSet(256); + // Static initializer for uric_no_slash + static { + uric_no_slash.or(unreserved); + uric_no_slash.or(escaped); + uric_no_slash.set(';'); + uric_no_slash.set('?'); + uric_no_slash.set(';'); + uric_no_slash.set('@'); + uric_no_slash.set('&'); + uric_no_slash.set('='); + uric_no_slash.set('+'); + uric_no_slash.set('$'); + uric_no_slash.set(','); + } + + + /** + * URI bitset that combines uric_no_slash and uric. + *

+     * opaque_part   = uric_no_slash *uric
+     * 

+ */ + protected static final BitSet opaque_part = new BitSet(256); + // Static initializer for opaque_part + static { + // it's generous. because first character must not include a slash + opaque_part.or(uric_no_slash); + opaque_part.or(uric); + } + + + /** + * URI bitset that combines absolute path and opaque part. + *

+     * path          = [ abs_path | opaque_part ]
+     * 

+ */ + protected static final BitSet path = new BitSet(256); + // Static initializer for path + static { + path.or(abs_path); + path.or(opaque_part); + } + + + /** + * Port, a logical alias for digit. + */ + protected static final BitSet port = digit; + + + /** + * Bitset that combines digit and dot fo IPv$address. + *

+     * IPv4address   = 1*digit "." 1*digit "." 1*digit "." 1*digit
+     * 

+ */ + protected static final BitSet IPv4address = new BitSet(256); + // Static initializer for IPv4address + static { + IPv4address.or(digit); + IPv4address.set('.'); + } + + + /** + * RFC 2373. + *

+     * IPv6address = hexpart [ ":" IPv4address ]
+     * 

+ */ + protected static final BitSet IPv6address = new BitSet(256); + // Static initializer for IPv6address reference + static { + IPv6address.or(hex); // hexpart + IPv6address.set(':'); + IPv6address.or(IPv4address); + } + + + /** + * RFC 2732, 2373. + *

+     * IPv6reference   = "[" IPv6address "]"
+     * 

+ */ + protected static final BitSet IPv6reference = new BitSet(256); + // Static initializer for IPv6reference + static { + IPv6reference.set('['); + IPv6reference.or(IPv6address); + IPv6reference.set(']'); + } + + + /** + * BitSet for toplabel. + *

+     * toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
+     * 

+ */ + protected static final BitSet toplabel = new BitSet(256); + // Static initializer for toplabel + static { + toplabel.or(alphanum); + toplabel.set('-'); + } + + + /** + * BitSet for domainlabel. + *

+     * domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
+     * 

+ */ + protected static final BitSet domainlabel = toplabel; + + + /** + * BitSet for hostname. + *

+     * hostname      = *( domainlabel "." ) toplabel [ "." ]
+     * 

+ */ + protected static final BitSet hostname = new BitSet(256); + // Static initializer for hostname + static { + hostname.or(toplabel); + // hostname.or(domainlabel); + hostname.set('.'); + } + + + /** + * BitSet for host. + *

+     * host          = hostname | IPv4address | IPv6reference
+     * 

+ */ + protected static final BitSet host = new BitSet(256); + // Static initializer for host + static { + host.or(hostname); + // host.or(IPv4address); + host.or(IPv6reference); // IPv4address + } + + + /** + * BitSet for hostport. + *

+     * hostport      = host [ ":" port ]
+     * 

+ */ + protected static final BitSet hostport = new BitSet(256); + // Static initializer for hostport + static { + hostport.or(host); + hostport.set(':'); + hostport.or(port); + } + + + /** + * Bitset for userinfo. + *

+     * userinfo      = *( unreserved | escaped |
+     *                    ";" | ":" | "&" | "=" | "+" | "$" | "," )
+     * 

+ */ + protected static final BitSet userinfo = new BitSet(256); + // Static initializer for userinfo + static { + userinfo.or(unreserved); + userinfo.or(escaped); + userinfo.set(';'); + userinfo.set(':'); + userinfo.set('&'); + userinfo.set('='); + userinfo.set('+'); + userinfo.set('$'); + userinfo.set(','); + } + + + /** + * BitSet for within the userinfo component like user and password. + */ + public static final BitSet within_userinfo = new BitSet(256); + // Static initializer for within_userinfo + static { + within_userinfo.or(userinfo); + within_userinfo.clear(';'); // reserved within authority + within_userinfo.clear(':'); + within_userinfo.clear('@'); + within_userinfo.clear('?'); + within_userinfo.clear('/'); + } + + + /** + * Bitset for server. + *

+     * server        = [ [ userinfo "@" ] hostport ]
+     * 

+ */ + protected static final BitSet server = new BitSet(256); + // Static initializer for server + static { + server.or(userinfo); + server.set('@'); + server.or(hostport); + } + + + /** + * BitSet for reg_name. + *

+     * reg_name      = 1*( unreserved | escaped | "$" | "," |
+     *                     ";" | ":" | "@" | "&" | "=" | "+" )
+     * 

+ */ + protected static final BitSet reg_name = new BitSet(256); + // Static initializer for reg_name + static { + reg_name.or(unreserved); + reg_name.or(escaped); + reg_name.set('$'); + reg_name.set(','); + reg_name.set(';'); + reg_name.set(':'); + reg_name.set('@'); + reg_name.set('&'); + reg_name.set('='); + reg_name.set('+'); + } + + + /** + * BitSet for authority. + *

+     * authority     = server | reg_name
+     * 

+ */ + protected static final BitSet authority = new BitSet(256); + // Static initializer for authority + static { + authority.or(server); + authority.or(reg_name); + } + + + /** + * BitSet for scheme. + *

+     * scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+     * 

+ */ + protected static final BitSet scheme = new BitSet(256); + // Static initializer for scheme + static { + scheme.or(alpha); + scheme.or(digit); + scheme.set('+'); + scheme.set('-'); + scheme.set('.'); + } + + + /** + * BitSet for rel_segment. + *

+     * rel_segment   = 1*( unreserved | escaped |
+     *                     ";" | "@" | "&" | "=" | "+" | "$" | "," )
+     * 

+ */ + protected static final BitSet rel_segment = new BitSet(256); + // Static initializer for rel_segment + static { + rel_segment.or(unreserved); + rel_segment.or(escaped); + rel_segment.set(';'); + rel_segment.set('@'); + rel_segment.set('&'); + rel_segment.set('='); + rel_segment.set('+'); + rel_segment.set('$'); + rel_segment.set(','); + } + + + /** + * BitSet for rel_path. + *

+     * rel_path      = rel_segment [ abs_path ]
+     * 

+ */ + protected static final BitSet rel_path = new BitSet(256); + // Static initializer for rel_path + static { + rel_path.or(rel_segment); + rel_path.or(abs_path); + } + + + /** + * BitSet for net_path. + *

+     * net_path      = "//" authority [ abs_path ]
+     * 

+ */ + protected static final BitSet net_path = new BitSet(256); + // Static initializer for net_path + static { + net_path.set('/'); + net_path.or(authority); + net_path.or(abs_path); + } + + + /** + * BitSet for hier_part. + *

+     * hier_part     = ( net_path | abs_path ) [ "?" query ]
+     * 

+ */ + protected static final BitSet hier_part = new BitSet(256); + // Static initializer for hier_part + static { + hier_part.or(net_path); + hier_part.or(abs_path); + // hier_part.set('?'); aleady included + hier_part.or(query); + } + + + /** + * BitSet for relativeURI. + *

+     * relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
+     * 

+ */ + protected static final BitSet relativeURI = new BitSet(256); + // Static initializer for relativeURI + static { + relativeURI.or(net_path); + relativeURI.or(abs_path); + relativeURI.or(rel_path); + // relativeURI.set('?'); aleady included + relativeURI.or(query); + } + + + /** + * BitSet for absoluteURI. + *

+     * absoluteURI   = scheme ":" ( hier_part | opaque_part )
+     * 

+ */ + protected static final BitSet absoluteURI = new BitSet(256); + // Static initializer for absoluteURI + static { + absoluteURI.or(scheme); + absoluteURI.set(':'); + absoluteURI.or(hier_part); + absoluteURI.or(opaque_part); + } + + + /** + * BitSet for URI-reference. + *

+     * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+     * 

+ */ + protected static final BitSet URI_reference = new BitSet(256); + // Static initializer for URI_reference + static { + URI_reference.or(absoluteURI); + URI_reference.or(relativeURI); + URI_reference.set('#'); + URI_reference.or(fragment); + } + + // ---------------------------- Characters disallowed within the URI syntax + // Excluded US-ASCII Characters are like control, space, delims and unwise + + /** + * BitSet for control. + */ + public static final BitSet control = new BitSet(256); + // Static initializer for control + static { + for (int i = 0; i <= 0x1F; i++) { + control.set(i); + } + control.set(0x7F); + } + + /** + * BitSet for space. + */ + public static final BitSet space = new BitSet(256); + // Static initializer for space + static { + space.set(0x20); + } + + + /** + * BitSet for delims. + */ + public static final BitSet delims = new BitSet(256); + // Static initializer for delims + static { + delims.set('<'); + delims.set('>'); + delims.set('#'); + delims.set('%'); + delims.set('"'); + } + + + /** + * BitSet for unwise. + */ + public static final BitSet unwise = new BitSet(256); + // Static initializer for unwise + static { + unwise.set('{'); + unwise.set('}'); + unwise.set('|'); + unwise.set('\\'); + unwise.set('^'); + unwise.set('['); + unwise.set(']'); + unwise.set('`'); + } + + + /** + * Disallowed rel_path before escaping. + */ + public static final BitSet disallowed_rel_path = new BitSet(256); + // Static initializer for disallowed_rel_path + static { + disallowed_rel_path.or(uric); + disallowed_rel_path.andNot(rel_path); + } + + + /** + * Disallowed opaque_part before escaping. + */ + public static final BitSet disallowed_opaque_part = new BitSet(256); + // Static initializer for disallowed_opaque_part + static { + disallowed_opaque_part.or(uric); + disallowed_opaque_part.andNot(opaque_part); + } + + // ----------------------- Characters allowed within and for each component + + /** + * Those characters that are allowed for the authority component. + */ + public static final BitSet allowed_authority = new BitSet(256); + // Static initializer for allowed_authority + static { + allowed_authority.or(authority); + allowed_authority.clear('%'); + } + + + /** + * Those characters that are allowed for the opaque_part. + */ + public static final BitSet allowed_opaque_part = new BitSet(256); + // Static initializer for allowed_opaque_part + static { + allowed_opaque_part.or(opaque_part); + allowed_opaque_part.clear('%'); + } + + + /** + * Those characters that are allowed for the reg_name. + */ + public static final BitSet allowed_reg_name = new BitSet(256); + // Static initializer for allowed_reg_name + static { + allowed_reg_name.or(reg_name); + // allowed_reg_name.andNot(percent); + allowed_reg_name.clear('%'); + } + + + /** + * Those characters that are allowed for the userinfo component. + */ + public static final BitSet allowed_userinfo = new BitSet(256); + // Static initializer for allowed_userinfo + static { + allowed_userinfo.or(userinfo); + // allowed_userinfo.andNot(percent); + allowed_userinfo.clear('%'); + } + + + /** + * Those characters that are allowed for within the userinfo component. + */ + public static final BitSet allowed_within_userinfo = new BitSet(256); + // Static initializer for allowed_within_userinfo + static { + allowed_within_userinfo.or(within_userinfo); + allowed_within_userinfo.clear('%'); + } + + + /** + * Those characters that are allowed for the IPv6reference component. + * The characters '[', ']' in IPv6reference should be excluded. + */ + public static final BitSet allowed_IPv6reference = new BitSet(256); + // Static initializer for allowed_IPv6reference + static { + allowed_IPv6reference.or(IPv6reference); + // allowed_IPv6reference.andNot(unwise); + allowed_IPv6reference.clear('['); + allowed_IPv6reference.clear(']'); + } + + + /** + * Those characters that are allowed for the host component. + * The characters '[', ']' in IPv6reference should be excluded. + */ + public static final BitSet allowed_host = new BitSet(256); + // Static initializer for allowed_host + static { + allowed_host.or(hostname); + allowed_host.or(allowed_IPv6reference); + } + + + /** + * Those characters that are allowed for the authority component. + */ + public static final BitSet allowed_within_authority = new BitSet(256); + // Static initializer for allowed_within_authority + static { + allowed_within_authority.or(server); + allowed_within_authority.or(reg_name); + allowed_within_authority.clear(';'); + allowed_within_authority.clear(':'); + allowed_within_authority.clear('@'); + allowed_within_authority.clear('?'); + allowed_within_authority.clear('/'); + } + + + /** + * Those characters that are allowed for the abs_path. + */ + public static final BitSet allowed_abs_path = new BitSet(256); + // Static initializer for allowed_abs_path + static { + allowed_abs_path.or(abs_path); + // allowed_abs_path.set('/'); // aleady included + allowed_abs_path.andNot(percent); + } + + + /** + * Those characters that are allowed for the rel_path. + */ + public static final BitSet allowed_rel_path = new BitSet(256); + // Static initializer for allowed_rel_path + static { + allowed_rel_path.or(rel_path); + allowed_rel_path.clear('%'); + } + + + /** + * Those characters that are allowed within the path. + */ + public static final BitSet allowed_within_path = new BitSet(256); + // Static initializer for allowed_within_path + static { + allowed_within_path.or(abs_path); + allowed_within_path.clear('/'); + allowed_within_path.clear(';'); + allowed_within_path.clear('='); + allowed_within_path.clear('?'); + } + + + /** + * Those characters that are allowed for the query component. + */ + public static final BitSet allowed_query = new BitSet(256); + // Static initializer for allowed_query + static { + allowed_query.or(uric); + allowed_query.clear('%'); + } + + + /** + * Those characters that are allowed within the query component. + */ + public static final BitSet allowed_within_query = new BitSet(256); + // Static initializer for allowed_within_query + static { + allowed_within_query.or(allowed_query); + allowed_within_query.andNot(reserved); // excluded 'reserved' + } + + + /** + * Those characters that are allowed for the fragment component. + */ + public static final BitSet allowed_fragment = new BitSet(256); + // Static initializer for allowed_fragment + static { + allowed_fragment.or(uric); + allowed_fragment.clear('%'); + } + + // ------------------------------------------- Flags for this URI-reference + + // TODO: Figure out what all these variables are for and provide javadoc + + // URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + // absoluteURI = scheme ":" ( hier_part | opaque_part ) + protected boolean _is_hier_part; + protected boolean _is_opaque_part; + // relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] + // hier_part = ( net_path | abs_path ) [ "?" query ] + protected boolean _is_net_path; + protected boolean _is_abs_path; + protected boolean _is_rel_path; + // net_path = "//" authority [ abs_path ] + // authority = server | reg_name + protected boolean _is_reg_name; + protected boolean _is_server; // = _has_server + // server = [ [ userinfo "@" ] hostport ] + // host = hostname | IPv4address | IPv6reference + protected boolean _is_hostname; + protected boolean _is_IPv4address; + protected boolean _is_IPv6reference; + + // ------------------------------------------ Character and escape encoding + + /** + * Encodes URI string. + * + * This is a two mapping, one from original characters to octets, and + * subsequently a second from octets to URI characters: + *

+     *   original character sequence->octet sequence->URI character sequence
+     * 

+ * + * An escaped octet is encoded as a character triplet, consisting of the + * percent character "%" followed by the two hexadecimal digits + * representing the octet code. For example, "%20" is the escaped + * encoding for the US-ASCII space character. + *

+ * Conversion from the local filesystem character set to UTF-8 will + * normally involve a two step process. First convert the local character + * set to the UCS; then convert the UCS to UTF-8. + * The first step in the process can be performed by maintaining a mapping + * table that includes the local character set code and the corresponding + * UCS code. + * The next step is to convert the UCS character code to the UTF-8 encoding. + *

+ * Mapping between vendor codepages can be done in a very similar manner + * as described above. + *

+ * The only time escape encodings can allowedly be made is when a URI is + * being created from its component parts. The escape and validate methods + * are internally performed within this method. + * + * @param original the original character sequence + * @param allowed those characters that are allowed within a component + * @param charset the protocol charset + * @return URI character sequence + * @throws URIException null component or unsupported character encoding + */ + + protected static char[] encode(String original, BitSet allowed, + String charset) throws URIException { + if (original == null) { + throw new IllegalArgumentException("Original string may not be null"); + } + if (allowed == null) { + throw new IllegalArgumentException("Allowed bitset may not be null"); + } + byte[] rawdata = URLCodec.encodeUrl(allowed, EncodingUtil.getBytes(original, charset)); + return EncodingUtil.getAsciiString(rawdata).toCharArray(); + } + + /** + * Decodes URI encoded string. + * + * This is a two mapping, one from URI characters to octets, and + * subsequently a second from octets to original characters: + *

+     *   URI character sequence->octet sequence->original character sequence
+     * 

+ * + * A URI must be separated into its components before the escaped + * characters within those components can be allowedly decoded. + *

+ * Notice that there is a chance that URI characters that are non UTF-8 + * may be parsed as valid UTF-8. A recent non-scientific analysis found + * that EUC encoded Japanese words had a 2.7% false reading; SJIS had a + * 0.0005% false reading; other encoding such as ASCII or KOI-8 have a 0% + * false reading. + *

+ * The percent "%" character always has the reserved purpose of being + * the escape indicator, it must be escaped as "%25" in order to be used + * as data within a URI. + *

+ * The unescape method is internally performed within this method. + * + * @param component the URI character sequence + * @param charset the protocol charset + * @return original character sequence + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + */ + protected static String decode(char[] component, String charset) + throws URIException { + if (component == null) { + throw new IllegalArgumentException("Component array of chars may not be null"); + } + return decode(new String(component), charset); + } + + /** + * Decodes URI encoded string. + * + * This is a two mapping, one from URI characters to octets, and + * subsequently a second from octets to original characters: + *

+     *   URI character sequence->octet sequence->original character sequence
+     * 

+ * + * A URI must be separated into its components before the escaped + * characters within those components can be allowedly decoded. + *

+ * Notice that there is a chance that URI characters that are non UTF-8 + * may be parsed as valid UTF-8. A recent non-scientific analysis found + * that EUC encoded Japanese words had a 2.7% false reading; SJIS had a + * 0.0005% false reading; other encoding such as ASCII or KOI-8 have a 0% + * false reading. + *

+ * The percent "%" character always has the reserved purpose of being + * the escape indicator, it must be escaped as "%25" in order to be used + * as data within a URI. + *

+ * The unescape method is internally performed within this method. + * + * @param component the URI character sequence + * @param charset the protocol charset + * @return original character sequence + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + * + * @since 3.0 + */ + protected static String decode(String component, String charset) + throws URIException { + if (component == null) { + throw new IllegalArgumentException("Component array of chars may not be null"); + } + byte[] rawdata = null; + try { + rawdata = URLCodec.decodeUrl(EncodingUtil.getAsciiBytes(component)); + } catch (DecoderException e) { + throw new URIException(e.getMessage()); + } + return EncodingUtil.getString(rawdata, charset); + } + /** + * Pre-validate the unescaped URI string within a specific component. + * + * @param component the component string within the component + * @param disallowed those characters disallowed within the component + * @return if true, it doesn't have the disallowed characters + * if false, the component is undefined or an incorrect one + */ + protected boolean prevalidate(String component, BitSet disallowed) { + // prevalidate the given component by disallowed characters + if (component == null) { + return false; // undefined + } + char[] target = component.toCharArray(); + for (int i = 0; i < target.length; i++) { + if (disallowed.get(target[i])) { + return false; + } + } + return true; + } + + + /** + * Validate the URI characters within a specific component. + * The component must be performed after escape encoding. Or it doesn't + * include escaped characters. + * + * @param component the characters sequence within the component + * @param generous those characters that are allowed within a component + * @return if true, it's the correct URI character sequence + */ + protected boolean validate(char[] component, BitSet generous) { + // validate each component by generous characters + return validate(component, 0, -1, generous); + } + + + /** + * Validate the URI characters within a specific component. + * The component must be performed after escape encoding. Or it doesn't + * include escaped characters. + *

+ * It's not that much strict, generous. The strict validation might be + * performed before being called this method. + * + * @param component the characters sequence within the component + * @param soffset the starting offset of the given component + * @param eoffset the ending offset of the given component + * if -1, it means the length of the component + * @param generous those characters that are allowed within a component + * @return if true, it's the correct URI character sequence + */ + protected boolean validate(char[] component, int soffset, int eoffset, + BitSet generous) { + // validate each component by generous characters + if (eoffset == -1) { + eoffset = component.length - 1; + } + for (int i = soffset; i <= eoffset; i++) { + if (!generous.get(component[i])) { + return false; + } + } + return true; + } + + + /** + * In order to avoid any possilbity of conflict with non-ASCII characters, + * Parse a URI reference as a String with the character + * encoding of the local system or the document. + *

+ * The following line is the regular expression for breaking-down a URI + * reference into its components. + *

+     *   ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+     *    12            3  4          5       6  7        8 9
+     * 

+ * For example, matching the above expression to + * http://jakarta.apache.org/ietf/uri/#Related + * results in the following subexpression matches: + *

+     *               $1 = http:
+     *  scheme    =  $2 = http
+     *               $3 = //jakarta.apache.org
+     *  authority =  $4 = jakarta.apache.org
+     *  path      =  $5 = /ietf/uri/
+     *               $6 = 
+     *  query     =  $7 = 
+     *               $8 = #Related
+     *  fragment  =  $9 = Related
+     * 

+ * + * @param original the original character sequence + * @param escaped true if original is escaped + * @throws URIException If an error occurs. + */ + protected void parseUriReference(String original, boolean escaped) + throws URIException { + + // validate and contruct the URI character sequence + if (original == null) { + throw new URIException("URI-Reference required"); + } + + /* @ + * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? + */ + String tmp = original.trim(); + + /* + * The length of the string sequence of characters. + * It may not be equal to the length of the byte array. + */ + int length = tmp.length(); + + /* + * Remove the delimiters like angle brackets around an URI. + */ + if (length > 0) { + char[] firstDelimiter = { tmp.charAt(0) }; + if (validate(firstDelimiter, delims)) { + if (length >= 2) { + char[] lastDelimiter = { tmp.charAt(length - 1) }; + if (validate(lastDelimiter, delims)) { + tmp = tmp.substring(1, length - 1); + length = length - 2; + } + } + } + } + + /* + * The starting index + */ + int from = 0; + + /* + * The test flag whether the URI is started from the path component. + */ + boolean isStartedFromPath = false; + int atColon = tmp.indexOf(':'); + int atSlash = tmp.indexOf('/'); + if (atColon <= 0 || (atSlash >= 0 && atSlash < atColon)) { + isStartedFromPath = true; + } + + /* + *

+         *     @@@@@@@@
+         *  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+         * 

+ */ + int at = indexFirstOf(tmp, isStartedFromPath ? "/?#" : ":/?#", from); + if (at == -1) { + at = 0; + } + + /* + * Parse the scheme. + *

+         *  scheme    =  $2 = http
+         *              @
+         *  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+         * 

+ */ + if (at > 0 && at < length && tmp.charAt(at) == ':') { + char[] target = tmp.substring(0, at).toLowerCase().toCharArray(); + if (validate(target, scheme)) { + _scheme = target; + } else { + throw new URIException("incorrect scheme"); + } + from = ++at; + } + + /* + * Parse the authority component. + *

+         *  authority =  $4 = jakarta.apache.org
+         *                  @@
+         *  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+         * 

+ */ + // Reset flags + _is_net_path = _is_abs_path = _is_rel_path = _is_hier_part = false; + if (0 <= at && at < length && tmp.charAt(at) == '/') { + // Set flag + _is_hier_part = true; + if (at + 2 < length && tmp.charAt(at + 1) == '/') { + // the temporary index to start the search from + int next = indexFirstOf(tmp, "/?#", at + 2); + if (next == -1) { + next = (tmp.substring(at + 2).length() == 0) ? at + 2 + : tmp.length(); + } + parseAuthority(tmp.substring(at + 2, next), escaped); + from = at = next; + // Set flag + _is_net_path = true; + } + if (from == at) { + // Set flag + _is_abs_path = true; + } + } + + /* + * Parse the path component. + *

+         *  path      =  $5 = /ietf/uri/
+         *                                @@@@@@
+         *  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+         * 

+ */ + if (from < length) { + // rel_path = rel_segment [ abs_path ] + int next = indexFirstOf(tmp, "?#", from); + if (next == -1) { + next = tmp.length(); + } + if (!_is_abs_path) { + if (!escaped + && prevalidate(tmp.substring(from, next), disallowed_rel_path) + || escaped + && validate(tmp.substring(from, next).toCharArray(), rel_path)) { + // Set flag + _is_rel_path = true; + } else if (!escaped + && prevalidate(tmp.substring(from, next), disallowed_opaque_part) + || escaped + && validate(tmp.substring(from, next).toCharArray(), opaque_part)) { + // Set flag + _is_opaque_part = true; + } else { + // the path component may be empty + _path = null; + } + } + if (escaped) { + setRawPath(tmp.substring(from, next).toCharArray()); + } else { + setPath(tmp.substring(from, next)); + } + at = next; + } + + // set the charset to do escape encoding + String charset = getProtocolCharset(); + + /* + * Parse the query component. + *

+         *  query     =  $7 = 
+         *                                        @@@@@@@@@
+         *  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+         * 

+ */ + if (0 <= at && at + 1 < length && tmp.charAt(at) == '?') { + int next = tmp.indexOf('#', at + 1); + if (next == -1) { + next = tmp.length(); + } + _query = (escaped) ? tmp.substring(at + 1, next).toCharArray() + : encode(tmp.substring(at + 1, next), allowed_query, charset); + at = next; + } + + /* + * Parse the fragment component. + *

+         *  fragment  =  $9 = Related
+         *                                                   @@@@@@@@
+         *  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+         * 

+ */ + if (0 <= at && at + 1 <= length && tmp.charAt(at) == '#') { + if (at + 1 == length) { // empty fragment + _fragment = "".toCharArray(); + } else { + _fragment = (escaped) ? tmp.substring(at + 1).toCharArray() + : encode(tmp.substring(at + 1), allowed_fragment, charset); + } + } + + // set this URI. + setURI(); + } + + + /** + * Get the earlier index that to be searched for the first occurrance in + * one of any of the given string. + * + * @param s the string to be indexed + * @param delims the delimiters used to index + * @return the earlier index if there are delimiters + */ + protected int indexFirstOf(String s, String delims) { + return indexFirstOf(s, delims, -1); + } + + + /** + * Get the earlier index that to be searched for the first occurrance in + * one of any of the given string. + * + * @param s the string to be indexed + * @param delims the delimiters used to index + * @param offset the from index + * @return the earlier index if there are delimiters + */ + protected int indexFirstOf(String s, String delims, int offset) { + if (s == null || s.length() == 0) { + return -1; + } + if (delims == null || delims.length() == 0) { + return -1; + } + // check boundaries + if (offset < 0) { + offset = 0; + } else if (offset > s.length()) { + return -1; + } + // s is never null + int min = s.length(); + char[] delim = delims.toCharArray(); + for (int i = 0; i < delim.length; i++) { + int at = s.indexOf(delim[i], offset); + if (at >= 0 && at < min) { + min = at; + } + } + return (min == s.length()) ? -1 : min; + } + + + /** + * Get the earlier index that to be searched for the first occurrance in + * one of any of the given array. + * + * @param s the character array to be indexed + * @param delim the delimiter used to index + * @return the ealier index if there are a delimiter + */ + protected int indexFirstOf(char[] s, char delim) { + return indexFirstOf(s, delim, 0); + } + + + /** + * Get the earlier index that to be searched for the first occurrance in + * one of any of the given array. + * + * @param s the character array to be indexed + * @param delim the delimiter used to index + * @param offset The offset. + * @return the ealier index if there is a delimiter + */ + protected int indexFirstOf(char[] s, char delim, int offset) { + if (s == null || s.length == 0) { + return -1; + } + // check boundaries + if (offset < 0) { + offset = 0; + } else if (offset > s.length) { + return -1; + } + for (int i = offset; i < s.length; i++) { + if (s[i] == delim) { + return i; + } + } + return -1; + } + + + /** + * Parse the authority component. + * + * @param original the original character sequence of authority component + * @param escaped true if original is escaped + * @throws URIException If an error occurs. + */ + protected void parseAuthority(String original, boolean escaped) + throws URIException { + + // Reset flags + _is_reg_name = _is_server = + _is_hostname = _is_IPv4address = _is_IPv6reference = false; + + // set the charset to do escape encoding + String charset = getProtocolCharset(); + + boolean hasPort = true; + int from = 0; + int next = original.indexOf('@'); + if (next != -1) { // neither -1 and 0 + // each protocol extented from URI supports the specific userinfo + _userinfo = (escaped) ? original.substring(0, next).toCharArray() + : encode(original.substring(0, next), allowed_userinfo, + charset); + from = next + 1; + } + next = original.indexOf('[', from); + if (next >= from) { + next = original.indexOf(']', from); + if (next == -1) { + throw new URIException(URIException.PARSING, "IPv6reference"); + } else { + next++; + } + // In IPv6reference, '[', ']' should be excluded + _host = (escaped) ? original.substring(from, next).toCharArray() + : encode(original.substring(from, next), allowed_IPv6reference, + charset); + // Set flag + _is_IPv6reference = true; + } else { // only for !_is_IPv6reference + next = original.indexOf(':', from); + if (next == -1) { + next = original.length(); + hasPort = false; + } + // REMINDME: it doesn't need the pre-validation + _host = original.substring(from, next).toCharArray(); + if (validate(_host, IPv4address)) { + // Set flag + _is_IPv4address = true; + } else if (validate(_host, hostname)) { + // Set flag + _is_hostname = true; + } else { + // Set flag + _is_reg_name = true; + } + } + if (_is_reg_name) { + // Reset flags for a server-based naming authority + _is_server = _is_hostname = _is_IPv4address = + _is_IPv6reference = false; + // set a registry-based naming authority + _authority = (escaped) ? original.toString().toCharArray() + : encode(original.toString(), allowed_reg_name, charset); + } else { + if (original.length() - 1 > next && hasPort + && original.charAt(next) == ':') { // not empty + from = next + 1; + try { + _port = Integer.parseInt(original.substring(from)); + } catch (NumberFormatException error) { + throw new URIException(URIException.PARSING, + "invalid port number"); + } + } + // set a server-based naming authority + StringBuffer buf = new StringBuffer(); + if (_userinfo != null) { // has_userinfo + buf.append(_userinfo); + buf.append('@'); + } + if (_host != null) { + buf.append(_host); + if (_port != -1) { + buf.append(':'); + buf.append(_port); + } + } + _authority = buf.toString().toCharArray(); + // Set flag + _is_server = true; + } + } + + + /** + * Once it's parsed successfully, set this URI. + * + * @see #getRawURI + */ + protected void setURI() { + // set _uri + StringBuffer buf = new StringBuffer(); + // ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? + if (_scheme != null) { + buf.append(_scheme); + buf.append(':'); + } + if (_is_net_path) { + buf.append("//"); + if (_authority != null) { // has_authority + if (_userinfo != null) { // by default, remove userinfo part + if (_host != null) { + buf.append(_host); + if (_port != -1) { + buf.append(':'); + buf.append(_port); + } + } + } else { + buf.append(_authority); + } + } + } + if (_opaque != null && _is_opaque_part) { + buf.append(_opaque); + } else if (_path != null) { + // _is_hier_part or _is_relativeURI + if (_path.length != 0) { + buf.append(_path); + } + } + if (_query != null) { // has_query + buf.append('?'); + buf.append(_query); + } + // ignore the fragment identifier + _uri = buf.toString().toCharArray(); + hash = 0; + } + + // ----------------------------------------------------------- Test methods + + + /** + * Tell whether or not this URI is absolute. + * + * @return true iif this URI is absoluteURI + */ + public boolean isAbsoluteURI() { + return (_scheme != null); + } + + + /** + * Tell whether or not this URI is relative. + * + * @return true iif this URI is relativeURI + */ + public boolean isRelativeURI() { + return (_scheme == null); + } + + + /** + * Tell whether or not the absoluteURI of this URI is hier_part. + * + * @return true iif the absoluteURI is hier_part + */ + public boolean isHierPart() { + return _is_hier_part; + } + + + /** + * Tell whether or not the absoluteURI of this URI is opaque_part. + * + * @return true iif the absoluteURI is opaque_part + */ + public boolean isOpaquePart() { + return _is_opaque_part; + } + + + /** + * Tell whether or not the relativeURI or heir_part of this URI is net_path. + * It's the same function as the has_authority() method. + * + * @return true iif the relativeURI or heir_part is net_path + * @see #hasAuthority + */ + public boolean isNetPath() { + return _is_net_path || (_authority != null); + } + + + /** + * Tell whether or not the relativeURI or hier_part of this URI is abs_path. + * + * @return true iif the relativeURI or hier_part is abs_path + */ + public boolean isAbsPath() { + return _is_abs_path; + } + + + /** + * Tell whether or not the relativeURI of this URI is rel_path. + * + * @return true iif the relativeURI is rel_path + */ + public boolean isRelPath() { + return _is_rel_path; + } + + + /** + * Tell whether or not this URI has authority. + * It's the same function as the is_net_path() method. + * + * @return true iif this URI has authority + * @see #isNetPath + */ + public boolean hasAuthority() { + return (_authority != null) || _is_net_path; + } + + /** + * Tell whether or not the authority component of this URI is reg_name. + * + * @return true iif the authority component is reg_name + */ + public boolean isRegName() { + return _is_reg_name; + } + + + /** + * Tell whether or not the authority component of this URI is server. + * + * @return true iif the authority component is server + */ + public boolean isServer() { + return _is_server; + } + + + /** + * Tell whether or not this URI has userinfo. + * + * @return true iif this URI has userinfo + */ + public boolean hasUserinfo() { + return (_userinfo != null); + } + + + /** + * Tell whether or not the host part of this URI is hostname. + * + * @return true iif the host part is hostname + */ + public boolean isHostname() { + return _is_hostname; + } + + + /** + * Tell whether or not the host part of this URI is IPv4address. + * + * @return true iif the host part is IPv4address + */ + public boolean isIPv4address() { + return _is_IPv4address; + } + + + /** + * Tell whether or not the host part of this URI is IPv6reference. + * + * @return true iif the host part is IPv6reference + */ + public boolean isIPv6reference() { + return _is_IPv6reference; + } + + + /** + * Tell whether or not this URI has query. + * + * @return true iif this URI has query + */ + public boolean hasQuery() { + return (_query != null); + } + + + /** + * Tell whether or not this URI has fragment. + * + * @return true iif this URI has fragment + */ + public boolean hasFragment() { + return (_fragment != null); + } + + + // ---------------------------------------------------------------- Charset + + + /** + * Set the default charset of the protocol. + *

+ * The character set used to store files SHALL remain a local decision and + * MAY depend on the capability of local operating systems. Prior to the + * exchange of URIs they SHOULD be converted into a ISO/IEC 10646 format + * and UTF-8 encoded. This approach, while allowing international exchange + * of URIs, will still allow backward compatibility with older systems + * because the code set positions for ASCII characters are identical to the + * one byte sequence in UTF-8. + *

+ * An individual URI scheme may require a single charset, define a default + * charset, or provide a way to indicate the charset used. + * + *

+ * Always all the time, the setter method is always succeeded and throws + * DefaultCharsetChanged exception. + * + * So API programmer must follow the following way: + *

+     *  import org.apache.util.URI$DefaultCharsetChanged;
+     *      .
+     *      .
+     *      .
+     *  try {
+     *      URI.setDefaultProtocolCharset("UTF-8");
+     *  } catch (DefaultCharsetChanged cc) {
+     *      // CASE 1: the exception could be ignored, when it is set by user
+     *      if (cc.getReasonCode() == DefaultCharsetChanged.PROTOCOL_CHARSET) {
+     *      // CASE 2: let user know the default protocol charset changed
+     *      } else {
+     *      // CASE 2: let user know the default document charset changed
+     *      }
+     *  }
+     *  
+ * + * The API programmer is responsible to set the correct charset. + * And each application should remember its own charset to support. + * + * @param charset the default charset for each protocol + * @throws DefaultCharsetChanged default charset changed + */ + public static void setDefaultProtocolCharset(String charset) + throws DefaultCharsetChanged { + + defaultProtocolCharset = charset; + throw new DefaultCharsetChanged(DefaultCharsetChanged.PROTOCOL_CHARSET, + "the default protocol charset changed"); + } + + + /** + * Get the default charset of the protocol. + *

+ * An individual URI scheme may require a single charset, define a default + * charset, or provide a way to indicate the charset used. + *

+ * To work globally either requires support of a number of character sets + * and to be able to convert between them, or the use of a single preferred + * character set. + * For support of global compatibility it is STRONGLY RECOMMENDED that + * clients and servers use UTF-8 encoding when exchanging URIs. + * + * @return the default charset string + */ + public static String getDefaultProtocolCharset() { + return defaultProtocolCharset; + } + + + /** + * Get the protocol charset used by this current URI instance. + * It was set by the constructor for this instance. If it was not set by + * contructor, it will return the default protocol charset. + * + * @return the protocol charset string + * @see #getDefaultProtocolCharset + */ + public String getProtocolCharset() { + return (protocolCharset != null) + ? protocolCharset + : defaultProtocolCharset; + } + + + /** + * Set the default charset of the document. + *

+ * Notice that it will be possible to contain mixed characters (e.g. + * ftp://host/KoreanNamespace/ChineseResource). To handle the Bi-directional + * display of these character sets, the protocol charset could be simply + * used again. Because it's not yet implemented that the insertion of BIDI + * control characters at different points during composition is extracted. + *

+ * + * Always all the time, the setter method is always succeeded and throws + * DefaultCharsetChanged exception. + * + * So API programmer must follow the following way: + *

+     *  import org.apache.util.URI$DefaultCharsetChanged;
+     *      .
+     *      .
+     *      .
+     *  try {
+     *      URI.setDefaultDocumentCharset("EUC-KR");
+     *  } catch (DefaultCharsetChanged cc) {
+     *      // CASE 1: the exception could be ignored, when it is set by user
+     *      if (cc.getReasonCode() == DefaultCharsetChanged.DOCUMENT_CHARSET) {
+     *      // CASE 2: let user know the default document charset changed
+     *      } else {
+     *      // CASE 2: let user know the default protocol charset changed
+     *      }
+     *  }
+     *  
+ * + * The API programmer is responsible to set the correct charset. + * And each application should remember its own charset to support. + * + * @param charset the default charset for the document + * @throws DefaultCharsetChanged default charset changed + */ + public static void setDefaultDocumentCharset(String charset) + throws DefaultCharsetChanged { + + defaultDocumentCharset = charset; + throw new DefaultCharsetChanged(DefaultCharsetChanged.DOCUMENT_CHARSET, + "the default document charset changed"); + } + + + /** + * Get the recommended default charset of the document. + * + * @return the default charset string + */ + public static String getDefaultDocumentCharset() { + return defaultDocumentCharset; + } + + + /** + * Get the default charset of the document by locale. + * + * @return the default charset string by locale + */ + public static String getDefaultDocumentCharsetByLocale() { + return defaultDocumentCharsetByLocale; + } + + + /** + * Get the default charset of the document by platform. + * + * @return the default charset string by platform + */ + public static String getDefaultDocumentCharsetByPlatform() { + return defaultDocumentCharsetByPlatform; + } + + // ------------------------------------------------------------- The scheme + + /** + * Get the scheme. + * + * @return the scheme + */ + public char[] getRawScheme() { + return _scheme; + } + + + /** + * Get the scheme. + * + * @return the scheme + * null if undefined scheme + */ + public String getScheme() { + return (_scheme == null) ? null : new String(_scheme); + } + + // ---------------------------------------------------------- The authority + + /** + * Set the authority. It can be one type of server, hostport, hostname, + * IPv4address, IPv6reference and reg_name. + *

+     *   authority     = server | reg_name
+     * 

+ * + * @param escapedAuthority the raw escaped authority + * @throws URIException If {@link + * #parseAuthority(java.lang.String,boolean)} fails + * @throws NullPointerException null authority + */ + public void setRawAuthority(char[] escapedAuthority) + throws URIException, NullPointerException { + + parseAuthority(new String(escapedAuthority), true); + setURI(); + } + + + /** + * Set the authority. It can be one type of server, hostport, hostname, + * IPv4address, IPv6reference and reg_name. + * Note that there is no setAuthority method by the escape encoding reason. + * + * @param escapedAuthority the escaped authority string + * @throws URIException If {@link + * #parseAuthority(java.lang.String,boolean)} fails + */ + public void setEscapedAuthority(String escapedAuthority) + throws URIException { + + parseAuthority(escapedAuthority, true); + setURI(); + } + + + /** + * Get the raw-escaped authority. + * + * @return the raw-escaped authority + */ + public char[] getRawAuthority() { + return _authority; + } + + + /** + * Get the escaped authority. + * + * @return the escaped authority + */ + public String getEscapedAuthority() { + return (_authority == null) ? null : new String(_authority); + } + + + /** + * Get the authority. + * + * @return the authority + * @throws URIException If {@link #decode} fails + */ + public String getAuthority() throws URIException { + return (_authority == null) ? null : decode(_authority, + getProtocolCharset()); + } + + // ----------------------------------------------------------- The userinfo + + /** + * Get the raw-escaped userinfo. + * + * @return the raw-escaped userinfo + * @see #getAuthority + */ + public char[] getRawUserinfo() { + return _userinfo; + } + + + /** + * Get the escaped userinfo. + * + * @return the escaped userinfo + * @see #getAuthority + */ + public String getEscapedUserinfo() { + return (_userinfo == null) ? null : new String(_userinfo); + } + + + /** + * Get the userinfo. + * + * @return the userinfo + * @throws URIException If {@link #decode} fails + * @see #getAuthority + */ + public String getUserinfo() throws URIException { + return (_userinfo == null) ? null : decode(_userinfo, + getProtocolCharset()); + } + + // --------------------------------------------------------------- The host + + /** + * Get the host. + *

+     *   host          = hostname | IPv4address | IPv6reference
+     * 

+ * + * @return the host + * @see #getAuthority + */ + public char[] getRawHost() { + return _host; + } + + + /** + * Get the host. + *

+     *   host          = hostname | IPv4address | IPv6reference
+     * 

+ * + * @return the host + * @throws URIException If {@link #decode} fails + * @see #getAuthority + */ + public String getHost() throws URIException { + if (_host != null) { + return decode(_host, getProtocolCharset()); + } else { + return null; + } + } + + // --------------------------------------------------------------- The port + + /** + * Get the port. In order to get the specfic default port, the specific + * protocol-supported class extended from the URI class should be used. + * It has the server-based naming authority. + * + * @return the port + * if -1, it has the default port for the scheme or the server-based + * naming authority is not supported in the specific URI. + */ + public int getPort() { + return _port; + } + + // --------------------------------------------------------------- The path + + /** + * Set the raw-escaped path. + * + * @param escapedPath the path character sequence + * @throws URIException encoding error or not proper for initial instance + * @see #encode + */ + public void setRawPath(char[] escapedPath) throws URIException { + if (escapedPath == null || escapedPath.length == 0) { + _path = _opaque = escapedPath; + setURI(); + return; + } + // remove the fragment identifier + escapedPath = removeFragmentIdentifier(escapedPath); + if (_is_net_path || _is_abs_path) { + if (escapedPath[0] != '/') { + throw new URIException(URIException.PARSING, + "not absolute path"); + } + if (!validate(escapedPath, abs_path)) { + throw new URIException(URIException.ESCAPING, + "escaped absolute path not valid"); + } + _path = escapedPath; + } else if (_is_rel_path) { + int at = indexFirstOf(escapedPath, '/'); + if (at == 0) { + throw new URIException(URIException.PARSING, "incorrect path"); + } + if (at > 0 && !validate(escapedPath, 0, at - 1, rel_segment) + && !validate(escapedPath, at, -1, abs_path) + || at < 0 && !validate(escapedPath, 0, -1, rel_segment)) { + + throw new URIException(URIException.ESCAPING, + "escaped relative path not valid"); + } + _path = escapedPath; + } else if (_is_opaque_part) { + if (!uric_no_slash.get(escapedPath[0]) + && !validate(escapedPath, 1, -1, uric)) { + throw new URIException(URIException.ESCAPING, + "escaped opaque part not valid"); + } + _opaque = escapedPath; + } else { + throw new URIException(URIException.PARSING, "incorrect path"); + } + setURI(); + } + + + /** + * Set the escaped path. + * + * @param escapedPath the escaped path string + * @throws URIException encoding error or not proper for initial instance + * @see #encode + */ + public void setEscapedPath(String escapedPath) throws URIException { + if (escapedPath == null) { + _path = _opaque = null; + setURI(); + return; + } + setRawPath(escapedPath.toCharArray()); + } + + + /** + * Set the path. + * + * @param path the path string + * @throws URIException set incorrectly or fragment only + * @see #encode + */ + public void setPath(String path) throws URIException { + + if (path == null || path.length() == 0) { + _path = _opaque = (path == null) ? null : path.toCharArray(); + setURI(); + return; + } + // set the charset to do escape encoding + String charset = getProtocolCharset(); + + if (_is_net_path || _is_abs_path) { + _path = encode(path, allowed_abs_path, charset); + } else if (_is_rel_path) { + StringBuffer buff = new StringBuffer(path.length()); + int at = path.indexOf('/'); + if (at == 0) { // never 0 + throw new URIException(URIException.PARSING, + "incorrect relative path"); + } + if (at > 0) { + buff.append(encode(path.substring(0, at), allowed_rel_path, + charset)); + buff.append(encode(path.substring(at), allowed_abs_path, + charset)); + } else { + buff.append(encode(path, allowed_rel_path, charset)); + } + _path = buff.toString().toCharArray(); + } else if (_is_opaque_part) { + StringBuffer buf = new StringBuffer(); + buf.insert(0, encode(path.substring(0, 1), uric_no_slash, charset)); + buf.insert(1, encode(path.substring(1), uric, charset)); + _opaque = buf.toString().toCharArray(); + } else { + throw new URIException(URIException.PARSING, "incorrect path"); + } + setURI(); + } + + + /** + * Resolve the base and relative path. + * + * @param basePath a character array of the basePath + * @param relPath a character array of the relPath + * @return the resolved path + * @throws URIException no more higher path level to be resolved + */ + protected char[] resolvePath(char[] basePath, char[] relPath) + throws URIException { + + // REMINDME: paths are never null + String base = (basePath == null) ? "" : new String(basePath); + int at = base.lastIndexOf('/'); + if (at != -1) { + basePath = base.substring(0, at + 1).toCharArray(); + } + // _path could be empty + if (relPath == null || relPath.length == 0) { + return normalize(basePath); + } else if (relPath[0] == '/') { + return normalize(relPath); + } else { + StringBuffer buff = new StringBuffer(base.length() + + relPath.length); + buff.append((at != -1) ? base.substring(0, at + 1) : "/"); + buff.append(relPath); + return normalize(buff.toString().toCharArray()); + } + } + + + /** + * Get the raw-escaped current hierarchy level in the given path. + * If the last namespace is a collection, the slash mark ('/') should be + * ended with at the last character of the path string. + * + * @param path the path + * @return the current hierarchy level + * @throws URIException no hierarchy level + */ + protected char[] getRawCurrentHierPath(char[] path) throws URIException { + + if (_is_opaque_part) { + throw new URIException(URIException.PARSING, "no hierarchy level"); + } + if (path == null) { + throw new URIException(URIException.PARSING, "empty path"); + } + String buff = new String(path); + int first = buff.indexOf('/'); + int last = buff.lastIndexOf('/'); + if (last == 0) { + return rootPath; + } else if (first != last && last != -1) { + return buff.substring(0, last).toCharArray(); + } + // FIXME: it could be a document on the server side + return path; + } + + + /** + * Get the raw-escaped current hierarchy level. + * + * @return the raw-escaped current hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + */ + public char[] getRawCurrentHierPath() throws URIException { + return (_path == null) ? null : getRawCurrentHierPath(_path); + } + + + /** + * Get the escaped current hierarchy level. + * + * @return the escaped current hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + */ + public String getEscapedCurrentHierPath() throws URIException { + char[] path = getRawCurrentHierPath(); + return (path == null) ? null : new String(path); + } + + + /** + * Get the current hierarchy level. + * + * @return the current hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + * @see #decode + */ + public String getCurrentHierPath() throws URIException { + char[] path = getRawCurrentHierPath(); + return (path == null) ? null : decode(path, getProtocolCharset()); + } + + + /** + * Get the level above the this hierarchy level. + * + * @return the raw above hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + */ + public char[] getRawAboveHierPath() throws URIException { + char[] path = getRawCurrentHierPath(); + return (path == null) ? null : getRawCurrentHierPath(path); + } + + + /** + * Get the level above the this hierarchy level. + * + * @return the raw above hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + */ + public String getEscapedAboveHierPath() throws URIException { + char[] path = getRawAboveHierPath(); + return (path == null) ? null : new String(path); + } + + + /** + * Get the level above the this hierarchy level. + * + * @return the above hierarchy level + * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails. + * @see #decode + */ + public String getAboveHierPath() throws URIException { + char[] path = getRawAboveHierPath(); + return (path == null) ? null : decode(path, getProtocolCharset()); + } + + + /** + * Get the raw-escaped path. + *

+     *   path          = [ abs_path | opaque_part ]
+     * 

+ * + * @return the raw-escaped path + */ + public char[] getRawPath() { + return _is_opaque_part ? _opaque : _path; + } + + + /** + * Get the escaped path. + *

+     *   path          = [ abs_path | opaque_part ]
+     *   abs_path      = "/"  path_segments 
+     *   opaque_part   = uric_no_slash *uric
+     * 

+ * + * @return the escaped path string + */ + public String getEscapedPath() { + char[] path = getRawPath(); + return (path == null) ? null : new String(path); + } + + + /** + * Get the path. + *

+     *   path          = [ abs_path | opaque_part ]
+     * 

+ * @return the path string + * @throws URIException If {@link #decode} fails. + * @see #decode + */ + public String getPath() throws URIException { + char[] path = getRawPath(); + return (path == null) ? null : decode(path, getProtocolCharset()); + } + + + /** + * Get the raw-escaped basename of the path. + * + * @return the raw-escaped basename + */ + public char[] getRawName() { + if (_path == null) { + return null; + } + + int at = 0; + for (int i = _path.length - 1; i >= 0; i--) { + if (_path[i] == '/') { + at = i + 1; + break; + } + } + int len = _path.length - at; + char[] basename = new char[len]; + System.arraycopy(_path, at, basename, 0, len); + return basename; + } + + + /** + * Get the escaped basename of the path. + * + * @return the escaped basename string + */ + public String getEscapedName() { + char[] basename = getRawName(); + return (basename == null) ? null : new String(basename); + } + + + /** + * Get the basename of the path. + * + * @return the basename string + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + * @see #decode + */ + public String getName() throws URIException { + char[] basename = getRawName(); + return (basename == null) ? null : decode(getRawName(), + getProtocolCharset()); + } + + // ----------------------------------------------------- The path and query + + /** + * Get the raw-escaped path and query. + * + * @return the raw-escaped path and query + */ + public char[] getRawPathQuery() { + + if (_path == null && _query == null) { + return null; + } + StringBuffer buff = new StringBuffer(); + if (_path != null) { + buff.append(_path); + } + if (_query != null) { + buff.append('?'); + buff.append(_query); + } + return buff.toString().toCharArray(); + } + + + /** + * Get the escaped query. + * + * @return the escaped path and query string + */ + public String getEscapedPathQuery() { + char[] rawPathQuery = getRawPathQuery(); + return (rawPathQuery == null) ? null : new String(rawPathQuery); + } + + + /** + * Get the path and query. + * + * @return the path and query string. + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + * @see #decode + */ + public String getPathQuery() throws URIException { + char[] rawPathQuery = getRawPathQuery(); + return (rawPathQuery == null) ? null : decode(rawPathQuery, + getProtocolCharset()); + } + + // -------------------------------------------------------------- The query + + /** + * Set the raw-escaped query. + * + * @param escapedQuery the raw-escaped query + * @throws URIException escaped query not valid + */ + public void setRawQuery(char[] escapedQuery) throws URIException { + if (escapedQuery == null || escapedQuery.length == 0) { + _query = escapedQuery; + setURI(); + return; + } + // remove the fragment identifier + escapedQuery = removeFragmentIdentifier(escapedQuery); + if (!validate(escapedQuery, query)) { + throw new URIException(URIException.ESCAPING, + "escaped query not valid"); + } + _query = escapedQuery; + setURI(); + } + + + /** + * Set the escaped query string. + * + * @param escapedQuery the escaped query string + * @throws URIException escaped query not valid + */ + public void setEscapedQuery(String escapedQuery) throws URIException { + if (escapedQuery == null) { + _query = null; + setURI(); + return; + } + setRawQuery(escapedQuery.toCharArray()); + } + + + /** + * Set the query. + *

+ * When a query string is not misunderstood the reserved special characters + * ("&", "=", "+", ",", and "$") within a query component, it is + * recommended to use in encoding the whole query with this method. + *

+ * The additional APIs for the special purpose using by the reserved + * special characters used in each protocol are implemented in each protocol + * classes inherited from URI. So refer to the same-named APIs + * implemented in each specific protocol instance. + * + * @param query the query string. + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + * @see #encode + */ + public void setQuery(String query) throws URIException { + if (query == null || query.length() == 0) { + _query = (query == null) ? null : query.toCharArray(); + setURI(); + return; + } + setRawQuery(encode(query, allowed_query, getProtocolCharset())); + } + + + /** + * Get the raw-escaped query. + * + * @return the raw-escaped query + */ + public char[] getRawQuery() { + return _query; + } + + + /** + * Get the escaped query. + * + * @return the escaped query string + */ + public String getEscapedQuery() { + return (_query == null) ? null : new String(_query); + } + + + /** + * Get the query. + * + * @return the query string. + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + * @see #decode + */ + public String getQuery() throws URIException { + return (_query == null) ? null : decode(_query, getProtocolCharset()); + } + + // ----------------------------------------------------------- The fragment + + /** + * Set the raw-escaped fragment. + * + * @param escapedFragment the raw-escaped fragment + * @throws URIException escaped fragment not valid + */ + public void setRawFragment(char[] escapedFragment) throws URIException { + if (escapedFragment == null || escapedFragment.length == 0) { + _fragment = escapedFragment; + hash = 0; + return; + } + if (!validate(escapedFragment, fragment)) { + throw new URIException(URIException.ESCAPING, + "escaped fragment not valid"); + } + _fragment = escapedFragment; + hash = 0; + } + + + /** + * Set the escaped fragment string. + * + * @param escapedFragment the escaped fragment string + * @throws URIException escaped fragment not valid + */ + public void setEscapedFragment(String escapedFragment) throws URIException { + if (escapedFragment == null) { + _fragment = null; + hash = 0; + return; + } + setRawFragment(escapedFragment.toCharArray()); + } + + + /** + * Set the fragment. + * + * @param fragment the fragment string. + * @throws URIException If an error occurs. + */ + public void setFragment(String fragment) throws URIException { + if (fragment == null || fragment.length() == 0) { + _fragment = (fragment == null) ? null : fragment.toCharArray(); + hash = 0; + return; + } + _fragment = encode(fragment, allowed_fragment, getProtocolCharset()); + hash = 0; + } + + + /** + * Get the raw-escaped fragment. + *

+ * The optional fragment identifier is not part of a URI, but is often used + * in conjunction with a URI. + *

+ * The format and interpretation of fragment identifiers is dependent on + * the media type [RFC2046] of the retrieval result. + *

+ * A fragment identifier is only meaningful when a URI reference is + * intended for retrieval and the result of that retrieval is a document + * for which the identified fragment is consistently defined. + * + * @return the raw-escaped fragment + */ + public char[] getRawFragment() { + return _fragment; + } + + + /** + * Get the escaped fragment. + * + * @return the escaped fragment string + */ + public String getEscapedFragment() { + return (_fragment == null) ? null : new String(_fragment); + } + + + /** + * Get the fragment. + * + * @return the fragment string + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + * @see #decode + */ + public String getFragment() throws URIException { + return (_fragment == null) ? null : decode(_fragment, + getProtocolCharset()); + } + + // ------------------------------------------------------------- Utilities + + /** + * Remove the fragment identifier of the given component. + * + * @param component the component that a fragment may be included + * @return the component that the fragment identifier is removed + */ + protected char[] removeFragmentIdentifier(char[] component) { + if (component == null) { + return null; + } + int lastIndex = new String(component).indexOf('#'); + if (lastIndex != -1) { + component = new String(component).substring(0, + lastIndex).toCharArray(); + } + return component; + } + + + /** + * Normalize the given hier path part. + * + *

Algorithm taken from URI reference parser at + * http://www.apache.org/~fielding/uri/rev-2002/issues.html. + * + * @param path the path to normalize + * @return the normalized path + * @throws URIException no more higher path level to be normalized + */ + protected char[] normalize(char[] path) throws URIException { + + if (path == null) { + return null; + } + + String normalized = new String(path); + + // If the buffer begins with "./" or "../", the "." or ".." is removed. + if (normalized.startsWith("./")) { + normalized = normalized.substring(1); + } else if (normalized.startsWith("../")) { + normalized = normalized.substring(2); + } else if (normalized.startsWith("..")) { + normalized = normalized.substring(2); + } + + // All occurrences of "/./" in the buffer are replaced with "/" + int index = -1; + while ((index = normalized.indexOf("/./")) != -1) { + normalized = normalized.substring(0, index) + normalized.substring(index + 2); + } + + // If the buffer ends with "/.", the "." is removed. + if (normalized.endsWith("/.")) { + normalized = normalized.substring(0, normalized.length() - 1); + } + + int startIndex = 0; + + // All occurrences of "//../" in the buffer, where ".." + // and are complete path segments, are iteratively replaced + // with "/" in order from left to right until no matching pattern remains. + // If the buffer ends with "//..", that is also replaced + // with "/". Note that may be empty. + while ((index = normalized.indexOf("/../", startIndex)) != -1) { + int slashIndex = normalized.lastIndexOf('/', index - 1); + if (slashIndex >= 0) { + normalized = normalized.substring(0, slashIndex) + normalized.substring(index + 3); + } else { + startIndex = index + 3; + } + } + if (normalized.endsWith("/..")) { + int slashIndex = normalized.lastIndexOf('/', normalized.length() - 4); + if (slashIndex >= 0) { + normalized = normalized.substring(0, slashIndex + 1); + } + } + + // All prefixes of "/../" in the buffer, where ".." + // and are complete path segments, are iteratively replaced + // with "/" in order from left to right until no matching pattern remains. + // If the buffer ends with "/..", that is also replaced + // with "/". Note that may be empty. + while ((index = normalized.indexOf("/../")) != -1) { + int slashIndex = normalized.lastIndexOf('/', index - 1); + if (slashIndex >= 0) { + break; + } else { + normalized = normalized.substring(index + 3); + } + } + if (normalized.endsWith("/..")) { + int slashIndex = normalized.lastIndexOf('/', normalized.length() - 4); + if (slashIndex < 0) { + normalized = "/"; + } + } + + return normalized.toCharArray(); + } + + + /** + * Normalizes the path part of this URI. Normalization is only meant to be performed on + * URIs with an absolute path. Calling this method on a relative path URI will have no + * effect. + * + * @throws URIException no more higher path level to be normalized + * + * @see #isAbsPath() + */ + public void normalize() throws URIException { + if (isAbsPath()) { + _path = normalize(_path); + setURI(); + } + } + + + /** + * Test if the first array is equal to the second array. + * + * @param first the first character array + * @param second the second character array + * @return true if they're equal + */ + protected boolean equals(char[] first, char[] second) { + + if (first == null && second == null) { + return true; + } + if (first == null || second == null) { + return false; + } + if (first.length != second.length) { + return false; + } + for (int i = 0; i < first.length; i++) { + if (first[i] != second[i]) { + return false; + } + } + return true; + } + + + /** + * Test an object if this URI is equal to another. + * + * @param obj an object to compare + * @return true if two URI objects are equal + */ + public boolean equals(Object obj) { + + // normalize and test each components + if (obj == this) { + return true; + } + if (!(obj instanceof URI)) { + return false; + } + URI another = (URI) obj; + // scheme + if (!equals(_scheme, another._scheme)) { + return false; + } + // is_opaque_part or is_hier_part? and opaque + if (!equals(_opaque, another._opaque)) { + return false; + } + // is_hier_part + // has_authority + if (!equals(_authority, another._authority)) { + return false; + } + // path + if (!equals(_path, another._path)) { + return false; + } + // has_query + if (!equals(_query, another._query)) { + return false; + } + // has_fragment? should be careful of the only fragment case. + if (!equals(_fragment, another._fragment)) { + return false; + } + return true; + } + + // ---------------------------------------------------------- Serialization + + /** + * Write the content of this URI. + * + * @param oos the object-output stream + * @throws IOException If an IO problem occurs. + */ + protected void writeObject(ObjectOutputStream oos) + throws IOException { + + oos.defaultWriteObject(); + } + + + /** + * Read a URI. + * + * @param ois the object-input stream + * @throws ClassNotFoundException If one of the classes specified in the + * input stream cannot be found. + * @throws IOException If an IO problem occurs. + */ + protected void readObject(ObjectInputStream ois) + throws ClassNotFoundException, IOException { + + ois.defaultReadObject(); + } + + // -------------------------------------------------------------- Hash code + + /** + * Return a hash code for this URI. + * + * @return a has code value for this URI + */ + public int hashCode() { + if (hash == 0) { + char[] c = _uri; + if (c != null) { + for (int i = 0, len = c.length; i < len; i++) { + hash = 31 * hash + c[i]; + } + } + c = _fragment; + if (c != null) { + for (int i = 0, len = c.length; i < len; i++) { + hash = 31 * hash + c[i]; + } + } + } + return hash; + } + + // ------------------------------------------------------------- Comparison + + /** + * Compare this URI to another object. + * + * @param obj the object to be compared. + * @return 0, if it's same, + * -1, if failed, first being compared with in the authority component + * @throws ClassCastException not URI argument + */ + public int compareTo(Object obj) throws ClassCastException { + + URI another = (URI) obj; + if (!equals(_authority, another.getRawAuthority())) { + return -1; + } + return toString().compareTo(another.toString()); + } + + // ------------------------------------------------------------------ Clone + + /** + * Create and return a copy of this object, the URI-reference containing + * the userinfo component. Notice that the whole URI-reference including + * the userinfo component counld not be gotten as a String. + *

+ * To copy the identical URI object including the userinfo + * component, it should be used. + * + * @return a clone of this instance + */ + public synchronized Object clone() { + + URI instance = new URI(); + + instance._uri = _uri; + instance._scheme = _scheme; + instance._opaque = _opaque; + instance._authority = _authority; + instance._userinfo = _userinfo; + instance._host = _host; + instance._port = _port; + instance._path = _path; + instance._query = _query; + instance._fragment = _fragment; + // the charset to do escape encoding for this instance + instance.protocolCharset = protocolCharset; + // flags + instance._is_hier_part = _is_hier_part; + instance._is_opaque_part = _is_opaque_part; + instance._is_net_path = _is_net_path; + instance._is_abs_path = _is_abs_path; + instance._is_rel_path = _is_rel_path; + instance._is_reg_name = _is_reg_name; + instance._is_server = _is_server; + instance._is_hostname = _is_hostname; + instance._is_IPv4address = _is_IPv4address; + instance._is_IPv6reference = _is_IPv6reference; + + return instance; + } + + // ------------------------------------------------------------ Get the URI + + /** + * It can be gotten the URI character sequence. It's raw-escaped. + * For the purpose of the protocol to be transported, it will be useful. + *

+ * It is clearly unwise to use a URL that contains a password which is + * intended to be secret. In particular, the use of a password within + * the 'userinfo' component of a URL is strongly disrecommended except + * in those rare cases where the 'password' parameter is intended to be + * public. + *

+ * When you want to get each part of the userinfo, you need to use the + * specific methods in the specific URL. It depends on the specific URL. + * + * @return the URI character sequence + */ + public char[] getRawURI() { + return _uri; + } + + + /** + * It can be gotten the URI character sequence. It's escaped. + * For the purpose of the protocol to be transported, it will be useful. + * + * @return the escaped URI string + */ + public String getEscapedURI() { + return (_uri == null) ? null : new String(_uri); + } + + + /** + * It can be gotten the URI character sequence. + * + * @return the original URI string + * @throws URIException incomplete trailing escape pattern or unsupported + * character encoding + * @see #decode + */ + public String getURI() throws URIException { + return (_uri == null) ? null : decode(_uri, getProtocolCharset()); + } + + + /** + * Get the URI reference character sequence. + * + * @return the URI reference character sequence + */ + public char[] getRawURIReference() { + if (_fragment == null) { + return _uri; + } + if (_uri == null) { + return _fragment; + } + // if _uri != null && _fragment != null + String uriReference = new String(_uri) + "#" + new String(_fragment); + return uriReference.toCharArray(); + } + + + /** + * Get the escaped URI reference string. + * + * @return the escaped URI reference string + */ + public String getEscapedURIReference() { + char[] uriReference = getRawURIReference(); + return (uriReference == null) ? null : new String(uriReference); + } + + + /** + * Get the original URI reference string. + * + * @return the original URI reference string + * @throws URIException If {@link #decode} fails. + */ + public String getURIReference() throws URIException { + char[] uriReference = getRawURIReference(); + return (uriReference == null) ? null : decode(uriReference, + getProtocolCharset()); + } + + + /** + * Get the escaped URI string. + *

+ * On the document, the URI-reference form is only used without the userinfo + * component like http://jakarta.apache.org/ by the security reason. + * But the URI-reference form with the userinfo component could be parsed. + *

+ * In other words, this URI and any its subclasses must not expose the + * URI-reference expression with the userinfo component like + * http://user:password@hostport/restricted_zone.
+ * It means that the API client programmer should extract each user and + * password to access manually. Probably it will be supported in the each + * subclass, however, not a whole URI-reference expression. + * + * @return the escaped URI string + * @see #clone() + */ + public String toString() { + return getEscapedURI(); + } + + + // ------------------------------------------------------------ Inner class + + /** + * The charset-changed normal operation to represent to be required to + * alert to user the fact the default charset is changed. + */ + public static class DefaultCharsetChanged extends RuntimeException { + + // ------------------------------------------------------- constructors + + /** + * The constructor with a reason string and its code arguments. + * + * @param reasonCode the reason code + * @param reason the reason + */ + public DefaultCharsetChanged(int reasonCode, String reason) { + super(reason); + this.reason = reason; + this.reasonCode = reasonCode; + } + + // ---------------------------------------------------------- constants + + /** No specified reason code. */ + public static final int UNKNOWN = 0; + + /** Protocol charset changed. */ + public static final int PROTOCOL_CHARSET = 1; + + /** Document charset changed. */ + public static final int DOCUMENT_CHARSET = 2; + + // ------------------------------------------------- instance variables + + /** The reason code. */ + private int reasonCode; + + /** The reason message. */ + private String reason; + + // ------------------------------------------------------------ methods + + /** + * Get the reason code. + * + * @return the reason code + */ + public int getReasonCode() { + return reasonCode; + } + + /** + * Get the reason message. + * + * @return the reason message + */ + public String getReason() { + return reason; + } + + } + + + /** + * A mapping to determine the (somewhat arbitrarily) preferred charset for a + * given locale. Supports all locales recognized in JDK 1.1. + *

+ * The distribution of this class is Servlets.com. It was originally + * written by Jason Hunter [jhunter at acm.org] and used by with permission. + */ + public static class LocaleToCharsetMap { + + /** A mapping of language code to charset */ + private static final Hashtable LOCALE_TO_CHARSET_MAP; + static { + LOCALE_TO_CHARSET_MAP = new Hashtable(); + LOCALE_TO_CHARSET_MAP.put("ar", "ISO-8859-6"); + LOCALE_TO_CHARSET_MAP.put("be", "ISO-8859-5"); + LOCALE_TO_CHARSET_MAP.put("bg", "ISO-8859-5"); + LOCALE_TO_CHARSET_MAP.put("ca", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("cs", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("da", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("de", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("el", "ISO-8859-7"); + LOCALE_TO_CHARSET_MAP.put("en", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("es", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("et", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("fi", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("fr", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("hr", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("hu", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("is", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("it", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("iw", "ISO-8859-8"); + LOCALE_TO_CHARSET_MAP.put("ja", "Shift_JIS"); + LOCALE_TO_CHARSET_MAP.put("ko", "EUC-KR"); + LOCALE_TO_CHARSET_MAP.put("lt", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("lv", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("mk", "ISO-8859-5"); + LOCALE_TO_CHARSET_MAP.put("nl", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("no", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("pl", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("pt", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("ro", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("ru", "ISO-8859-5"); + LOCALE_TO_CHARSET_MAP.put("sh", "ISO-8859-5"); + LOCALE_TO_CHARSET_MAP.put("sk", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("sl", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("sq", "ISO-8859-2"); + LOCALE_TO_CHARSET_MAP.put("sr", "ISO-8859-5"); + LOCALE_TO_CHARSET_MAP.put("sv", "ISO-8859-1"); + LOCALE_TO_CHARSET_MAP.put("tr", "ISO-8859-9"); + LOCALE_TO_CHARSET_MAP.put("uk", "ISO-8859-5"); + LOCALE_TO_CHARSET_MAP.put("zh", "GB2312"); + LOCALE_TO_CHARSET_MAP.put("zh_TW", "Big5"); + } + + /** + * Get the preferred charset for the given locale. + * + * @param locale the locale + * @return the preferred charset or null if the locale is not + * recognized. + */ + public static String getCharset(Locale locale) { + // try for an full name match (may include country) + String charset = + (String) LOCALE_TO_CHARSET_MAP.get(locale.toString()); + if (charset != null) { + return charset; + } + + // if a full name didn't match, try just the language + charset = (String) LOCALE_TO_CHARSET_MAP.get(locale.getLanguage()); + return charset; // may be null + } + + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URIException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URIException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URIException.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,177 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/URIException.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +/** + * The URI parsing and escape encoding exception. + * + * @author Sung-Gu + * @author Oleg Kalnichevski + * @version $Revision: 1.1 $ $Date: 2002/03/14 15:14:01 + */ +public class URIException extends HttpException { + + // ----------------------------------------------------------- constructors + + /** + * Default constructor. + */ + public URIException() { + } + + + /** + * The constructor with a reason code argument. + * + * @param reasonCode the reason code + */ + public URIException(int reasonCode) { + this.reasonCode = reasonCode; + } + + + /** + * The constructor with a reason string and its code arguments. + * + * @param reasonCode the reason code + * @param reason the reason + */ + public URIException(int reasonCode, String reason) { + super(reason); // for backward compatibility of Throwable + this.reason = reason; + this.reasonCode = reasonCode; + } + + + /** + * The constructor with a reason string argument. + * + * @param reason the reason + */ + public URIException(String reason) { + super(reason); // for backward compatibility of Throwable + this.reason = reason; + this.reasonCode = UNKNOWN; + } + + // -------------------------------------------------------------- constants + + /** + * No specified reason code. + */ + public static final int UNKNOWN = 0; + + + /** + * The URI parsing error. + */ + public static final int PARSING = 1; + + + /** + * The unsupported character encoding. + */ + public static final int UNSUPPORTED_ENCODING = 2; + + + /** + * The URI escape encoding and decoding error. + */ + public static final int ESCAPING = 3; + + + /** + * The DNS punycode encoding or decoding error. + */ + public static final int PUNYCODE = 4; + + // ------------------------------------------------------------- properties + + /** + * The reason code. + */ + protected int reasonCode; + + + /** + * The reason message. + */ + protected String reason; + + // ---------------------------------------------------------------- methods + + /** + * Get the reason code. + * + * @return the reason code + */ + public int getReasonCode() { + return reasonCode; + } + + /** + * Set the reason code. + * + * @param reasonCode the reason code + * + * @deprecated Callers should set the reason code as a parameter to the + * constructor. + */ + public void setReasonCode(int reasonCode) { + this.reasonCode = reasonCode; + } + + + /** + * Get the reason message. + * + * @return the reason message + * + * @deprecated You should instead call {@link #getMessage()}. + */ + public String getReason() { + return reason; + } + + + /** + * Set the reason message. + * + * @param reason the reason message + * + * @deprecated Callers should instead set this via a parameter to the constructor. + */ + public void setReason(String reason) { + this.reason = reason; + } + + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/UsernamePasswordCredentials.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/UsernamePasswordCredentials.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/UsernamePasswordCredentials.java 22 Aug 2012 17:30:33 -0000 1.1 @@ -0,0 +1,213 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/UsernamePasswordCredentials.java,v 1.1 2012/08/22 17:30:33 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:33 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import org.apache.commons.httpclient.util.LangUtils; + +/** + *

Username and password {@link Credentials}.

+ * + * @author Remy Maucherat + * @author Sean C. Sullivan + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:33 $ + * + */ +public class UsernamePasswordCredentials implements Credentials { + + // ----------------------------------------------------------- Constructors + + /** + * Default constructor. + * + * @deprecated Do not use. Null user name no longer allowed + */ + public UsernamePasswordCredentials() { + super(); + } + + + /** + * The constructor with the username and password combined string argument. + * + * @param usernamePassword the username:password formed string + * @see #toString + */ + public UsernamePasswordCredentials(String usernamePassword) { + super(); + if (usernamePassword == null) { + throw new IllegalArgumentException("Username:password string may not be null"); + } + int atColon = usernamePassword.indexOf(':'); + if (atColon >= 0) { + this.userName = usernamePassword.substring(0, atColon); + this.password = usernamePassword.substring(atColon + 1); + } else { + this.userName = usernamePassword; + } + } + + + /** + * The constructor with the username and password arguments. + * + * @param userName the user name + * @param password the password + */ + public UsernamePasswordCredentials(String userName, String password) { + super(); + if (userName == null) { + throw new IllegalArgumentException("Username may not be null"); + } + this.userName = userName; + this.password = password; + } + + // ----------------------------------------------------- Instance Variables + + /** + * User name. + */ + private String userName; + + + /** + * Password. + */ + private String password; + + + // ------------------------------------------------------------- Properties + + + /** + * User name property setter. User name may not be null. + * + * @param userName + * @see #getUserName() + * + * @deprecated Do not use. The UsernamePasswordCredentials objects should be immutable + */ + public void setUserName(String userName) { + if (userName == null) { + throw new IllegalArgumentException("Username may not be null"); + } + this.userName = userName; + } + + + /** + * User name property getter. + * + * @return the userName + * @see #setUserName(String) + */ + public String getUserName() { + return userName; + } + + + /** + * Password property setter. + * + * @param password + * @see #getPassword() + * + * @deprecated Do not use. The UsernamePasswordCredentials objects should be immutable + */ + public void setPassword(String password) { + this.password = password; + } + + + /** + * Password property getter. + * + * @return the password + * @see #setPassword(String) + */ + public String getPassword() { + return password; + } + + + /** + * Get this object string. + * + * @return the username:password formed string + */ + public String toString() { + StringBuffer result = new StringBuffer(); + result.append(this.userName); + result.append(":"); + result.append((this.password == null) ? "null" : this.password); + return result.toString(); + } + + /** + * Does a hash of both user name and password. + * + * @return The hash code including user name and password. + */ + public int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.userName); + hash = LangUtils.hashCode(hash, this.password); + return hash; + } + + /** + * These credentials are assumed equal if the username and password are the + * same. + * + * @param o The other object to compare with. + * + * @return true if the object is equivalent. + */ + public boolean equals(Object o) { + if (o == null) return false; + if (this == o) return true; + // note - to allow for sub-classing, this checks that class is the same + // rather than do "instanceof". + if (this.getClass().equals(o.getClass())) { + UsernamePasswordCredentials that = (UsernamePasswordCredentials) o; + + if (LangUtils.equals(this.userName, that.userName) + && LangUtils.equals(this.password, that.password) ) { + return true; + } + } + return false; + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Wire.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Wire.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Wire.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,165 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/Wire.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Logs data to the wire LOG. + * + * @author Oleg Kalnichevski + * + * @since 2.0beta1 + */ +class Wire { + + public static Wire HEADER_WIRE = new Wire(LogFactory.getLog("httpclient.wire.header")); + + public static Wire CONTENT_WIRE = new Wire(LogFactory.getLog("httpclient.wire.content")); + + /** Log for any wire messages. */ + private Log log; + + private Wire(Log log) { + this.log = log; + } + + private void wire(String header, InputStream instream) + throws IOException { + StringBuffer buffer = new StringBuffer(); + int ch; + while ((ch = instream.read()) != -1) { + if (ch == 13) { + buffer.append("[\\r]"); + } else if (ch == 10) { + buffer.append("[\\n]\""); + buffer.insert(0, "\""); + buffer.insert(0, header); + log.debug(buffer.toString()); + buffer.setLength(0); + } else if ((ch < 32) || (ch > 127)) { + buffer.append("[0x"); + buffer.append(Integer.toHexString(ch)); + buffer.append("]"); + } else { + buffer.append((char) ch); + } + } + if (buffer.length() > 0) { + buffer.append("\""); + buffer.insert(0, "\""); + buffer.insert(0, header); + log.debug(buffer.toString()); + } + } + + + public boolean enabled() { + return log.isDebugEnabled(); + } + + public void output(InputStream outstream) + throws IOException { + if (outstream == null) { + throw new IllegalArgumentException("Output may not be null"); + } + wire(">> ", outstream); + } + + public void input(InputStream instream) + throws IOException { + if (instream == null) { + throw new IllegalArgumentException("Input may not be null"); + } + wire("<< ", instream); + } + + public void output(byte[] b, int off, int len) + throws IOException { + if (b == null) { + throw new IllegalArgumentException("Output may not be null"); + } + wire(">> ", new ByteArrayInputStream(b, off, len)); + } + + public void input(byte[] b, int off, int len) + throws IOException { + if (b == null) { + throw new IllegalArgumentException("Input may not be null"); + } + wire("<< ", new ByteArrayInputStream(b, off, len)); + } + + public void output(byte[] b) + throws IOException { + if (b == null) { + throw new IllegalArgumentException("Output may not be null"); + } + wire(">> ", new ByteArrayInputStream(b)); + } + + public void input(byte[] b) + throws IOException { + if (b == null) { + throw new IllegalArgumentException("Input may not be null"); + } + wire("<< ", new ByteArrayInputStream(b)); + } + + public void output(int b) + throws IOException { + output(new byte[] {(byte) b}); + } + + public void input(int b) + throws IOException { + input(new byte[] {(byte) b}); + } + + public void output(final String s) + throws IOException { + if (s == null) { + throw new IllegalArgumentException("Output may not be null"); + } + output(s.getBytes()); + } + + public void input(final String s) + throws IOException { + if (s == null) { + throw new IllegalArgumentException("Input may not be null"); + } + input(s.getBytes()); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogInputStream.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogInputStream.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogInputStream.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,98 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogInputStream.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Logs all data read to the wire LOG. + * + * @author Ortwin Gl�ck + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @since 2.0 + */ +class WireLogInputStream extends FilterInputStream { + + /** Original input stream. */ + private InputStream in; + + /** The wire log to use for writing. */ + private Wire wire; + + /** + * Create an instance that wraps the specified input stream. + * @param in The input stream. + * @param wire The wire log to use. + */ + public WireLogInputStream(InputStream in, Wire wire) { + super(in); + this.in = in; + this.wire = wire; + } + /** + * + * @see java.io.InputStream#read(byte[], int, int) + */ + public int read(byte[] b, int off, int len) throws IOException { + int l = this.in.read(b, off, len); + if (l > 0) { + wire.input(b, off, l); + } + return l; + } + + /** + * + * @see java.io.InputStream#read() + */ + public int read() throws IOException { + int l = this.in.read(); + if (l > 0) { + wire.input(l); + } + return l; + } + + /** + * + * @see java.io.InputStream#read(byte[]) + */ + public int read(byte[] b) throws IOException { + int l = this.in.read(b); + if (l > 0) { + wire.input(b, 0, l); + } + return l; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogOutputStream.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogOutputStream.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogOutputStream.java 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,88 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/WireLogOutputStream.java,v 1.1 2012/08/22 17:30:34 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:34 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Logs all data written to the wire LOG. + * + * @author Oleg Kalnichevski + * + * @since 2.0beta1 + */ +class WireLogOutputStream extends FilterOutputStream { + + /** Original input stream. */ + private OutputStream out; + + /** The wire log to use. */ + private Wire wire; + + /** + * Create an instance that wraps the specified output stream. + * @param out The output stream. + * @param wire The Wire log to use. + */ + public WireLogOutputStream(OutputStream out, Wire wire) { + super(out); + this.out = out; + this.wire = wire; + } + + /** + * + * @see java.io.OutputStream#write(byte[], int, int) + */ + public void write(byte[] b, int off, int len) throws IOException { + this.out.write(b, off, len); + wire.output(b, off, len); + } + + /** + * + * @see java.io.OutputStream#write() + */ + public void write(int b) throws IOException { + this.out.write(b); + wire.output(b); + } + + /** + * + * @see java.io.OutputStream#write(byte[]) + */ + public void write(byte[] b) throws IOException { + this.out.write(b); + wire.output(b); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/package.html 22 Aug 2012 17:30:34 -0000 1.1 @@ -0,0 +1,124 @@ + + + + Package Documentation for org.apache.commons.httpclient + + + +

Classes and interfaces supporting the client side of the HTTP protocol.

+

+ The HttpClient component supports the client-side of + RFC 1945 (HTTP/1.0) and + RFC 2616 (HTTP/1.1), + several related specifications + (RFC 2109 (Cookies), + RFC 2617 (HTTP Authentication), + etc.), and provides a framework by which new request types (methods) or HTTP + extensions can can be easily created or supported. +

+

+ The basis for the abstraction is provided by three types: +

+
    +
    {@link org.apache.commons.httpclient.HttpConnection}
    +
    + represents a network connection to some HTTP host. +
    +
    {@link org.apache.commons.httpclient.HttpMethod}
    +
    + represents a request to be made over some + {@link org.apache.commons.httpclient.HttpConnection} + and contains the server's response. +
    +
    {@link org.apache.commons.httpclient.HttpState}
    +
    + contains the HTTP attributes that may persist from + request to request, such as cookies and authentication + credentials. +
    +
+

+ and several simple bean-style classes: +

+
    +
    {@link org.apache.commons.httpclient.Cookie}
    +
    + represents HTTP cookie. +
    +
    {@link org.apache.commons.httpclient.Credentials}
    +
    + an interface representing a set of authentication credentials. +
    +
    {@link org.apache.commons.httpclient.Header}
    +
    + represents an HTTP request or response header. +
    +
    {@link org.apache.commons.httpclient.HeaderElement}
    +
    + represents a single element of a multi-part header. +
    +
    {@link org.apache.commons.httpclient.UsernamePasswordCredentials}
    +
    + a username and password pair. +
    +
+

+ {@link org.apache.commons.httpclient.HttpClient} provides a + simple "user-agent" implementation that will suffice for many + applications, but whose use is not required. +

+

+ HttpClient also provides several utilities that may be + useful when extending the framework: +

+
    +
    {@link org.apache.commons.httpclient.HttpMethodBase}
    +
    + an abstract base implementation of HttpMethod, + which may be extended to create new method types or + to support additional protocol HTTP features. +
    +
    {@link org.apache.commons.httpclient.HttpStatus}
    +
    + an enumeration of HttpStatus codes. +
    +
    {@link org.apache.commons.httpclient.ChunkedOutputStream}
    +
    + an {@link java.io.OutputStream} wrapper supporting the "chunked" + transfer encoding. +
    +
    {@link org.apache.commons.httpclient.ChunkedInputStream}
    +
    + an {@link java.io.InputStream} wrapper supporting the "chunked" + transfer encoding. +
    +
    {@link org.apache.commons.httpclient.util.URIUtil}
    +
    + provides utilities for encoding and decoding URI's in the + %HH format. +
    +
+ +

HttpClient Configuration with Java Properties

+ Java properties can be set at run time with the -Dname=value + command line arguments to the application that uses HttpClient. + These properties can also be set programaticly by calling + System.getProperties().setProperty(name, value). + This is the list of properties that HttpClient recognizes: + + + + + + + + + + + + + +
NameTypeEffect
httpclient.useragentStringSets the User-Agent string to be sent on every HTTP request.
httpclient.authentication.preemptivebooleanSends authorization credentials without requiring explicit requests + from the web server
+ + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeException.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,68 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeException.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +/** + * Signals a failure processing authentication challenge + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class AuthChallengeException extends AuthenticationException { + + /** + * Creates a new AuthChallengeException with a null detail message. + */ + public AuthChallengeException() { + super(); + } + + /** + * Creates a new AuthChallengeException with the specified message. + * + * @param message the exception detail message + */ + public AuthChallengeException(String message) { + super(message); + } + + /** + * Creates a new AuthChallengeException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public AuthChallengeException(String message, Throwable cause) { + super(message, cause); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeParser.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeParser.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeParser.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,135 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeParser.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.util.ParameterParser; + +/** + * This class provides utility methods for parsing HTTP www and proxy authentication + * challenges. + * + * @author Oleg Kalnichevski + * + * @since 2.0beta1 + */ +public final class AuthChallengeParser { + /** + * Extracts authentication scheme from the given authentication + * challenge. + * + * @param challengeStr the authentication challenge string + * @return authentication scheme + * + * @throws MalformedChallengeException when the authentication challenge string + * is malformed + * + * @since 2.0beta1 + */ + public static String extractScheme(final String challengeStr) + throws MalformedChallengeException { + if (challengeStr == null) { + throw new IllegalArgumentException("Challenge may not be null"); + } + int idx = challengeStr.indexOf(' '); + String s = null; + if (idx == -1) { + s = challengeStr; + } else { + s = challengeStr.substring(0, idx); + } + if (s.equals("")) { + throw new MalformedChallengeException("Invalid challenge: " + challengeStr); + } + return s.toLowerCase(); + } + + /** + * Extracts a map of challenge parameters from an authentication challenge. + * Keys in the map are lower-cased + * + * @param challengeStr the authentication challenge string + * @return a map of authentication challenge parameters + * @throws MalformedChallengeException when the authentication challenge string + * is malformed + * + * @since 2.0beta1 + */ + public static Map extractParams(final String challengeStr) + throws MalformedChallengeException { + if (challengeStr == null) { + throw new IllegalArgumentException("Challenge may not be null"); + } + int idx = challengeStr.indexOf(' '); + if (idx == -1) { + throw new MalformedChallengeException("Invalid challenge: " + challengeStr); + } + Map map = new HashMap(); + ParameterParser parser = new ParameterParser(); + List params = parser.parse( + challengeStr.substring(idx + 1, challengeStr.length()), ','); + for (int i = 0; i < params.size(); i++) { + NameValuePair param = (NameValuePair) params.get(i); + map.put(param.getName().toLowerCase(), param.getValue()); + } + return map; + } + + /** + * Extracts a map of challenges ordered by authentication scheme name + * + * @param headers the array of authorization challenges + * @return a map of authorization challenges + * + * @throws MalformedChallengeException if any of challenge strings + * is malformed + * + * @since 3.0 + */ + public static Map parseChallenges(final Header[] headers) + throws MalformedChallengeException { + if (headers == null) { + throw new IllegalArgumentException("Array of challenges may not be null"); + } + String challenge = null; + Map challengemap = new HashMap(headers.length); + for (int i = 0; i < headers.length; i++) { + challenge = headers[i].getValue(); + String s = AuthChallengeParser.extractScheme(challenge); + challengemap.put(s, challenge); + } + return challengemap; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeProcessor.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeProcessor.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeProcessor.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,165 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthChallengeProcessor.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.httpclient.params.HttpParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class provides utility methods for processing HTTP www and proxy authentication + * challenges. + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public final class AuthChallengeProcessor { + + private static final Log LOG = LogFactory.getLog(AuthChallengeProcessor.class); + + private HttpParams params = null; + + /** + * Creates an authentication challenge processor with the given {@link HttpParams HTTP + * parameters} + * + * @param params the {@link HttpParams HTTP parameters} used by this processor + */ + public AuthChallengeProcessor(final HttpParams params) { + super(); + if (params == null) { + throw new IllegalArgumentException("Parameter collection may not be null"); + } + this.params = params; + } + + /** + * Determines the preferred {@link AuthScheme authentication scheme} that can be used + * to respond to the given collection of challenges. + * + * @param challenges the collection of authentication challenges + * + * @return the preferred {@link AuthScheme authentication scheme} + * + * @throws AuthChallengeException if the preferred authentication scheme + * cannot be determined or is not supported + */ + public AuthScheme selectAuthScheme(final Map challenges) throws AuthChallengeException { + if (challenges == null) { + throw new IllegalArgumentException("Challenge map may not be null"); + } + Collection authPrefs = (Collection) this.params.getParameter( + AuthPolicy.AUTH_SCHEME_PRIORITY); + if (authPrefs == null || authPrefs.isEmpty()) { + authPrefs = AuthPolicy.getDefaultAuthPrefs(); + } + if (LOG.isDebugEnabled()) { + LOG.debug("Supported authentication schemes in the order of preference: " + + authPrefs); + } + AuthScheme authscheme = null; + String challenge = null; + Iterator item = authPrefs.iterator(); + while (item.hasNext()) { + String id = (String) item.next(); + challenge = (String) challenges.get(id.toLowerCase()); + if (challenge != null) { + if (LOG.isInfoEnabled()) { + LOG.info(id + " authentication scheme selected"); + } + try { + authscheme = AuthPolicy.getAuthScheme(id); + } catch (IllegalStateException e) { + throw new AuthChallengeException(e.getMessage()); + } + break; + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Challenge for " + id + " authentication scheme not available"); + // Try again + } + } + } + if (authscheme == null) { + // If none selected, something is wrong + throw new AuthChallengeException( + "Unable to respond to any of these challenges: " + + challenges); + } + return authscheme; + } + + /** + * Processes the given collection of challenges and updates the + * {@link AuthState state} of the authentication process. + * + * @param challenges the collection of authentication challenges + * + * @return the {@link AuthScheme authentication scheme} used to + * process the challenge + * + * @throws AuthChallengeException if authentication challenges cannot be + * successfully processed or the preferred authentication scheme cannot + * be determined + */ + public AuthScheme processChallenge(final AuthState state, final Map challenges) + throws MalformedChallengeException, AuthenticationException + { + if (state == null) { + throw new IllegalArgumentException("Authentication state may not be null"); + } + if (challenges == null) { + throw new IllegalArgumentException("Challenge map may not be null"); + } + + if (state.isPreemptive() || state.getAuthScheme() == null) { + // Authentication not attempted before + state.setAuthScheme(selectAuthScheme(challenges)); + } + AuthScheme authscheme = state.getAuthScheme(); + String id = authscheme.getSchemeName(); + if (LOG.isDebugEnabled()) { + LOG.debug("Using authentication scheme: " + id); + } + String challenge = (String) challenges.get(id.toLowerCase()); + if (challenge == null) { + throw new AuthenticationException(id + + " authorization challenge expected, but not found"); + } + authscheme.processChallenge(challenge); + LOG.debug("Authorization challenge processed"); + return authscheme; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthPolicy.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthPolicy.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthPolicy.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,188 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthPolicy.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Authentication policy class. The Authentication policy provides corresponding + * authentication scheme interfrace for a given type of authorization challenge. + *

The following specifications are provided: + *

    + *
  • Basic: Basic authentication scheme as defined in RFC2617 + * (considered inherently insecure, but most widely supported) + *
  • Digest: Digest authentication scheme as defined in RFC2617 + *
  • NTLM: The NTLM scheme is a proprietary Microsoft Windows + * Authentication protocol (considered to be the most secure among + * currently supported authentication schemes) + *
+ * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * @since 3.0 + */ +public abstract class AuthPolicy { + + private static final HashMap SCHEMES = new HashMap(); + private static final ArrayList SCHEME_LIST = new ArrayList(); + + /** + * The key used to look up the list of IDs of supported {@link AuthScheme + * authentication schemes} in their order of preference. The scheme IDs are + * stored in a {@link java.util.Collection} as {@link java.lang.String}s. + * + *

+ * If several schemes are returned in the WWW-Authenticate + * or Proxy-Authenticate header, this parameter defines which + * {@link AuthScheme authentication schemes} takes precedence over others. + * The first item in the collection represents the most preferred + * {@link AuthScheme authentication scheme}, the last item represents the ID + * of the least preferred one. + *

+ * + * @see org.apache.commons.httpclient.params.DefaultHttpParams + */ + public static final String AUTH_SCHEME_PRIORITY = "http.auth.scheme-priority"; + + /** + * 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"; + + static { + AuthPolicy.registerAuthScheme(NTLM, NTLMScheme.class); + AuthPolicy.registerAuthScheme(DIGEST, DigestScheme.class); + AuthPolicy.registerAuthScheme(BASIC, BasicScheme.class); + } + + /** Log object. */ + protected static final Log LOG = LogFactory.getLog(AuthPolicy.class); + + /** + * Registers a class implementing an {@link AuthScheme authentication scheme} with + * the given identifier. If a class with the given ID already exists it will be overridden. + * This ID is the same one used to retrieve the {@link AuthScheme authentication scheme} + * from {@link #getAuthScheme(String)}. + * + *

+ * Please note that custom authentication preferences, if used, need to be updated accordingly + * for the new {@link AuthScheme authentication scheme} to take effect. + *

+ * + * @param id the identifier for this scheme + * @param clazz the class to register + * + * @see #getAuthScheme(String) + * @see #AUTH_SCHEME_PRIORITY + */ + public static synchronized void registerAuthScheme(final String id, Class clazz) { + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + if (clazz == null) { + throw new IllegalArgumentException("Authentication scheme class may not be null"); + } + SCHEMES.put(id.toLowerCase(), clazz); + SCHEME_LIST.add(id.toLowerCase()); + } + + /** + * Unregisters the class implementing an {@link AuthScheme authentication scheme} with + * the given ID. + * + * @param id the ID of the class to unregister + */ + public static synchronized void unregisterAuthScheme(final String id) { + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + SCHEMES.remove(id.toLowerCase()); + SCHEME_LIST.remove(id.toLowerCase()); + } + + /** + * Gets the {@link AuthScheme authentication scheme} with the given ID. + * + * @param id the {@link AuthScheme authentication scheme} ID + * + * @return {@link AuthScheme authentication scheme} + * + * @throws IllegalStateException if a scheme with the ID cannot be found + */ + public static synchronized AuthScheme getAuthScheme(final String id) + throws IllegalStateException { + + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + Class clazz = (Class)SCHEMES.get(id.toLowerCase()); + if (clazz != null) { + try { + return (AuthScheme)clazz.newInstance(); + } catch (Exception e) { + LOG.error("Error initializing authentication scheme: " + id, e); + throw new IllegalStateException(id + + " authentication scheme implemented by " + + clazz.getName() + " could not be initialized"); + } + } else { + throw new IllegalStateException("Unsupported authentication scheme " + id); + } + } + + /** + * Returns a list containing all registered {@link AuthScheme authentication + * schemes} in their default order. + * + * @return {@link AuthScheme authentication scheme} + */ + public static synchronized List getDefaultAuthPrefs() { + return (List)SCHEME_LIST.clone(); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScheme.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScheme.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScheme.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,190 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScheme.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpMethod; + +/** + *

+ * This interface represents an abstract challenge-response oriented + * authentication scheme. + *

+ *

+ * An authentication scheme should be able to support the following + * functions: + *

    + *
  • Parse and process the challenge sent by the targer server + * in response to request for a protected resource + *
  • Provide its textual designation + *
  • Provide its parameters, if available + *
  • Provide the realm this authentication scheme is applicable to, + * if available + *
  • Generate authorization string for the given set of credentials, + * request method and URI as specificed in the HTTP request line + * in response to the actual authorization challenge + *
+ *

+ *

+ * Authentication schemes may ignore method name and URI parameters + * if they are not relevant for the given authentication mechanism + *

+ *

+ * Authentication schemes may be stateful involving a series of + * challenge-response exchanges + *

+ * + * @author Oleg Kalnichevski + * @author Adrian Sutton + * + * @since 2.0beta1 + */ + +public interface AuthScheme { + + /** + * Processes the given challenge token. Some authentication schemes + * may involve multiple challenge-response exchanges. Such schemes must be able + * to maintain the state information when dealing with sequential challenges + * + * @param challenge the challenge string + * + * @since 3.0 + */ + void processChallenge(final String challenge) throws MalformedChallengeException; + + /** + * Returns textual designation of the given authentication scheme. + * + * @return the name of the given authentication scheme + */ + String getSchemeName(); + + /** + * Returns authentication parameter with the given name, if available. + * + * @param name The name of the parameter to be returned + * + * @return the parameter with the given name + */ + String getParameter(final String name); + + /** + * Returns authentication realm. If the concept of an authentication + * realm is not applicable to the given authentication scheme, returns + * null. + * + * @return the authentication realm + */ + String getRealm(); + + /** + * Returns a String identifying the authentication challenge. This is + * used, in combination with the host and port to determine if + * authorization has already been attempted or not. Schemes which + * require multiple requests to complete the authentication should + * return a different value for each stage in the request. + * + *

Additionally, the ID should take into account any changes to the + * authentication challenge and return a different value when appropriate. + * For example when the realm changes in basic authentication it should be + * considered a different authentication attempt and a different value should + * be returned.

+ * + * @return String a String identifying the authentication challenge. The + * returned value may be null. + * + * @deprecated no longer used + */ + String getID(); + + /** + * Tests if the authentication scheme is provides authorization on a per + * connection basis instead of usual per request basis + * + * @return true if the scheme is connection based, false + * if the scheme is request based. + * + * @since 3.0 + */ + boolean isConnectionBased(); + + /** + * Authentication process may involve a series of challenge-response exchanges. + * This method tests if the authorization process has been completed, either + * successfully or unsuccessfully, that is, all the required authorization + * challenges have been processed in their entirety. + * + * @return true if the authentication process has been completed, + * false otherwise. + * + * @since 3.0 + */ + boolean isComplete(); + /** + * @deprecated Use {@link #authenticate(Credentials, HttpMethod)} + * + * Produces an authorization string for the given set of {@link Credentials}, + * method name and URI using the given authentication scheme in response to + * the actual authorization challenge. + * + * @param credentials The set of credentials to be used for athentication + * @param method The name of the method that requires authorization. + * This parameter may be ignored, if it is irrelevant + * or not applicable to the given authentication scheme + * @param uri The URI for which authorization is needed. + * This parameter may be ignored, if it is irrelevant or not + * applicable to the given authentication scheme + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return the authorization string + * + * @see org.apache.commons.httpclient.HttpMethod#getName() + * @see org.apache.commons.httpclient.HttpMethod#getPath() + */ + String authenticate(Credentials credentials, String method, String uri) + throws AuthenticationException; + + /** + * Produces an authorization string for the given set of {@link Credentials}. + * + * @param credentials The set of credentials to be used for athentication + * @param method The method being authenticated + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return the authorization string + * + * @since 3.0 + */ + String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException; + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthSchemeBase.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthSchemeBase.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthSchemeBase.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,92 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthSchemeBase.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +/** + *

+ * Abstract authentication scheme class that implements {@link AuthScheme} + * interface and provides a default contstructor. + *

+ * @deprecated No longer used + * + * @author Oleg Kalnichevski + */ +public abstract class AuthSchemeBase implements AuthScheme { + + /** + * Original challenge string as received from the server. + */ + private String challenge = null; + + /** + * Constructor for an abstract authetication schemes. + * + * @param challenge authentication challenge + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} + * method + */ + public AuthSchemeBase(final String challenge) + throws MalformedChallengeException { + super(); + if (challenge == null) { + throw new IllegalArgumentException("Challenge may not be null"); + } + this.challenge = challenge; + } + + /** + * @see java.lang.Object#equals(Object) + */ + public boolean equals(Object obj) { + if (obj instanceof AuthSchemeBase) { + return this.challenge.equals(((AuthSchemeBase) obj).challenge); + } else { + return super.equals(obj); + } + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.challenge.hashCode(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return this.challenge; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScope.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScope.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScope.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,328 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthScope.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.httpclient.util.LangUtils; + +/** + * The class represents an authentication scope consisting of a host name, + * a port number, a realm name and an authentication scheme name which + * {@link org.apache.commons.httpclient.Credentials} apply to. + * + * @author Oleg Kalnichevski + * @author Adrian Sutton + * + * @since 3.0 + */ +public class AuthScope { + + /** + * The null value represents any host. In the future versions of + * HttpClient the use of this parameter will be discontinued. + */ + public static final String ANY_HOST = null; + + /** + * The -1 value represents any port. + */ + public static final int ANY_PORT = -1; + + /** + * The null value represents any realm. + */ + public static final String ANY_REALM = null; + + /** + * The null value represents any authentication scheme. + */ + public static final String ANY_SCHEME = null; + + /** + * Default scope matching any host, port, realm and authentication scheme. + * In the future versions of HttpClient the use of this parameter will be + * discontinued. + */ + public static final AuthScope ANY = new AuthScope(ANY_HOST, ANY_PORT, ANY_REALM, ANY_SCHEME); + + /** The authentication scheme the credentials apply to. */ + private String scheme = null; + + /** The realm the credentials apply to. */ + private String realm = null; + + /** The host the credentials apply to. */ + private String host = null; + + /** The port the credentials apply to. */ + private int port = -1; + + /** Creates a new credentials scope for the given + * host, port, realm, and + * authentication scheme. + * + * @param host the host the credentials apply to. May be set + * to null if credenticals are applicable to + * any host. + * @param port the port the credentials apply to. May be set + * to negative value if credenticals are applicable to + * any port. + * @param realm the realm the credentials apply to. May be set + * to null if credenticals are applicable to + * any realm. + * @param scheme the authentication scheme the credentials apply to. + * May be set to null if credenticals are applicable to + * any authentication scheme. + * + * @since 3.0 + */ + public AuthScope(final String host, int port, + final String realm, final String scheme) + { + this.host = (host == null) ? ANY_HOST: host.toLowerCase(); + this.port = (port < 0) ? ANY_PORT: port; + this.realm = (realm == null) ? ANY_REALM: realm; + this.scheme = (scheme == null) ? ANY_SCHEME: scheme.toUpperCase();; + } + + /** Creates a new credentials scope for the given + * host, port, realm, and any + * authentication scheme. + * + * @param host the host the credentials apply to. May be set + * to null if credenticals are applicable to + * any host. + * @param port the port the credentials apply to. May be set + * to negative value if credenticals are applicable to + * any port. + * @param realm the realm the credentials apply to. May be set + * to null if credenticals are applicable to + * any realm. + * + * @since 3.0 + */ + public AuthScope(final String host, int port, final String realm) { + this(host, port, realm, ANY_SCHEME); + } + + /** Creates a new credentials scope for the given + * host, port, any realm name, and any + * authentication scheme. + * + * @param host the host the credentials apply to. May be set + * to null if credenticals are applicable to + * any host. + * @param port the port the credentials apply to. May be set + * to negative value if credenticals are applicable to + * any port. + * + * @since 3.0 + */ + public AuthScope(final String host, int port) { + this(host, port, ANY_REALM, ANY_SCHEME); + } + + /** + * Creates a copy of the given credentials scope. + * + * @since 3.0 + */ + public AuthScope(final AuthScope authscope) { + super(); + if (authscope == null) { + throw new IllegalArgumentException("Scope may not be null"); + } + this.host = authscope.getHost(); + this.port = authscope.getPort(); + this.realm = authscope.getRealm(); + this.scheme = authscope.getScheme(); + } + + /** + * @return the host + * + * @since 3.0 + */ + public String getHost() { + return this.host; + } + + /** + * @return the port + * + * @since 3.0 + */ + public int getPort() { + return this.port; + } + + /** + * @return the realm name + * + * @since 3.0 + */ + public String getRealm() { + return this.realm; + } + + /** + * @return the scheme type + * + * @since 3.0 + */ + public String getScheme() { + return this.scheme; + } + + /** Determines if the given parameters are equal. + * + * @param p1 the parameter + * @param p2 the other parameter + * @return boolean true if the parameters are equal, otherwise false. + */ + private static boolean paramsEqual(final String p1, final String p2) { + if (p1 == null) { + return p1 == p2; + } else { + return p1.equals(p2); + } + } + + /** Determines if the given parameters are equal. + * + * @param p1 the parameter + * @param p2 the other parameter + * @return boolean true if the parameters are equal, otherwise false. + */ + private static boolean paramsEqual(int p1, int p2) { + return p1 == p2; + } + + /** + * Tests if the authentication scopes match. + * + * @return the match factor. Negative value signifies no match. + * Non-negative signifies a match. The greater the returned value + * the closer the match. + * + * @since 3.0 + */ + public int match(final AuthScope that) { + int factor = 0; + if (paramsEqual(this.scheme, that.scheme)) { + factor += 1; + } else { + if (this.scheme != ANY_SCHEME && that.scheme != ANY_SCHEME) { + return -1; + } + } + if (paramsEqual(this.realm, that.realm)) { + factor += 2; + } else { + if (this.realm != ANY_REALM && that.realm != ANY_REALM) { + return -1; + } + } + if (paramsEqual(this.port, that.port)) { + factor += 4; + } else { + if (this.port != ANY_PORT && that.port != ANY_PORT) { + return -1; + } + } + if (paramsEqual(this.host, that.host)) { + factor += 8; + } else { + if (this.host != ANY_HOST && that.host != ANY_HOST) { + return -1; + } + } + return factor; + } + + /** + * @see java.lang.Object#equals(Object) + */ + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (o == this) { + return true; + } + if (!(o instanceof AuthScope)) { + return super.equals(o); + } + AuthScope that = (AuthScope) o; + return + paramsEqual(this.host, that.host) + && paramsEqual(this.port, that.port) + && paramsEqual(this.realm, that.realm) + && paramsEqual(this.scheme, that.scheme); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + if (this.scheme != null) { + buffer.append(this.scheme.toUpperCase()); + buffer.append(' '); + } + if (this.realm != null) { + buffer.append('\''); + buffer.append(this.realm); + buffer.append('\''); + } else { + buffer.append(""); + } + if (this.host != null) { + buffer.append('@'); + buffer.append(this.host); + if (this.port >= 0) { + buffer.append(':'); + buffer.append(this.port); + } + } + return buffer.toString(); + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.host); + hash = LangUtils.hashCode(hash, this.port); + hash = LangUtils.hashCode(hash, this.realm); + hash = LangUtils.hashCode(hash, this.scheme); + return hash; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthState.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthState.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthState.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,192 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthState.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +/** + * This class provides detailed information about the state of the + * authentication process. + * + * @author Oleg Kalnichevski + * @since 3.0 + */ +public class AuthState { + + public static final String PREEMPTIVE_AUTH_SCHEME = "basic"; + + /** Actual authentication scheme */ + private AuthScheme authScheme = null; + + /** Whether an authetication challenged has been received */ + private boolean authRequested = false; + + /** Whether the authetication challenge has been responsed to */ + private boolean authAttempted = false; + + /** Whether preemtive authentication is attempted */ + private boolean preemptive = false; + + /** + * Default constructor. + * + */ + public AuthState() { + super(); + } + + /** + * Invalidates the authentication state by resetting its parameters. + */ + public void invalidate() { + this.authScheme = null; + this.authRequested = false; + this.authAttempted = false; + this.preemptive = false; + } + + /** + * Tests whether authenication challenge has been received + * + * @return true if authenication challenge has been received, + * false otherwise + */ + public boolean isAuthRequested() { + return this.authRequested; + } + + /** + * Sets authentication request status + * + * @param challengeReceived true if authenication has been requested, + * false otherwise + */ + public void setAuthRequested(boolean challengeReceived) { + this.authRequested = challengeReceived; + } + + /** + * Tests whether authenication challenge has been responsed to + * + * @return true if authenication challenge has been responsed to, + * false otherwise + */ + public boolean isAuthAttempted() { + return this.authAttempted; + } + + /** + * Sets authentication attempt status + * + * @param challengeResponded true if authenication has been attempted, + * false otherwise + */ + public void setAuthAttempted(boolean challengeResponded) { + this.authAttempted = challengeResponded; + } + + /** + * Preemptively assigns Basic authentication scheme. + */ + public void setPreemptive() { + if (!this.preemptive) { + if (this.authScheme != null) { + throw new IllegalStateException("Authentication state already initialized"); + } + this.authScheme = AuthPolicy.getAuthScheme(PREEMPTIVE_AUTH_SCHEME); + this.preemptive = true; + } + } + + /** + * Tests if preemptive authentication is used. + * + * @return true if using the default Basic {@link AuthScheme + * authentication scheme}, false otherwise. + */ + public boolean isPreemptive() { + return this.preemptive; + } + + /** + * Assigns the given {@link AuthScheme authentication scheme}. + * + * @param authScheme the {@link AuthScheme authentication scheme} + */ + public void setAuthScheme(final AuthScheme authScheme) { + if (authScheme == null) { + invalidate(); + return; + } + if (this.preemptive && !(this.authScheme.getClass().isInstance(authScheme))) { + this.preemptive = false; + this.authAttempted = false; + } + this.authScheme = authScheme; + } + + /** + * Returns the {@link AuthScheme authentication scheme}. + * + * @return {@link AuthScheme authentication scheme} + */ + public AuthScheme getAuthScheme() { + return authScheme; + } + + /** + * Returns the authentication realm. + * + * @return the name of the authentication realm + */ + public String getRealm() { + if (this.authScheme != null) { + return this.authScheme.getRealm(); + } else { + return null; + } + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("Auth state: auth requested ["); + buffer.append(this.authRequested); + buffer.append("]; auth attempted ["); + buffer.append(this.authAttempted); + if (this.authScheme != null) { + buffer.append("]; auth scheme ["); + buffer.append(this.authScheme.getSchemeName()); + buffer.append("]; realm ["); + buffer.append(this.authScheme.getRealm()); + } + buffer.append("] preemptive ["); + buffer.append(this.preemptive); + buffer.append("]"); + return buffer.toString(); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthenticationException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthenticationException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthenticationException.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,72 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/AuthenticationException.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.httpclient.ProtocolException; + +/** + * Signals a failure in authentication process + * + * @author Oleg Kalnichevski + * + * @since 2.0 + */ +public class AuthenticationException extends ProtocolException { + + /** + * Creates a new AuthenticationException with a null detail message. + */ + public AuthenticationException() { + super(); + } + + /** + * Creates a new AuthenticationException with the specified message. + * + * @param message the exception detail message + */ + public AuthenticationException(String message) { + super(message); + } + + /** + * Creates a new AuthenticationException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + * + * @since 3.0 + */ + public AuthenticationException(String message, Throwable cause) { + super(message, cause); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/BasicScheme.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/BasicScheme.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/BasicScheme.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,248 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/BasicScheme.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * Basic authentication scheme as defined in RFC 2617. + *

+ * + * @author Remy Maucherat + * @author Rodney Waldhoff + * @author Jeff Dever + * @author Ortwin Gl?ck + * @author Sean C. Sullivan + * @author Adrian Sutton + * @author Mike Bowler + * @author Oleg Kalnichevski + */ + +public class BasicScheme extends RFC2617Scheme { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(BasicScheme.class); + + /** Whether the basic authentication process is complete */ + private boolean complete; + + /** + * Default constructor for the basic authetication scheme. + * + * @since 3.0 + */ + public BasicScheme() { + super(); + this.complete = false; + } + + /** + * Constructor for the basic authetication scheme. + * + * @param challenge authentication challenge + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} + * method + */ + public BasicScheme(final String challenge) throws MalformedChallengeException { + super(challenge); + this.complete = true; + } + + /** + * Returns textual designation of the basic authentication scheme. + * + * @return basic + */ + public String getSchemeName() { + return "basic"; + } + + /** + * Processes the Basic challenge. + * + * @param challenge the challenge string + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @since 3.0 + */ + public void processChallenge(String challenge) + throws MalformedChallengeException + { + super.processChallenge(challenge); + this.complete = true; + } + + /** + * Tests if the Basic authentication process has been completed. + * + * @return true if Basic authorization has been processed, + * false otherwise. + * + * @since 3.0 + */ + public boolean isComplete() { + return this.complete; + } + + /** + * Produces basic authorization string for the given set of + * {@link Credentials}. + * + * @param credentials The set of credentials to be used for athentication + * @param method Method name is ignored by the basic authentication scheme + * @param uri URI is ignored by the basic authentication scheme + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for this authentication scheme + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return a basic authorization string + * + * @deprecated Use {@link #authenticate(Credentials, HttpMethod)} + */ + public String authenticate(Credentials credentials, String method, String uri) + throws AuthenticationException { + + LOG.trace("enter BasicScheme.authenticate(Credentials, String, String)"); + + UsernamePasswordCredentials usernamepassword = null; + try { + usernamepassword = (UsernamePasswordCredentials) credentials; + } catch (ClassCastException e) { + throw new InvalidCredentialsException( + "Credentials cannot be used for basic authentication: " + + credentials.getClass().getName()); + } + return BasicScheme.authenticate(usernamepassword); + } + + /** + * Returns false. Basic authentication scheme is request based. + * + * @return false. + * + * @since 3.0 + */ + public boolean isConnectionBased() { + return false; + } + + /** + * Produces basic authorization string for the given set of {@link Credentials}. + * + * @param credentials The set of credentials to be used for athentication + * @param method The method being authenticated + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for this authentication scheme + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return a basic authorization string + * + * @since 3.0 + */ + public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException { + + LOG.trace("enter BasicScheme.authenticate(Credentials, HttpMethod)"); + + if (method == null) { + throw new IllegalArgumentException("Method may not be null"); + } + UsernamePasswordCredentials usernamepassword = null; + try { + usernamepassword = (UsernamePasswordCredentials) credentials; + } catch (ClassCastException e) { + throw new InvalidCredentialsException( + "Credentials cannot be used for basic authentication: " + + credentials.getClass().getName()); + } + return BasicScheme.authenticate( + usernamepassword, + method.getParams().getCredentialCharset()); + } + + /** + * @deprecated Use {@link #authenticate(UsernamePasswordCredentials, String)} + * + * Returns a basic Authorization header value for the given + * {@link UsernamePasswordCredentials}. + * + * @param credentials The credentials to encode. + * + * @return a basic authorization string + */ + public static String authenticate(UsernamePasswordCredentials credentials) { + return authenticate(credentials, "ISO-8859-1"); + } + + /** + * Returns a basic Authorization header value for the given + * {@link UsernamePasswordCredentials} and charset. + * + * @param credentials The credentials to encode. + * @param charset The charset to use for encoding the credentials + * + * @return a basic authorization string + * + * @since 3.0 + */ + public static String authenticate(UsernamePasswordCredentials credentials, String charset) { + + LOG.trace("enter BasicScheme.authenticate(UsernamePasswordCredentials, String)"); + + if (credentials == null) { + throw new IllegalArgumentException("Credentials may not be null"); + } + if (charset == null || charset.length() == 0) { + throw new IllegalArgumentException("charset may not be null or empty"); + } + StringBuffer buffer = new StringBuffer(); + buffer.append(credentials.getUserName()); + buffer.append(":"); + buffer.append(credentials.getPassword()); + + return "Basic " + EncodingUtil.getAsciiString( + Base64.encodeBase64(EncodingUtil.getBytes(buffer.toString(), charset))); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsNotAvailableException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsNotAvailableException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsNotAvailableException.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,67 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsNotAvailableException.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +/** + * Authentication credentials required to respond to a authentication + * challenge are not available + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class CredentialsNotAvailableException extends AuthenticationException { + /** + * Creates a new CredentialsNotAvailableException with a null detail message. + */ + public CredentialsNotAvailableException() { + super(); + } + + /** + * Creates a new CredentialsNotAvailableException with the specified message. + * + * @param message the exception detail message + */ + public CredentialsNotAvailableException(String message) { + super(message); + } + + /** + * Creates a new CredentialsNotAvailableException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public CredentialsNotAvailableException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsProvider.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsProvider.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsProvider.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,87 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/CredentialsProvider.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.httpclient.Credentials; + +/** + *

+ * Credentials provider interface can be used to provide {@link + * org.apache.commons.httpclient.HttpMethod HTTP method} with a means to request + * authentication credentials if no credentials have been given or given + * credentials are incorrect. + *

+ *

+ * HttpClient makes no provisions to check whether the same credentials have + * been tried already. It is a responsibility of the custom credentials provider + * to keep track of authentication attempts and to ensure that credentials known + * to be invalid are not retried. HttpClient will simply store the set of + * credentials returned by the custom credentials provider in the + * {@link org.apache.commons.httpclient.HttpState http state} object and will + * attempt to use these credentials for all subsequent requests with the given + * authentication scope. + *

+ *

+ * Classes implementing this interface must synchronize access to shared data as + * methods of this interfrace may be executed from multiple threads + *

+ * + * + * @author Ortwin Glueck + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public interface CredentialsProvider { + + /** + * Sets the credentials provider parameter. + *

+ * This parameter expects a value of type {@link CredentialsProvider}. + *

+ */ + public static final String PROVIDER = "http.authentication.credential-provider"; + + /** + * Requests additional {@link Credentials authentication credentials}. + * + * @param scheme the {@link AuthScheme authentication scheme} + * @param host the authentication host + * @param port the port of the authentication host + * @param proxy true if authenticating with a proxy, + * false otherwise + */ + public Credentials getCredentials( + final AuthScheme scheme, + final String host, + int port, + boolean proxy) throws CredentialsNotAvailableException; + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/DigestScheme.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/DigestScheme.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/DigestScheme.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,561 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/DigestScheme.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpClientError; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.httpclient.util.ParameterFormatter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * Digest authentication scheme as defined in RFC 2617. + * Both MD5 (default) and MD5-sess are supported. + * Currently only qop=auth or no qop is supported. qop=auth-int + * is unsupported. If auth and auth-int are provided, auth is + * used. + *

+ *

+ * Credential charset is configured via the + * {@link org.apache.commons.httpclient.params.HttpMethodParams#CREDENTIAL_CHARSET credential + * charset} parameter. Since the digest username is included as clear text in the generated + * Authentication header, the charset of the username must be compatible with the + * {@link org.apache.commons.httpclient.params.HttpMethodParams#HTTP_ELEMENT_CHARSET http element + * charset}. + *

+ * TODO: make class more stateful regarding repeated authentication requests + * + * @author Remy Maucherat + * @author Rodney Waldhoff + * @author Jeff Dever + * @author Ortwin Gl?ck + * @author Sean C. Sullivan + * @author Adrian Sutton + * @author Mike Bowler + * @author Oleg Kalnichevski + */ + +public class DigestScheme extends RFC2617Scheme { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(DigestScheme.class); + + /** + * Hexa values used when creating 32 character long digest in HTTP DigestScheme + * in case of authentication. + * + * @see #encode(byte[]) + */ + private static final char[] HEXADECIMAL = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', + 'e', 'f' + }; + + /** Whether the digest authentication process is complete */ + private boolean complete; + + //TODO: supply a real nonce-count, currently a server will interprete a repeated request as a replay + private static final String NC = "00000001"; //nonce-count is always 1 + private static final int QOP_MISSING = 0; + private static final int QOP_AUTH_INT = 1; + private static final int QOP_AUTH = 2; + + private int qopVariant = QOP_MISSING; + private String cnonce; + + private final ParameterFormatter formatter; + /** + * Default constructor for the digest authetication scheme. + * + * @since 3.0 + */ + public DigestScheme() { + super(); + this.complete = false; + this.formatter = new ParameterFormatter(); + } + + /** + * Gets an ID based upon the realm and the nonce value. This ensures that requests + * to the same realm with different nonce values will succeed. This differentiation + * allows servers to request re-authentication using a fresh nonce value. + * + * @deprecated no longer used + */ + public String getID() { + + String id = getRealm(); + String nonce = getParameter("nonce"); + if (nonce != null) { + id += "-" + nonce; + } + + return id; + } + + /** + * Constructor for the digest authetication scheme. + * + * @param challenge authentication challenge + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} + * method + */ + public DigestScheme(final String challenge) + throws MalformedChallengeException { + this(); + processChallenge(challenge); + } + + /** + * Processes the Digest challenge. + * + * @param challenge the challenge string + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @since 3.0 + */ + public void processChallenge(final String challenge) + throws MalformedChallengeException { + super.processChallenge(challenge); + + if (getParameter("realm") == null) { + throw new MalformedChallengeException("missing realm in challange"); + } + if (getParameter("nonce") == null) { + throw new MalformedChallengeException("missing nonce in challange"); + } + + boolean unsupportedQop = false; + // qop parsing + String qop = getParameter("qop"); + if (qop != null) { + StringTokenizer tok = new StringTokenizer(qop,","); + while (tok.hasMoreTokens()) { + String variant = tok.nextToken().trim(); + if (variant.equals("auth")) { + qopVariant = QOP_AUTH; + break; //that's our favourite, because auth-int is unsupported + } else if (variant.equals("auth-int")) { + qopVariant = QOP_AUTH_INT; + } else { + unsupportedQop = true; + LOG.warn("Unsupported qop detected: "+ variant); + } + } + } + + if (unsupportedQop && (qopVariant == QOP_MISSING)) { + throw new MalformedChallengeException("None of the qop methods is supported"); + } + + cnonce = createCnonce(); + this.complete = true; + } + + /** + * Tests if the Digest authentication process has been completed. + * + * @return true if Digest authorization has been processed, + * false otherwise. + * + * @since 3.0 + */ + public boolean isComplete() { + String s = getParameter("stale"); + if ("true".equalsIgnoreCase(s)) { + return false; + } else { + return this.complete; + } + } + + /** + * Returns textual designation of the digest authentication scheme. + * + * @return digest + */ + public String getSchemeName() { + return "digest"; + } + + /** + * Returns false. Digest authentication scheme is request based. + * + * @return false. + * + * @since 3.0 + */ + public boolean isConnectionBased() { + return false; + } + + /** + * Produces a digest authorization string for the given set of + * {@link Credentials}, method name and URI. + * + * @param credentials A set of credentials to be used for athentication + * @param method the name of the method that requires authorization. + * @param uri The URI for which authorization is needed. + * + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for this authentication scheme + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return a digest authorization string + * + * @see org.apache.commons.httpclient.HttpMethod#getName() + * @see org.apache.commons.httpclient.HttpMethod#getPath() + * + * @deprecated Use {@link #authenticate(Credentials, HttpMethod)} + */ + public String authenticate(Credentials credentials, String method, String uri) + throws AuthenticationException { + + LOG.trace("enter DigestScheme.authenticate(Credentials, String, String)"); + + UsernamePasswordCredentials usernamepassword = null; + try { + usernamepassword = (UsernamePasswordCredentials) credentials; + } catch (ClassCastException e) { + throw new InvalidCredentialsException( + "Credentials cannot be used for digest authentication: " + + credentials.getClass().getName()); + } + getParameters().put("methodname", method); + getParameters().put("uri", uri); + String digest = createDigest( + usernamepassword.getUserName(), + usernamepassword.getPassword()); + return "Digest " + createDigestHeader(usernamepassword.getUserName(), digest); + } + + /** + * Produces a digest authorization string for the given set of + * {@link Credentials}, method name and URI. + * + * @param credentials A set of credentials to be used for athentication + * @param method The method being authenticated + * + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for this authentication scheme + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return a digest authorization string + * + * @since 3.0 + */ + public String authenticate(Credentials credentials, HttpMethod method) + throws AuthenticationException { + + LOG.trace("enter DigestScheme.authenticate(Credentials, HttpMethod)"); + + UsernamePasswordCredentials usernamepassword = null; + try { + usernamepassword = (UsernamePasswordCredentials) credentials; + } catch (ClassCastException e) { + throw new InvalidCredentialsException( + "Credentials cannot be used for digest authentication: " + + credentials.getClass().getName()); + } + getParameters().put("methodname", method.getName()); + getParameters().put("uri", method.getPath()); + String charset = getParameter("charset"); + if (charset == null) { + getParameters().put("charset", method.getParams().getCredentialCharset()); + } + String digest = createDigest( + usernamepassword.getUserName(), + usernamepassword.getPassword()); + return "Digest " + createDigestHeader(usernamepassword.getUserName(), + digest); + } + + /** + * Creates an MD5 response digest. + * + * @param uname Username + * @param pwd Password + * @param charset The credential charset + * + * @return The created digest as string. This will be the response tag's + * value in the Authentication HTTP header. + * @throws AuthenticationException when MD5 is an unsupported algorithm + */ + private String createDigest(final String uname, final String pwd) throws AuthenticationException { + + LOG.trace("enter DigestScheme.createDigest(String, String, Map)"); + + final String digAlg = "MD5"; + + // Collecting required tokens + String uri = getParameter("uri"); + String realm = getParameter("realm"); + String nonce = getParameter("nonce"); + String qop = getParameter("qop"); + String method = getParameter("methodname"); + String algorithm = getParameter("algorithm"); + // If an algorithm is not specified, default to MD5. + if (algorithm == null) { + algorithm = "MD5"; + } + // If an charset is not specified, default to ISO-8859-1. + String charset = getParameter("charset"); + if (charset == null) { + charset = "ISO-8859-1"; + } + + if (qopVariant == QOP_AUTH_INT) { + LOG.warn("qop=auth-int is not supported"); + throw new AuthenticationException( + "Unsupported qop in HTTP Digest authentication"); + } + + MessageDigest md5Helper; + + try { + md5Helper = MessageDigest.getInstance(digAlg); + } catch (Exception e) { + throw new AuthenticationException( + "Unsupported algorithm in HTTP Digest authentication: " + + digAlg); + } + + // 3.2.2.2: Calculating digest + StringBuffer tmp = new StringBuffer(uname.length() + realm.length() + pwd.length() + 2); + tmp.append(uname); + tmp.append(':'); + tmp.append(realm); + tmp.append(':'); + tmp.append(pwd); + // unq(username-value) ":" unq(realm-value) ":" passwd + String a1 = tmp.toString(); + //a1 is suitable for MD5 algorithm + if(algorithm.equals("MD5-sess")) { + // H( unq(username-value) ":" unq(realm-value) ":" passwd ) + // ":" unq(nonce-value) + // ":" unq(cnonce-value) + + String tmp2=encode(md5Helper.digest(EncodingUtil.getBytes(a1, charset))); + StringBuffer tmp3 = new StringBuffer(tmp2.length() + nonce.length() + cnonce.length() + 2); + tmp3.append(tmp2); + tmp3.append(':'); + tmp3.append(nonce); + tmp3.append(':'); + tmp3.append(cnonce); + a1 = tmp3.toString(); + } else if(!algorithm.equals("MD5")) { + LOG.warn("Unhandled algorithm " + algorithm + " requested"); + } + String md5a1 = encode(md5Helper.digest(EncodingUtil.getBytes(a1, charset))); + + String a2 = null; + if (qopVariant == QOP_AUTH_INT) { + LOG.error("Unhandled qop auth-int"); + //we do not have access to the entity-body or its hash + //TODO: add Method ":" digest-uri-value ":" H(entity-body) + } else { + a2 = method + ":" + uri; + } + String md5a2 = encode(md5Helper.digest(EncodingUtil.getAsciiBytes(a2))); + + // 3.2.2.1 + String serverDigestValue; + if (qopVariant == QOP_MISSING) { + LOG.debug("Using null qop method"); + StringBuffer tmp2 = new StringBuffer(md5a1.length() + nonce.length() + md5a2.length()); + tmp2.append(md5a1); + tmp2.append(':'); + tmp2.append(nonce); + tmp2.append(':'); + tmp2.append(md5a2); + serverDigestValue = tmp2.toString(); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Using qop method " + qop); + } + String qopOption = getQopVariantString(); + StringBuffer tmp2 = new StringBuffer(md5a1.length() + nonce.length() + + NC.length() + cnonce.length() + qopOption.length() + md5a2.length() + 5); + tmp2.append(md5a1); + tmp2.append(':'); + tmp2.append(nonce); + tmp2.append(':'); + tmp2.append(NC); + tmp2.append(':'); + tmp2.append(cnonce); + tmp2.append(':'); + tmp2.append(qopOption); + tmp2.append(':'); + tmp2.append(md5a2); + serverDigestValue = tmp2.toString(); + } + + String serverDigest = + encode(md5Helper.digest(EncodingUtil.getAsciiBytes(serverDigestValue))); + + return serverDigest; + } + + /** + * Creates digest-response header as defined in RFC2617. + * + * @param uname Username + * @param digest The response tag's value as String. + * + * @return The digest-response as String. + */ + private String createDigestHeader(final String uname, final String digest) + throws AuthenticationException { + + LOG.trace("enter DigestScheme.createDigestHeader(String, Map, " + + "String)"); + + String uri = getParameter("uri"); + String realm = getParameter("realm"); + String nonce = getParameter("nonce"); + String opaque = getParameter("opaque"); + String response = digest; + String algorithm = getParameter("algorithm"); + + List params = new ArrayList(20); + params.add(new NameValuePair("username", uname)); + params.add(new NameValuePair("realm", realm)); + params.add(new NameValuePair("nonce", nonce)); + params.add(new NameValuePair("uri", uri)); + params.add(new NameValuePair("response", response)); + + if (qopVariant != QOP_MISSING) { + params.add(new NameValuePair("qop", getQopVariantString())); + params.add(new NameValuePair("nc", NC)); + params.add(new NameValuePair("cnonce", this.cnonce)); + } + if (algorithm != null) { + params.add(new NameValuePair("algorithm", algorithm)); + } + if (opaque != null) { + params.add(new NameValuePair("opaque", opaque)); + } + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < params.size(); i++) { + NameValuePair param = (NameValuePair) params.get(i); + if (i > 0) { + buffer.append(", "); + } + boolean noQuotes = "nc".equals(param.getName()) || + "qop".equals(param.getName()); + this.formatter.setAlwaysUseQuotes(!noQuotes); + this.formatter.format(buffer, param); + } + return buffer.toString(); + } + + private String getQopVariantString() { + String qopOption; + if (qopVariant == QOP_AUTH_INT) { + qopOption = "auth-int"; + } else { + qopOption = "auth"; + } + return qopOption; + } + + /** + * Encodes the 128 bit (16 bytes) MD5 digest into a 32 characters long + * String according to RFC 2617. + * + * @param binaryData array containing the digest + * @return encoded MD5, or null if encoding failed + */ + private static String encode(byte[] binaryData) { + LOG.trace("enter DigestScheme.encode(byte[])"); + + if (binaryData.length != 16) { + return null; + } + + char[] buffer = new char[32]; + for (int i = 0; i < 16; i++) { + int low = (int) (binaryData[i] & 0x0f); + int high = (int) ((binaryData[i] & 0xf0) >> 4); + buffer[i * 2] = HEXADECIMAL[high]; + buffer[(i * 2) + 1] = HEXADECIMAL[low]; + } + + return new String(buffer); + } + + + /** + * Creates a random cnonce value based on the current time. + * + * @return The cnonce value as String. + * @throws HttpClientError if MD5 algorithm is not supported. + */ + public static String createCnonce() { + LOG.trace("enter DigestScheme.createCnonce()"); + + String cnonce; + final String digAlg = "MD5"; + MessageDigest md5Helper; + + try { + md5Helper = MessageDigest.getInstance(digAlg); + } catch (NoSuchAlgorithmException e) { + throw new HttpClientError( + "Unsupported algorithm in HTTP Digest authentication: " + + digAlg); + } + + cnonce = Long.toString(System.currentTimeMillis()); + cnonce = encode(md5Helper.digest(EncodingUtil.getAsciiBytes(cnonce))); + + return cnonce; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthRealm.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthRealm.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthRealm.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,56 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthRealm.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +/** The key used to look up authentication credentials. + * + * @author Oleg Kalnichevski + * @author Adrian Sutton + * + * @deprecated no longer used + */ +public class HttpAuthRealm extends AuthScope { + + /** Creates a new HttpAuthRealm for the given domain and + * realm. + * + * @param domain the domain the credentials apply to. May be set + * to null if credenticals are applicable to + * any domain. + * @param realm the realm the credentials apply to. May be set + * to null if credenticals are applicable to + * any realm. + * + */ + public HttpAuthRealm(final String domain, final String realm) { + super(domain, ANY_PORT, realm, ANY_SCHEME); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthenticator.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthenticator.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthenticator.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,392 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/HttpAuthenticator.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Utility methods for HTTP authorization and authentication. This class + * provides utility methods for generating responses to HTTP www and proxy + * authentication challenges. + * + *
+ * A client SHOULD assume that all paths at or deeper than the depth of the + * last symbolic element in the path field of the Request-URI also are within + * the protection space specified by the basic realm value of the current + * challenge. A client MAY preemptively send the corresponding Authorization + * header with requests for resources in that space without receipt of another + * challenge from the server. Similarly, when a client sends a request to a + * proxy, it may reuse a userid and password in the Proxy-Authorization header + * field without receiving another challenge from the proxy server. + *
+ *

+ * + * @author Remy Maucherat + * @author Rodney Waldhoff + * @author Jeff Dever + * @author Ortwin Gl�ck + * @author Sean C. Sullivan + * @author Adrian Sutton + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @deprecated no longer used + */ +public final class HttpAuthenticator { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpAuthenticator.class); + + /** + * The www authenticate challange header. + */ + public static final String WWW_AUTH = "WWW-Authenticate"; + + /** + * The www authenticate response header. + */ + public static final String WWW_AUTH_RESP = "Authorization"; + + /** + * The proxy authenticate challange header. + */ + public static final String PROXY_AUTH = "Proxy-Authenticate"; + + /** + * The proxy authenticate response header. + */ + public static final String PROXY_AUTH_RESP = "Proxy-Authorization"; + + /** Chooses the strongest authentication scheme supported from the + * array of authentication challenges. Currently only NTLM, + * Digest, Basic schemes are recognized. + * The NTLM scheme is considered the strongest and is + * preferred to all others. The Digest scheme is preferred to + * the Basic one which provides no encryption for credentials. + * The Basic scheme is used only if it is the only one + * supported. + * + * @param challenges The array of authentication challenges + * + * @return The strongest authentication scheme supported + * + * @throws MalformedChallengeException is thrown if an authentication + * challenge is malformed + * @throws UnsupportedOperationException when none of challenge types + * available is supported. + * + * @deprecated Use {@link AuthChallengeParser#parseChallenges(Header[])} and + * {@link AuthPolicy#getAuthScheme(String)} + */ + public static AuthScheme selectAuthScheme(final Header[] challenges) + throws MalformedChallengeException { + LOG.trace("enter HttpAuthenticator.selectAuthScheme(Header[])"); + if (challenges == null) { + throw new IllegalArgumentException("Array of challenges may not be null"); + } + if (challenges.length == 0) { + throw new IllegalArgumentException("Array of challenges may not be empty"); + } + String challenge = null; + Map challengemap = new HashMap(challenges.length); + for (int i = 0; i < challenges.length; i++) { + challenge = challenges[i].getValue(); + String s = AuthChallengeParser.extractScheme(challenge); + challengemap.put(s, challenge); + } + challenge = (String) challengemap.get("ntlm"); + if (challenge != null) { + return new NTLMScheme(challenge); + } + challenge = (String) challengemap.get("digest"); + if (challenge != null) { + return new DigestScheme(challenge); + } + challenge = (String) challengemap.get("basic"); + if (challenge != null) { + return new BasicScheme(challenge); + } + throw new UnsupportedOperationException( + "Authentication scheme(s) not supported: " + challengemap.toString()); + } + + private static boolean doAuthenticateDefault( + HttpMethod method, + HttpConnection conn, + HttpState state, + boolean proxy) + throws AuthenticationException { + if (method == null) { + throw new IllegalArgumentException("HTTP method may not be null"); + } + if (state == null) { + throw new IllegalArgumentException("HTTP state may not be null"); + } + String host = null; + if (conn != null) { + host = proxy ? conn.getProxyHost() : conn.getHost(); + } + Credentials credentials = proxy + ? state.getProxyCredentials(null, host) : state.getCredentials(null, host); + if (credentials == null) { + return false; + } + if (!(credentials instanceof UsernamePasswordCredentials)) { + throw new InvalidCredentialsException( + "Credentials cannot be used for basic authentication: " + + credentials.toString()); + } + String auth = BasicScheme.authenticate( + (UsernamePasswordCredentials) credentials, + method.getParams().getCredentialCharset()); + if (auth != null) { + String s = proxy ? PROXY_AUTH_RESP : WWW_AUTH_RESP; + Header header = new Header(s, auth, true); + method.addRequestHeader(header); + return true; + } else { + return false; + } + } + + + /** + * Attempt to provide default authentication credentials + * to the given method in the given context using basic + * authentication scheme. + * + * @param method the HttpMethod which requires authentication + * @param conn the connection to a specific host. This parameter + * may be null if default credentials (not specific + * to any particular host) are to be used + * @param state the HttpState object providing Credentials + * + * @return true if the Authenticate response header + * was added + * + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for basic scheme + * @throws AuthenticationException when a parsing or other error occurs + * + * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme + */ + public static boolean authenticateDefault( + HttpMethod method, + HttpConnection conn, + HttpState state) + throws AuthenticationException { + LOG.trace( + "enter HttpAuthenticator.authenticateDefault(HttpMethod, HttpConnection, HttpState)"); + return doAuthenticateDefault(method, conn, state, false); + } + + + /** + * Attempt to provide default proxy authentication credentials + * to the given method in the given context using basic + * authentication scheme. + * + * @param method the HttpMethod which requires authentication + * @param conn the connection to a specific host. This parameter + * may be null if default credentials (not specific + * to any particular host) are to be used + * @param state the HttpState object providing Credentials + * + * @return true if the Proxy-Authenticate response header + * was added + * + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for basic scheme + * @throws AuthenticationException when a parsing or other error occurs + + * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme + */ + public static boolean authenticateProxyDefault( + HttpMethod method, + HttpConnection conn, + HttpState state) + throws AuthenticationException { + LOG.trace("enter HttpAuthenticator.authenticateProxyDefault(HttpMethod, HttpState)"); + return doAuthenticateDefault(method, conn, state, true); + } + + + private static boolean doAuthenticate( + AuthScheme authscheme, + HttpMethod method, + HttpConnection conn, + HttpState state, + boolean proxy) + throws AuthenticationException { + if (authscheme == null) { + throw new IllegalArgumentException("Authentication scheme may not be null"); + } + if (method == null) { + throw new IllegalArgumentException("HTTP method may not be null"); + } + if (state == null) { + throw new IllegalArgumentException("HTTP state may not be null"); + } + String host = null; + if (conn != null) { + if (proxy) { + host = conn.getProxyHost(); + } else { + host = method.getParams().getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + } + } + String realm = authscheme.getRealm(); + if (LOG.isDebugEnabled()) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Using credentials for "); + if (realm == null) { + buffer.append("default"); + } else { + buffer.append('\''); + buffer.append(realm); + buffer.append('\''); + } + buffer.append(" authentication realm at "); + buffer.append(host); + LOG.debug(buffer.toString()); + } + Credentials credentials = proxy + ? state.getProxyCredentials(realm, host) + : state.getCredentials(realm, host); + if (credentials == null) { + StringBuffer buffer = new StringBuffer(); + buffer.append("No credentials available for the "); + if (realm == null) { + buffer.append("default"); + } else { + buffer.append('\''); + buffer.append(realm); + buffer.append('\''); + } + buffer.append(" authentication realm at "); + buffer.append(host); + throw new CredentialsNotAvailableException(buffer.toString()); + } + String auth = authscheme.authenticate(credentials, method); + if (auth != null) { + String s = proxy ? PROXY_AUTH_RESP : WWW_AUTH_RESP; + Header header = new Header(s, auth, true); + method.addRequestHeader(header); + return true; + } else { + return false; + } + } + + /** + * Attempt to provide requisite authentication credentials to the + * given method in the given context using the given + * authentication scheme. + * + * @param authscheme The authentication scheme to be used + * @param method The HttpMethod which requires authentication + * @param conn the connection to a specific host. This parameter + * may be null if default credentials (not specific + * to any particular host) are to be used + * @param state The HttpState object providing Credentials + * + * @return true if the Authenticate response header was added + * + * @throws CredentialsNotAvailableException if authentication credentials + * required to respond to the authentication challenge are not available + * @throws AuthenticationException when a parsing or other error occurs + + * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme + */ + public static boolean authenticate( + AuthScheme authscheme, + HttpMethod method, + HttpConnection conn, + HttpState state) + throws AuthenticationException { + LOG.trace( + "enter HttpAuthenticator.authenticate(AuthScheme, HttpMethod, HttpConnection, " + + "HttpState)"); + return doAuthenticate(authscheme, method, conn, state, false); + } + + + /** + * Attempt to provide requisite proxy authentication credentials + * to the given method in the given context using + * the given authentication scheme. + * + * @param authscheme The authentication scheme to be used + * @param method the HttpMethod which requires authentication + * @param conn the connection to a specific host. This parameter + * may be null if default credentials (not specific + * to any particular host) are to be used + * @param state the HttpState object providing Credentials + * + * @return true if the Proxy-Authenticate response header + * was added + * + * @throws CredentialsNotAvailableException if authentication credentials + * required to respond to the authentication challenge are not available + * @throws AuthenticationException when a parsing or other error occurs + + * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme + */ + public static boolean authenticateProxy( + AuthScheme authscheme, + HttpMethod method, + HttpConnection conn, + HttpState state + ) throws AuthenticationException { + LOG.trace("enter HttpAuthenticator.authenticateProxy(AuthScheme, HttpMethod, HttpState)"); + return doAuthenticate(authscheme, method, conn, state, true); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/InvalidCredentialsException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/InvalidCredentialsException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/InvalidCredentialsException.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,67 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/InvalidCredentialsException.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +/** + * Authentication credentials required to respond to a authentication + * challenge are invalid + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class InvalidCredentialsException extends AuthenticationException { + /** + * Creates a new InvalidCredentialsException with a null detail message. + */ + public InvalidCredentialsException() { + super(); + } + + /** + * Creates a new InvalidCredentialsException with the specified message. + * + * @param message the exception detail message + */ + public InvalidCredentialsException(String message) { + super(message); + } + + /** + * Creates a new InvalidCredentialsException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + */ + public InvalidCredentialsException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/MalformedChallengeException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/MalformedChallengeException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/MalformedChallengeException.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,72 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/MalformedChallengeException.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.httpclient.ProtocolException; + +/** + * Signals that authentication challenge is in some way invalid or + * illegal in the given context + * + * @author Oleg Kalnichevski + * + * @since 2.0 + */ +public class MalformedChallengeException extends ProtocolException { + + /** + * Creates a new MalformedChallengeException with a null detail message. + */ + public MalformedChallengeException() { + super(); + } + + /** + * Creates a new MalformedChallengeException with the specified message. + * + * @param message the exception detail message + */ + public MalformedChallengeException(String message) { + super(message); + } + + /** + * Creates a new MalformedChallengeException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + * + * @since 3.0 + */ + public MalformedChallengeException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLM.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLM.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLM.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,564 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLM.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.httpclient.util.EncodingUtil; + +/** + * Provides an implementation of the NTLM authentication protocol. + *

+ * This class provides methods for generating authentication + * challenge responses for the NTLM authentication protocol. The NTLM + * protocol is a proprietary Microsoft protocol and as such no RFC + * exists for it. This class is based upon the reverse engineering + * efforts of a wide range of people.

+ * + *

Please note that an implementation of JCE must be correctly installed and configured when + * using NTLM support.

+ * + *

This class should not be used externally to HttpClient as it's API is specifically + * designed to work with HttpClient's use case, in particular it's connection management.

+ * + * @author Adrian Sutton + * @author Jeff Dever + * @author Mike Bowler + * + * @version $Revision: 1.1 $ $Date: 2012/08/22 17:30:36 $ + * @since 3.0 + */ +final class NTLM { + + /** Character encoding */ + public static final String DEFAULT_CHARSET = "ASCII"; + + /** The current response */ + private byte[] currentResponse; + + /** The current position */ + private int currentPosition = 0; + + /** The character set to use for encoding the credentials */ + private String credentialCharset = DEFAULT_CHARSET; + + /** + * Returns the response for the given message. + * + * @param message the message that was received from the server. + * @param username the username to authenticate with. + * @param password the password to authenticate with. + * @param host The host. + * @param domain the NT domain to authenticate in. + * @return The response. + * @throws HttpException If the messages cannot be retrieved. + */ + public final String getResponseFor(String message, + String username, String password, String host, String domain) + throws AuthenticationException { + + final String response; + if (message == null || message.trim().equals("")) { + response = getType1Message(host, domain); + } else { + response = getType3Message(username, password, host, domain, + parseType2Message(message)); + } + return response; + } + + /** + * Return the cipher for the specified key. + * @param key The key. + * @return Cipher The cipher. + * @throws AuthenticationException If the cipher cannot be retrieved. + */ + private Cipher getCipher(byte[] key) throws AuthenticationException { + try { + final Cipher ecipher = Cipher.getInstance("DES/ECB/NoPadding"); + key = setupKey(key); + ecipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "DES")); + return ecipher; + } catch (NoSuchAlgorithmException e) { + throw new AuthenticationException("DES encryption is not available.", e); + } catch (InvalidKeyException e) { + throw new AuthenticationException("Invalid key for DES encryption.", e); + } catch (NoSuchPaddingException e) { + throw new AuthenticationException( + "NoPadding option for DES is not available.", e); + } + } + + /** + * Adds parity bits to the key. + * @param key56 The key + * @return The modified key. + */ + private byte[] setupKey(byte[] key56) { + byte[] key = new byte[8]; + key[0] = (byte) ((key56[0] >> 1) & 0xff); + key[1] = (byte) ((((key56[0] & 0x01) << 6) + | (((key56[1] & 0xff) >> 2) & 0xff)) & 0xff); + key[2] = (byte) ((((key56[1] & 0x03) << 5) + | (((key56[2] & 0xff) >> 3) & 0xff)) & 0xff); + key[3] = (byte) ((((key56[2] & 0x07) << 4) + | (((key56[3] & 0xff) >> 4) & 0xff)) & 0xff); + key[4] = (byte) ((((key56[3] & 0x0f) << 3) + | (((key56[4] & 0xff) >> 5) & 0xff)) & 0xff); + key[5] = (byte) ((((key56[4] & 0x1f) << 2) + | (((key56[5] & 0xff) >> 6) & 0xff)) & 0xff); + key[6] = (byte) ((((key56[5] & 0x3f) << 1) + | (((key56[6] & 0xff) >> 7) & 0xff)) & 0xff); + key[7] = (byte) (key56[6] & 0x7f); + + for (int i = 0; i < key.length; i++) { + key[i] = (byte) (key[i] << 1); + } + return key; + } + + /** + * Encrypt the data. + * @param key The key. + * @param bytes The data + * @return byte[] The encrypted data + * @throws HttpException If {@link Cipher.doFinal(byte[])} fails + */ + private byte[] encrypt(byte[] key, byte[] bytes) + throws AuthenticationException { + Cipher ecipher = getCipher(key); + try { + byte[] enc = ecipher.doFinal(bytes); + return enc; + } catch (IllegalBlockSizeException e) { + throw new AuthenticationException("Invalid block size for DES encryption.", e); + } catch (BadPaddingException e) { + throw new AuthenticationException("Data not padded correctly for DES encryption.", e); + } + } + + /** + * Prepares the object to create a response of the given length. + * @param length the length of the response to prepare. + */ + private void prepareResponse(int length) { + currentResponse = new byte[length]; + currentPosition = 0; + } + + /** + * Adds the given byte to the response. + * @param b the byte to add. + */ + private void addByte(byte b) { + currentResponse[currentPosition] = b; + currentPosition++; + } + + /** + * Adds the given bytes to the response. + * @param bytes the bytes to add. + */ + private void addBytes(byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + currentResponse[currentPosition] = bytes[i]; + currentPosition++; + } + } + + /** + * Returns the response that has been generated after shrinking the array if + * required and base64 encodes the response. + * @return The response as above. + */ + private String getResponse() { + byte[] resp; + if (currentResponse.length > currentPosition) { + byte[] tmp = new byte[currentPosition]; + for (int i = 0; i < currentPosition; i++) { + tmp[i] = currentResponse[i]; + } + resp = tmp; + } else { + resp = currentResponse; + } + return EncodingUtil.getAsciiString(Base64.encodeBase64(resp)); + } + + /** + * Creates the first message (type 1 message) in the NTLM authentication sequence. + * This message includes the user name, domain and host for the authentication session. + * + * @param host the computer name of the host requesting authentication. + * @param domain The domain to authenticate with. + * @return String the message to add to the HTTP request header. + */ + public String getType1Message(String host, String domain) { + host = host.toUpperCase(); + domain = domain.toUpperCase(); + byte[] hostBytes = EncodingUtil.getBytes(host, DEFAULT_CHARSET); + byte[] domainBytes = EncodingUtil.getBytes(domain, DEFAULT_CHARSET); + + int finalLength = 32 + hostBytes.length + domainBytes.length; + prepareResponse(finalLength); + + // The initial id string. + byte[] protocol = EncodingUtil.getBytes("NTLMSSP", DEFAULT_CHARSET); + addBytes(protocol); + addByte((byte) 0); + + // Type + addByte((byte) 1); + addByte((byte) 0); + addByte((byte) 0); + addByte((byte) 0); + + // Flags + addByte((byte) 6); + addByte((byte) 82); + addByte((byte) 0); + addByte((byte) 0); + + // Domain length (first time). + int iDomLen = domainBytes.length; + byte[] domLen = convertShort(iDomLen); + addByte(domLen[0]); + addByte(domLen[1]); + + // Domain length (second time). + addByte(domLen[0]); + addByte(domLen[1]); + + // Domain offset. + byte[] domOff = convertShort(hostBytes.length + 32); + addByte(domOff[0]); + addByte(domOff[1]); + addByte((byte) 0); + addByte((byte) 0); + + // Host length (first time). + byte[] hostLen = convertShort(hostBytes.length); + addByte(hostLen[0]); + addByte(hostLen[1]); + + // Host length (second time). + addByte(hostLen[0]); + addByte(hostLen[1]); + + // Host offset (always 32). + byte[] hostOff = convertShort(32); + addByte(hostOff[0]); + addByte(hostOff[1]); + addByte((byte) 0); + addByte((byte) 0); + + // Host String. + addBytes(hostBytes); + + // Domain String. + addBytes(domainBytes); + + return getResponse(); + } + + /** + * Extracts the server nonce out of the given message type 2. + * + * @param message the String containing the base64 encoded message. + * @return an array of 8 bytes that the server sent to be used when + * hashing the password. + */ + public byte[] parseType2Message(String message) { + // Decode the message first. + byte[] msg = Base64.decodeBase64(EncodingUtil.getBytes(message, DEFAULT_CHARSET)); + byte[] nonce = new byte[8]; + // The nonce is the 8 bytes starting from the byte in position 24. + for (int i = 0; i < 8; i++) { + nonce[i] = msg[i + 24]; + } + return nonce; + } + + /** + * Creates the type 3 message using the given server nonce. The type 3 message includes all the + * information for authentication, host, domain, username and the result of encrypting the + * nonce sent by the server using the user's password as the key. + * + * @param user The user name. This should not include the domain name. + * @param password The password. + * @param host The host that is originating the authentication request. + * @param domain The domain to authenticate within. + * @param nonce the 8 byte array the server sent. + * @return The type 3 message. + * @throws AuthenticationException If {@encrypt(byte[],byte[])} fails. + */ + public String getType3Message(String user, String password, + String host, String domain, byte[] nonce) + throws AuthenticationException { + + int ntRespLen = 0; + int lmRespLen = 24; + domain = domain.toUpperCase(); + host = host.toUpperCase(); + user = user.toUpperCase(); + byte[] domainBytes = EncodingUtil.getBytes(domain, DEFAULT_CHARSET); + byte[] hostBytes = EncodingUtil.getBytes(host, DEFAULT_CHARSET); + byte[] userBytes = EncodingUtil.getBytes(user, credentialCharset); + int domainLen = domainBytes.length; + int hostLen = hostBytes.length; + int userLen = userBytes.length; + int finalLength = 64 + ntRespLen + lmRespLen + domainLen + + userLen + hostLen; + prepareResponse(finalLength); + byte[] ntlmssp = EncodingUtil.getBytes("NTLMSSP", DEFAULT_CHARSET); + addBytes(ntlmssp); + addByte((byte) 0); + addByte((byte) 3); + addByte((byte) 0); + addByte((byte) 0); + addByte((byte) 0); + + // LM Resp Length (twice) + addBytes(convertShort(24)); + addBytes(convertShort(24)); + + // LM Resp Offset + addBytes(convertShort(finalLength - 24)); + addByte((byte) 0); + addByte((byte) 0); + + // NT Resp Length (twice) + addBytes(convertShort(0)); + addBytes(convertShort(0)); + + // NT Resp Offset + addBytes(convertShort(finalLength)); + addByte((byte) 0); + addByte((byte) 0); + + // Domain length (twice) + addBytes(convertShort(domainLen)); + addBytes(convertShort(domainLen)); + + // Domain offset. + addBytes(convertShort(64)); + addByte((byte) 0); + addByte((byte) 0); + + // User Length (twice) + addBytes(convertShort(userLen)); + addBytes(convertShort(userLen)); + + // User offset + addBytes(convertShort(64 + domainLen)); + addByte((byte) 0); + addByte((byte) 0); + + // Host length (twice) + addBytes(convertShort(hostLen)); + addBytes(convertShort(hostLen)); + + // Host offset + addBytes(convertShort(64 + domainLen + userLen)); + + for (int i = 0; i < 6; i++) { + addByte((byte) 0); + } + + // Message length + addBytes(convertShort(finalLength)); + addByte((byte) 0); + addByte((byte) 0); + + // Flags + addByte((byte) 6); + addByte((byte) 82); + addByte((byte) 0); + addByte((byte) 0); + + addBytes(domainBytes); + addBytes(userBytes); + addBytes(hostBytes); + addBytes(hashPassword(password, nonce)); + return getResponse(); + } + + /** + * Creates the LANManager and NT response for the given password using the + * given nonce. + * @param password the password to create a hash for. + * @param nonce the nonce sent by the server. + * @return The response. + * @throws HttpException If {@link #encrypt(byte[],byte[])} fails. + */ + private byte[] hashPassword(String password, byte[] nonce) + throws AuthenticationException { + byte[] passw = EncodingUtil.getBytes(password.toUpperCase(), credentialCharset); + byte[] lmPw1 = new byte[7]; + byte[] lmPw2 = new byte[7]; + + int len = passw.length; + if (len > 7) { + len = 7; + } + + int idx; + for (idx = 0; idx < len; idx++) { + lmPw1[idx] = passw[idx]; + } + for (; idx < 7; idx++) { + lmPw1[idx] = (byte) 0; + } + + len = passw.length; + if (len > 14) { + len = 14; + } + for (idx = 7; idx < len; idx++) { + lmPw2[idx - 7] = passw[idx]; + } + for (; idx < 14; idx++) { + lmPw2[idx - 7] = (byte) 0; + } + + // Create LanManager hashed Password + byte[] magic = { + (byte) 0x4B, (byte) 0x47, (byte) 0x53, (byte) 0x21, + (byte) 0x40, (byte) 0x23, (byte) 0x24, (byte) 0x25 + }; + + byte[] lmHpw1; + lmHpw1 = encrypt(lmPw1, magic); + + byte[] lmHpw2 = encrypt(lmPw2, magic); + + byte[] lmHpw = new byte[21]; + for (int i = 0; i < lmHpw1.length; i++) { + lmHpw[i] = lmHpw1[i]; + } + for (int i = 0; i < lmHpw2.length; i++) { + lmHpw[i + 8] = lmHpw2[i]; + } + for (int i = 0; i < 5; i++) { + lmHpw[i + 16] = (byte) 0; + } + + // Create the responses. + byte[] lmResp = new byte[24]; + calcResp(lmHpw, nonce, lmResp); + + return lmResp; + } + + /** + * Takes a 21 byte array and treats it as 3 56-bit DES keys. The 8 byte + * plaintext is encrypted with each key and the resulting 24 bytes are + * stored in the results array. + * + * @param keys The keys. + * @param plaintext The plain text to encrypt. + * @param results Where the results are stored. + * @throws AuthenticationException If {@link #encrypt(byte[],byte[])} fails. + */ + private void calcResp(byte[] keys, byte[] plaintext, byte[] results) + throws AuthenticationException { + byte[] keys1 = new byte[7]; + byte[] keys2 = new byte[7]; + byte[] keys3 = new byte[7]; + for (int i = 0; i < 7; i++) { + keys1[i] = keys[i]; + } + + for (int i = 0; i < 7; i++) { + keys2[i] = keys[i + 7]; + } + + for (int i = 0; i < 7; i++) { + keys3[i] = keys[i + 14]; + } + byte[] results1 = encrypt(keys1, plaintext); + + byte[] results2 = encrypt(keys2, plaintext); + + byte[] results3 = encrypt(keys3, plaintext); + + for (int i = 0; i < 8; i++) { + results[i] = results1[i]; + } + for (int i = 0; i < 8; i++) { + results[i + 8] = results2[i]; + } + for (int i = 0; i < 8; i++) { + results[i + 16] = results3[i]; + } + } + + /** + * Converts a given number to a two byte array in little endian order. + * @param num the number to convert. + * @return The byte representation of num in little endian order. + */ + private byte[] convertShort(int num) { + byte[] val = new byte[2]; + String hex = Integer.toString(num, 16); + while (hex.length() < 4) { + hex = "0" + hex; + } + String low = hex.substring(2, 4); + String high = hex.substring(0, 2); + + val[0] = (byte) Integer.parseInt(low, 16); + val[1] = (byte) Integer.parseInt(high, 16); + return val; + } + + /** + * @return Returns the credentialCharset. + */ + public String getCredentialCharset() { + return credentialCharset; + } + + /** + * @param credentialCharset The credentialCharset to set. + */ + public void setCredentialCharset(String credentialCharset) { + this.credentialCharset = credentialCharset; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLMScheme.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLMScheme.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLMScheme.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,354 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/NTLMScheme.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.NTCredentials; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** An implementation of the Microsoft proprietary NTLM authentication scheme. For a detailed + * explanation of the NTLM scheme please see + * http://davenport.sourceforge.net/ntlm.html. + * + * @author Remy Maucherat + * @author Rodney Waldhoff + * @author Jeff Dever + * @author Ortwin Gl???ck + * @author Sean C. Sullivan + * @author Adrian Sutton + * @author Mike Bowler + * @author Oleg Kalnichevski + */ +public class NTLMScheme implements AuthScheme { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(NTLMScheme.class); + + /** NTLM challenge string. */ + private String ntlmchallenge = null; + + private static final int UNINITIATED = 0; + private static final int INITIATED = 1; + private static final int TYPE1_MSG_GENERATED = 2; + private static final int TYPE2_MSG_RECEIVED = 3; + private static final int TYPE3_MSG_GENERATED = 4; + private static final int FAILED = Integer.MAX_VALUE; + + /** Authentication process state */ + private int state; + + /** + * Default constructor for the NTLM authentication scheme. + * + * @since 3.0 + */ + public NTLMScheme() { + super(); + this.state = UNINITIATED; + } + + /** + * Constructor for the NTLM authentication scheme. + * + * @param challenge The authentication challenge + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + */ + public NTLMScheme(final String challenge) throws MalformedChallengeException { + super(); + processChallenge(challenge); + } + + /** + * Processes the NTLM challenge. + * + * @param challenge the challenge string + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @since 3.0 + */ + public void processChallenge(final String challenge) throws MalformedChallengeException { + String s = AuthChallengeParser.extractScheme(challenge); + if (!s.equalsIgnoreCase(getSchemeName())) { + throw new MalformedChallengeException("Invalid NTLM challenge: " + challenge); + } + int i = challenge.indexOf(' '); + if (i != -1) { + s = challenge.substring(i, challenge.length()); + this.ntlmchallenge = s.trim(); + this.state = TYPE2_MSG_RECEIVED; + } else { + this.ntlmchallenge = ""; + if (this.state == UNINITIATED) { + this.state = INITIATED; + } else { + this.state = FAILED; + } + } + } + + /** + * Tests if the NTLM authentication process has been completed. + * + * @return true if Basic authorization has been processed, + * false otherwise. + * + * @since 3.0 + */ + public boolean isComplete() { + return this.state == TYPE3_MSG_GENERATED || this.state == FAILED; + } + + /** + * Returns textual designation of the NTLM authentication scheme. + * + * @return ntlm + */ + public String getSchemeName() { + return "ntlm"; + } + + /** + * The concept of an authentication realm is not supported by the NTLM + * authentication scheme. Always returns null. + * + * @return null + */ + public String getRealm() { + return null; + } + + /** + * Returns a String identifying the authentication challenge. This is + * used, in combination with the host and port to determine if + * authorization has already been attempted or not. Schemes which + * require multiple requests to complete the authentication should + * return a different value for each stage in the request. + * + *

Additionally, the ID should take into account any changes to the + * authentication challenge and return a different value when appropriate. + * For example when the realm changes in basic authentication it should be + * considered a different authentication attempt and a different value should + * be returned.

+ * + * @return String a String identifying the authentication challenge. The + * returned value may be null. + * + * @deprecated no longer used + */ + public String getID() { + return ntlmchallenge; + } + + /** + * Returns the authentication parameter with the given name, if available. + * + *

There are no valid parameters for NTLM authentication so this method always returns + * null.

+ * + * @param name The name of the parameter to be returned + * + * @return the parameter with the given name + */ + public String getParameter(String name) { + if (name == null) { + throw new IllegalArgumentException("Parameter name may not be null"); + } + return null; + } + + /** + * Returns true. NTLM authentication scheme is connection based. + * + * @return true. + * + * @since 3.0 + */ + public boolean isConnectionBased() { + return true; + } + + /** + * Create a NTLM authorization string for the given + * challenge and NT credentials. + * + * @param challenge The challenge. + * @param credentials {@link NTCredentials} + * + * @return a ntlm authorization string + * @throws AuthenticationException is thrown if authentication fails + * + * @deprecated Use non-static {@link #authenticate(Credentials, HttpMethod)} + */ + public static String authenticate( + final NTCredentials credentials, final String challenge) + throws AuthenticationException { + + LOG.trace("enter NTLMScheme.authenticate(NTCredentials, String)"); + + if (credentials == null) { + throw new IllegalArgumentException("Credentials may not be null"); + } + + NTLM ntlm = new NTLM(); + String s = ntlm.getResponseFor(challenge, + credentials.getUserName(), credentials.getPassword(), + credentials.getHost(), credentials.getDomain()); + return "NTLM " + s; + } + + /** + * Create a NTLM authorization string for the given + * challenge and NT credentials. + * + * @param challenge The challenge. + * @param credentials {@link NTCredentials} + * @param charset The charset to use for encoding the credentials + * + * @return a ntlm authorization string + * @throws AuthenticationException is thrown if authentication fails + * + * @deprecated Use non-static {@link #authenticate(Credentials, HttpMethod)} + * + * @since 3.0 + */ + public static String authenticate( + final NTCredentials credentials, + final String challenge, + String charset + ) throws AuthenticationException { + + LOG.trace("enter NTLMScheme.authenticate(NTCredentials, String)"); + + if (credentials == null) { + throw new IllegalArgumentException("Credentials may not be null"); + } + + NTLM ntlm = new NTLM(); + ntlm.setCredentialCharset(charset); + String s = ntlm.getResponseFor( + challenge, + credentials.getUserName(), + credentials.getPassword(), + credentials.getHost(), + credentials.getDomain()); + return "NTLM " + s; + } + + /** + * Produces NTLM authorization string for the given set of + * {@link Credentials}. + * + * @param credentials The set of credentials to be used for athentication + * @param method Method name is ignored by the NTLM authentication scheme + * @param uri URI is ignored by the NTLM authentication scheme + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for this authentication scheme + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return an NTLM authorization string + * + * @deprecated Use {@link #authenticate(Credentials, HttpMethod)} + */ + public String authenticate(Credentials credentials, String method, String uri) + throws AuthenticationException { + LOG.trace("enter NTLMScheme.authenticate(Credentials, String, String)"); + + NTCredentials ntcredentials = null; + try { + ntcredentials = (NTCredentials) credentials; + } catch (ClassCastException e) { + throw new InvalidCredentialsException( + "Credentials cannot be used for NTLM authentication: " + + credentials.getClass().getName()); + } + return NTLMScheme.authenticate(ntcredentials, this.ntlmchallenge); + } + + /** + * Produces NTLM authorization string for the given set of + * {@link Credentials}. + * + * @param credentials The set of credentials to be used for athentication + * @param method The method being authenticated + * + * @throws InvalidCredentialsException if authentication credentials + * are not valid or not applicable for this authentication scheme + * @throws AuthenticationException if authorization string cannot + * be generated due to an authentication failure + * + * @return an NTLM authorization string + * + * @since 3.0 + */ + public String authenticate( + Credentials credentials, + HttpMethod method + ) throws AuthenticationException { + LOG.trace("enter NTLMScheme.authenticate(Credentials, HttpMethod)"); + + if (this.state == UNINITIATED) { + throw new IllegalStateException("NTLM authentication process has not been initiated"); + } + + NTCredentials ntcredentials = null; + try { + ntcredentials = (NTCredentials) credentials; + } catch (ClassCastException e) { + throw new InvalidCredentialsException( + "Credentials cannot be used for NTLM authentication: " + + credentials.getClass().getName()); + } + NTLM ntlm = new NTLM(); + ntlm.setCredentialCharset(method.getParams().getCredentialCharset()); + String response = null; + if (this.state == INITIATED || this.state == FAILED) { + response = ntlm.getType1Message( + ntcredentials.getHost(), + ntcredentials.getDomain()); + this.state = TYPE1_MSG_GENERATED; + } else { + response = ntlm.getType3Message( + ntcredentials.getUserName(), + ntcredentials.getPassword(), + ntcredentials.getHost(), + ntcredentials.getDomain(), + ntlm.parseType2Message(this.ntlmchallenge)); + this.state = TYPE3_MSG_GENERATED; + } + return "NTLM " + response; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/RFC2617Scheme.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/RFC2617Scheme.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/RFC2617Scheme.java 22 Aug 2012 17:30:35 -0000 1.1 @@ -0,0 +1,154 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/RFC2617Scheme.java,v 1.1 2012/08/22 17:30:35 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:35 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.auth; + +import java.util.Map; + +/** + *

+ * Abstract authentication scheme class that lays foundation for all + * RFC 2617 compliant authetication schemes and provides capabilities common + * to all authentication schemes defined in RFC 2617. + *

+ * + * @author Oleg Kalnichevski +*/ +public abstract class RFC2617Scheme implements AuthScheme { + + /** + * Authentication parameter map. + */ + private Map params = null; + + /** + * Default constructor for RFC2617 compliant authetication schemes. + * + * @since 3.0 + */ + public RFC2617Scheme() { + super(); + } + + /** + * Default constructor for RFC2617 compliant authetication schemes. + * + * @param challenge authentication challenge + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} + * method + */ + public RFC2617Scheme(final String challenge) throws MalformedChallengeException { + super(); + processChallenge(challenge); + } + + /** + * Processes the given challenge token. Some authentication schemes + * may involve multiple challenge-response exchanges. Such schemes must be able + * to maintain the state information when dealing with sequential challenges + * + * @param challenge the challenge string + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + * + * @since 3.0 + */ + public void processChallenge(final String challenge) throws MalformedChallengeException { + String s = AuthChallengeParser.extractScheme(challenge); + if (!s.equalsIgnoreCase(getSchemeName())) { + throw new MalformedChallengeException( + "Invalid " + getSchemeName() + " challenge: " + challenge); + } + this.params = AuthChallengeParser.extractParams(challenge); + } + + /** + * Returns authentication parameters map. Keys in the map are lower-cased. + * + * @return the map of authentication parameters + */ + protected Map getParameters() { + return this.params; + } + + /** + * Returns authentication parameter with the given name, if available. + * + * @param name The name of the parameter to be returned + * + * @return the parameter with the given name + */ + public String getParameter(String name) { + if (name == null) { + throw new IllegalArgumentException("Parameter name may not be null"); + } + if (this.params == null) { + return null; + } + return (String) this.params.get(name.toLowerCase()); + } + + /** + * Returns authentication realm. The realm may not be null. + * + * @return the authentication realm + */ + public String getRealm() { + return getParameter("realm"); + } + + /** + * Returns a String identifying the authentication challenge. This is + * used, in combination with the host and port to determine if + * authorization has already been attempted or not. Schemes which + * require multiple requests to complete the authentication should + * return a different value for each stage in the request. + * + *

Additionally, the ID should take into account any changes to the + * authentication challenge and return a different value when appropriate. + * For example when the realm changes in basic authentication it should be + * considered a different authentication attempt and a different value should + * be returned.

+ * + *

This method simply returns the realm for the challenge.

+ * + * @return String a String identifying the authentication challenge. The + * returned value may be null. + * + * @deprecated no longer used + */ + public String getID() { + return getRealm(); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/auth/package.html 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,11 @@ + + + Package Documentation for org.apache.commons.httpclient.auth + + + Provides implementation of various authentication schemes as well as + utility classes that can be used to authenticate HTTP requests. + + @since 2.0 + + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookiePolicy.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookiePolicy.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookiePolicy.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,305 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookiePolicy.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.cookie; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Cookie management policy class. The cookie policy provides corresponding + * cookie management interfrace for a given type or version of cookie. + *

RFC 2109 specification is used per default. Other supported specification + * can be chosen when appropriate or set default when desired + *

The following specifications are provided: + *

    + *
  • BROWSER_COMPATIBILITY: compatible with the common cookie + * management practices (even if they are not 100% standards compliant) + *
  • NETSCAPE: Netscape cookie draft compliant + *
  • RFC_2109: RFC2109 compliant (default) + *
  • IGNORE_COOKIES: do not automcatically process cookies + *
+ * + * @author Oleg Kalnichevski + * @author Mike Bowler + * + * @since 2.0 + */ +public abstract class CookiePolicy { + + private static Map SPECS = Collections.synchronizedMap(new HashMap()); + + /** + * The policy that provides high degree of compatibilty + * with common cookie management of popular HTTP agents. + * + * @since 3.0 + */ + public static final String BROWSER_COMPATIBILITY = "compatibility"; + + /** + * The Netscape cookie draft compliant policy. + * + * @since 3.0 + */ + public static final String NETSCAPE = "netscape"; + + /** + * The RFC 2109 compliant policy. + * + * @since 3.0 + */ + public static final String RFC_2109 = "rfc2109"; + + /** + * The policy that ignores cookies. + * + * @since 3.0 + */ + public static final String IGNORE_COOKIES = "ignoreCookies"; + + /** + * The default cookie policy. + * + * @since 3.0 + */ + public static final String DEFAULT = "default"; + + static { + CookiePolicy.registerCookieSpec(DEFAULT, RFC2109Spec.class); + CookiePolicy.registerCookieSpec(RFC_2109, RFC2109Spec.class); + CookiePolicy.registerCookieSpec(BROWSER_COMPATIBILITY, CookieSpecBase.class); + CookiePolicy.registerCookieSpec(NETSCAPE, NetscapeDraftSpec.class); + CookiePolicy.registerCookieSpec(IGNORE_COOKIES, IgnoreCookiesSpec.class); + } + + /** + * The COMPATIBILITY policy provides high compatibilty + * with common cookie management of popular HTTP agents. + * + * @deprecated Use {@link #BROWSER_COMPATIBILITY} + */ + public static final int COMPATIBILITY = 0; + + /** + * The NETSCAPE_DRAFT Netscape draft compliant policy. + * + * @deprecated Use {@link #NETSCAPE} + */ + public static final int NETSCAPE_DRAFT = 1; + + /** + * The RFC2109 RFC 2109 compliant policy. + * + * @deprecated Use {@link #RFC_2109} + */ + public static final int RFC2109 = 2; + + /** + * The default cookie policy. + * + * @deprecated Use {@link #DEFAULT} + */ + private static int defaultPolicy = RFC2109; + + /** Log object. */ + protected static final Log LOG = LogFactory.getLog(CookiePolicy.class); + + /** + * Registers a new {@link CookieSpec cookie specification} with the given identifier. + * If a specification with the given ID already exists it will be overridden. + * This ID is the same one used to retrieve the {@link CookieSpec cookie specification} + * from {@link #getCookieSpec(String)}. + * + * @param id the identifier for this specification + * @param clazz the {@link CookieSpec cookie specification} class to register + * + * @see #getCookieSpec(String) + * + * @since 3.0 + */ + public static void registerCookieSpec(final String id, final Class clazz) { + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + if (clazz == null) { + throw new IllegalArgumentException("Cookie spec class may not be null"); + } + SPECS.put(id.toLowerCase(), clazz); + } + + /** + * Unregisters the {@link CookieSpec cookie specification} with the given ID. + * + * @param id the ID of the {@link CookieSpec cookie specification} to unregister + * + * @since 3.0 + */ + public static void unregisterCookieSpec(final String id) { + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + SPECS.remove(id.toLowerCase()); + } + + /** + * Gets the {@link CookieSpec cookie specification} with the given ID. + * + * @param id the {@link CookieSpec cookie specification} ID + * + * @return {@link CookieSpec cookie specification} + * + * @throws IllegalStateException if a policy with the ID cannot be found + * + * @since 3.0 + */ + public static CookieSpec getCookieSpec(final String id) + throws IllegalStateException { + + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + Class clazz = (Class)SPECS.get(id.toLowerCase()); + + if (clazz != null) { + try { + return (CookieSpec)clazz.newInstance(); + } catch (Exception e) { + LOG.error("Error initializing cookie spec: " + id, e); + throw new IllegalStateException(id + + " cookie spec implemented by " + + clazz.getName() + " could not be initialized"); + } + } else { + throw new IllegalStateException("Unsupported cookie spec " + id); + } + } + + /** + * @return default cookie policy + * + * @deprecated Use {@link #getDefaultSpec()} + * + * @see #getDefaultSpec() + */ + public static int getDefaultPolicy() { + return defaultPolicy; + } + + + /** + * @param policy new default cookie policy + * + * @deprecated Use {@link CookiePolicy#registerCookieSpec(String, Class)} + * @see #DEFAULT + */ + public static void setDefaultPolicy(int policy) { + defaultPolicy = policy; + } + + /** + * @param policy cookie policy to get the CookieSpec for + * @return cookie specification interface for the given policy + * + * @deprecated Use {@link CookiePolicy#getCookieSpec(String)} + */ + public static CookieSpec getSpecByPolicy(int policy) { + switch(policy) { + case COMPATIBILITY: + return new CookieSpecBase(); + case NETSCAPE_DRAFT: + return new NetscapeDraftSpec(); + case RFC2109: + return new RFC2109Spec(); + default: + return getDefaultSpec(); + } + } + + + /** + * Returns {@link CookieSpec cookie specification} registered as {@link #DEFAULT}. + * If no default {@link CookieSpec cookie specification} has been registered, + * {@link RFC2109Spec RFC2109 specification} is returned. + * + * @return default {@link CookieSpec cookie specification} + * + * @see #DEFAULT + */ + public static CookieSpec getDefaultSpec() { + try { + return getCookieSpec(DEFAULT); + } catch (IllegalStateException e) { + LOG.warn("Default cookie policy is not registered"); + return new RFC2109Spec(); + } + } + + + /** + * Gets the CookieSpec for a particular cookie version. + * + *

Supported versions: + *

    + *
  • version 0 corresponds to the Netscape draft + *
  • version 1 corresponds to the RFC 2109 + *
  • Any other cookie value coresponds to the default spec + *
      + * + * @param ver the cookie version to get the spec for + * @return cookie specification interface intended for processing + * cookies with the given version + * + * @deprecated Use {@link CookiePolicy#getCookieSpec(String)} + */ + public static CookieSpec getSpecByVersion(int ver) { + switch(ver) { + case 0: + return new NetscapeDraftSpec(); + case 1: + return new RFC2109Spec(); + default: + return getDefaultSpec(); + } + } + + /** + * @return cookie specification interface that provides high compatibilty + * with common cookie management of popular HTTP agents + * + * @deprecated Use {@link CookiePolicy#getCookieSpec(String)} + */ + public static CookieSpec getCompatibilitySpec() { + return getSpecByPolicy(COMPATIBILITY); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpec.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpec.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpec.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,237 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpec.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.cookie; + +import java.util.Collection; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.Cookie; + +/** + * Defines the cookie management specification. + *

      Cookie management specification must define + *

        + *
      • rules of parsing "Set-Cookie" header + *
      • rules of validation of parsed cookies + *
      • formatting of "Cookie" header + *
      + * for a given host, port and path of origin + * + * @author Oleg Kalnichevski + * @author Jeff Dever + * + * @since 2.0 + */ +public interface CookieSpec { + + /** Path delimiter */ + static final String PATH_DELIM = "/"; + + /** Path delimiting charachter */ + static final char PATH_DELIM_CHAR = PATH_DELIM.charAt(0); + + /** + * Parse the "Set-Cookie" header value into Cookie array. + * + *

      This method will not perform the validation of the resultant + * {@link Cookie}s

      + * + * @see #validate(String, int, String, boolean, Cookie) + * + * @param host the host which sent the Set-Cookie header + * @param port the port which sent the Set-Cookie header + * @param path the path which sent the Set-Cookie header + * @param secure true when the Set-Cookie header + * was received over secure conection + * @param header the Set-Cookie received from the server + * @return an array of Cookies parsed from the Set-Cookie value + * @throws MalformedCookieException if an exception occurs during parsing + * @throws IllegalArgumentException if an input parameter is illegal + */ + Cookie[] parse(String host, int port, String path, boolean secure, + final String header) + throws MalformedCookieException, IllegalArgumentException; + + /** + * Parse the "Set-Cookie" Header into an array of Cookies. + * + *

      This method will not perform the validation of the resultant + * {@link Cookie}s

      + * + * @see #validate(String, int, String, boolean, Cookie) + * + * @param host the host which sent the Set-Cookie header + * @param port the port which sent the Set-Cookie header + * @param path the path which sent the Set-Cookie header + * @param secure true when the Set-Cookie header + * was received over secure conection + * @param header the Set-Cookie received from the server + * @return an array of Cookies parsed from the header + * @throws MalformedCookieException if an exception occurs during parsing + * @throws IllegalArgumentException if an input parameter is illegal + */ + Cookie[] parse(String host, int port, String path, boolean secure, + final Header header) + throws MalformedCookieException, IllegalArgumentException; + + /** + * Parse the cookie attribute and update the corresponsing Cookie + * properties. + * + * @param attribute cookie attribute from the Set-Cookie + * @param cookie the to be updated + * @throws MalformedCookieException if an exception occurs during parsing + * @throws IllegalArgumentException if an input parameter is illegal + */ + void parseAttribute(NameValuePair attribute, Cookie cookie) + throws MalformedCookieException, IllegalArgumentException; + + /** + * Validate the cookie according to validation rules defined by the + * cookie specification. + * + * @param host the host from which the {@link Cookie} was received + * @param port the port from which the {@link Cookie} was received + * @param path the path from which the {@link Cookie} was received + * @param secure true when the {@link Cookie} was received + * using a secure connection + * @param cookie the Cookie to validate + * @throws MalformedCookieException if the cookie is invalid + * @throws IllegalArgumentException if an input parameter is illegal + */ + void validate(String host, int port, String path, boolean secure, + final Cookie cookie) + throws MalformedCookieException, IllegalArgumentException; + + + /** + * Sets the {@link Collection} of date patterns used for parsing. The String patterns must be + * compatible with {@link java.text.SimpleDateFormat}. + * + * @param datepatterns collection of date patterns + */ + void setValidDateFormats(Collection datepatterns); + + /** + * Returns the {@link Collection} of date patterns used for parsing. The String patterns are compatible + * with the {@link java.text.SimpleDateFormat}. + * + * @return collection of date patterns + */ + Collection getValidDateFormats(); + + /** + * Determines if a Cookie matches a location. + * + * @param host the host to which the request is being submitted + * @param port the port to which the request is being submitted + * @param path the path to which the request is being submitted + * @param secure true if the request is using a secure connection + * @param cookie the Cookie to be matched + * + * @return true if the cookie should be submitted with a request + * with given attributes, false otherwise. + */ + boolean match(String host, int port, String path, boolean secure, + final Cookie cookie); + + /** + * Determines which of an array of Cookies matches a location. + * + * @param host the host to which the request is being submitted + * @param port the port to which the request is being submitted + * (currenlty ignored) + * @param path the path to which the request is being submitted + * @param secure true if the request is using a secure protocol + * @param cookies an array of Cookies to be matched + * + * @return true if the cookie should be submitted with a request + * with given attributes, false otherwise. + */ + Cookie[] match(String host, int port, String path, boolean secure, + final Cookie cookies[]); + + /** + * Performs domain-match as defined by the cookie specification. + * @param host The target host. + * @param domain The cookie domain attribute. + * @return true if the specified host matches the given domain. + * + * @since 3.0 + */ + boolean domainMatch(String host, String domain); + + /** + * Performs path-match as defined by the cookie specification. + * @param path The target path. + * @param topmostPath The cookie path attribute. + * @return true if the paths match + * + * @since 3.0 + */ + boolean pathMatch(String path, String topmostPath); + + /** + * Create a "Cookie" header value for an array of cookies. + * + * @param cookie the cookie to be formatted as string + * @return a string suitable for sending in a "Cookie" header. + */ + String formatCookie(Cookie cookie); + + /** + * Create a "Cookie" header value for an array of cookies. + * + * @param cookies the Cookies to be formatted + * @return a string suitable for sending in a Cookie header. + * @throws IllegalArgumentException if an input parameter is illegal + */ + String formatCookies(Cookie[] cookies) throws IllegalArgumentException; + + /** + * Create a "Cookie" Header for an array of Cookies. + * + * @param cookies the Cookies format into a Cookie header + * @return a Header for the given Cookies. + * @throws IllegalArgumentException if an input parameter is illegal + */ + Header formatCookieHeader(Cookie[] cookies) throws IllegalArgumentException; + + /** + * Create a "Cookie" Header for single Cookie. + * + * @param cookie the Cookie format as a Cookie header + * @return a Cookie header. + * @throws IllegalArgumentException if an input parameter is illegal + */ + Header formatCookieHeader(Cookie cookie) throws IllegalArgumentException; + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpecBase.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpecBase.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpecBase.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,658 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/CookieSpecBase.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.cookie; + +import java.util.Collection; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.httpclient.Cookie; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HeaderElement; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.util.DateParseException; +import org.apache.commons.httpclient.util.DateUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * Cookie management functions shared by all specification. + * + * @author B.C. Holmes + * @author Park, Sung-Gu + * @author Doug Sale + * @author Rod Waldhoff + * @author dIon Gillard + * @author Sean C. Sullivan + * @author John Evans + * @author Marc A. Saegesser + * @author Oleg Kalnichevski + * @author Mike Bowler + * + * @since 2.0 + */ +public class CookieSpecBase implements CookieSpec { + + /** Log object */ + protected static final Log LOG = LogFactory.getLog(CookieSpec.class); + + /** Valid date patterns */ + private Collection datepatterns = null; + + /** Default constructor */ + public CookieSpecBase() { + super(); + } + + + /** + * Parses the Set-Cookie value into an array of Cookies. + * + *

      The syntax for the Set-Cookie response header is: + * + *

      +      * set-cookie      =    "Set-Cookie:" cookies
      +      * cookies         =    1#cookie
      +      * cookie          =    NAME "=" VALUE * (";" cookie-av)
      +      * NAME            =    attr
      +      * VALUE           =    value
      +      * cookie-av       =    "Comment" "=" value
      +      *                 |    "Domain" "=" value
      +      *                 |    "Max-Age" "=" value
      +      *                 |    "Path" "=" value
      +      *                 |    "Secure"
      +      *                 |    "Version" "=" 1*DIGIT
      +      * 
      + * + * @param host the host from which the Set-Cookie value was + * received + * @param port the port from which the Set-Cookie value was + * received + * @param path the path from which the Set-Cookie value was + * received + * @param secure true when the Set-Cookie value was + * received over secure conection + * @param header the Set-Cookie received from the server + * @return an array of Cookies parsed from the Set-Cookie value + * @throws MalformedCookieException if an exception occurs during parsing + */ + public Cookie[] parse(String host, int port, String path, + boolean secure, final String header) + throws MalformedCookieException { + + LOG.trace("enter CookieSpecBase.parse(" + + "String, port, path, boolean, Header)"); + + if (host == null) { + throw new IllegalArgumentException( + "Host of origin may not be null"); + } + if (host.trim().equals("")) { + throw new IllegalArgumentException( + "Host of origin may not be blank"); + } + if (port < 0) { + throw new IllegalArgumentException("Invalid port: " + port); + } + if (path == null) { + throw new IllegalArgumentException( + "Path of origin may not be null."); + } + if (header == null) { + throw new IllegalArgumentException("Header may not be null."); + } + + if (path.trim().equals("")) { + path = PATH_DELIM; + } + host = host.toLowerCase(); + + String defaultPath = path; + int lastSlashIndex = defaultPath.lastIndexOf(PATH_DELIM); + if (lastSlashIndex >= 0) { + if (lastSlashIndex == 0) { + //Do not remove the very first slash + lastSlashIndex = 1; + } + defaultPath = defaultPath.substring(0, lastSlashIndex); + } + + HeaderElement[] headerElements = null; + + boolean isNetscapeCookie = false; + int i1 = header.toLowerCase().indexOf("expires="); + if (i1 != -1) { + i1 += "expires=".length(); + int i2 = header.indexOf(";", i1); + if (i2 == -1) { + i2 = header.length(); + } + try { + DateUtil.parseDate(header.substring(i1, i2), this.datepatterns); + isNetscapeCookie = true; + } catch (DateParseException e) { + // Does not look like a valid expiry date + } + } + if (isNetscapeCookie) { + headerElements = new HeaderElement[] { + new HeaderElement(header.toCharArray()) + }; + } else { + headerElements = HeaderElement.parseElements(header.toCharArray()); + } + + Cookie[] cookies = new Cookie[headerElements.length]; + + for (int i = 0; i < headerElements.length; i++) { + + HeaderElement headerelement = headerElements[i]; + Cookie cookie = null; + try { + cookie = new Cookie(host, + headerelement.getName(), + headerelement.getValue(), + defaultPath, + null, + false); + } catch (IllegalArgumentException e) { + throw new MalformedCookieException(e.getMessage()); + } + // cycle through the parameters + NameValuePair[] parameters = headerelement.getParameters(); + // could be null. In case only a header element and no parameters. + if (parameters != null) { + + for (int j = 0; j < parameters.length; j++) { + parseAttribute(parameters[j], cookie); + } + } + cookies[i] = cookie; + } + return cookies; + } + + + /** + * Parse the "Set-Cookie" {@link Header} into an array of {@link + * Cookie}s. + * + *

      The syntax for the Set-Cookie response header is: + * + *

      +      * set-cookie      =    "Set-Cookie:" cookies
      +      * cookies         =    1#cookie
      +      * cookie          =    NAME "=" VALUE * (";" cookie-av)
      +      * NAME            =    attr
      +      * VALUE           =    value
      +      * cookie-av       =    "Comment" "=" value
      +      *                 |    "Domain" "=" value
      +      *                 |    "Max-Age" "=" value
      +      *                 |    "Path" "=" value
      +      *                 |    "Secure"
      +      *                 |    "Version" "=" 1*DIGIT
      +      * 
      + * + * @param host the host from which the Set-Cookie header was + * received + * @param port the port from which the Set-Cookie header was + * received + * @param path the path from which the Set-Cookie header was + * received + * @param secure true when the Set-Cookie header was + * received over secure conection + * @param header the Set-Cookie received from the server + * @return an array of Cookies parsed from the "Set-Cookie" + * header + * @throws MalformedCookieException if an exception occurs during parsing + */ + public Cookie[] parse( + String host, int port, String path, boolean secure, final Header header) + throws MalformedCookieException { + + LOG.trace("enter CookieSpecBase.parse(" + + "String, port, path, boolean, String)"); + if (header == null) { + throw new IllegalArgumentException("Header may not be null."); + } + return parse(host, port, path, secure, header.getValue()); + } + + + /** + * Parse the cookie attribute and update the corresponsing {@link Cookie} + * properties. + * + * @param attribute {@link HeaderElement} cookie attribute from the + * Set- Cookie + * @param cookie {@link Cookie} to be updated + * @throws MalformedCookieException if an exception occurs during parsing + */ + + public void parseAttribute( + final NameValuePair attribute, final Cookie cookie) + throws MalformedCookieException { + + if (attribute == null) { + throw new IllegalArgumentException("Attribute may not be null."); + } + if (cookie == null) { + throw new IllegalArgumentException("Cookie may not be null."); + } + final String paramName = attribute.getName().toLowerCase(); + String paramValue = attribute.getValue(); + + if (paramName.equals("path")) { + + if ((paramValue == null) || (paramValue.trim().equals(""))) { + paramValue = "/"; + } + cookie.setPath(paramValue); + cookie.setPathAttributeSpecified(true); + + } else if (paramName.equals("domain")) { + + if (paramValue == null) { + throw new MalformedCookieException( + "Missing value for domain attribute"); + } + if (paramValue.trim().equals("")) { + throw new MalformedCookieException( + "Blank value for domain attribute"); + } + cookie.setDomain(paramValue); + cookie.setDomainAttributeSpecified(true); + + } else if (paramName.equals("max-age")) { + + if (paramValue == null) { + throw new MalformedCookieException( + "Missing value for max-age attribute"); + } + int age; + try { + age = Integer.parseInt(paramValue); + } catch (NumberFormatException e) { + throw new MalformedCookieException ("Invalid max-age " + + "attribute: " + e.getMessage()); + } + cookie.setExpiryDate( + new Date(System.currentTimeMillis() + age * 1000L)); + + } else if (paramName.equals("secure")) { + + cookie.setSecure(true); + + } else if (paramName.equals("comment")) { + + cookie.setComment(paramValue); + + } else if (paramName.equals("expires")) { + + if (paramValue == null) { + throw new MalformedCookieException( + "Missing value for expires attribute"); + } + + try { + cookie.setExpiryDate(DateUtil.parseDate(paramValue, this.datepatterns)); + } catch (DateParseException dpe) { + LOG.debug("Error parsing cookie date", dpe); + throw new MalformedCookieException( + "Unable to parse expiration date parameter: " + + paramValue); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Unrecognized cookie attribute: " + + attribute.toString()); + } + } + } + + + public Collection getValidDateFormats() { + return this.datepatterns; + } + + public void setValidDateFormats(final Collection datepatterns) { + this.datepatterns = datepatterns; + } + + /** + * Performs most common {@link Cookie} validation + * + * @param host the host from which the {@link Cookie} was received + * @param port the port from which the {@link Cookie} was received + * @param path the path from which the {@link Cookie} was received + * @param secure true when the {@link Cookie} was received using a + * secure connection + * @param cookie The cookie to validate. + * @throws MalformedCookieException if an exception occurs during + * validation + */ + + public void validate(String host, int port, String path, + boolean secure, final Cookie cookie) + throws MalformedCookieException { + + LOG.trace("enter CookieSpecBase.validate(" + + "String, port, path, boolean, Cookie)"); + if (host == null) { + throw new IllegalArgumentException( + "Host of origin may not be null"); + } + if (host.trim().equals("")) { + throw new IllegalArgumentException( + "Host of origin may not be blank"); + } + if (port < 0) { + throw new IllegalArgumentException("Invalid port: " + port); + } + if (path == null) { + throw new IllegalArgumentException( + "Path of origin may not be null."); + } + if (path.trim().equals("")) { + path = PATH_DELIM; + } + host = host.toLowerCase(); + // check version + if (cookie.getVersion() < 0) { + throw new MalformedCookieException ("Illegal version number " + + cookie.getValue()); + } + + // security check... we musn't allow the server to give us an + // invalid domain scope + + // Validate the cookies domain attribute. NOTE: Domains without + // any dots are allowed to support hosts on private LANs that don't + // have DNS names. Since they have no dots, to domain-match the + // request-host and domain must be identical for the cookie to sent + // back to the origin-server. + if (host.indexOf(".") >= 0) { + // Not required to have at least two dots. RFC 2965. + // A Set-Cookie2 with Domain=ajax.com will be accepted. + + // domain must match host + if (!host.endsWith(cookie.getDomain())) { + String s = cookie.getDomain(); + if (s.startsWith(".")) { + s = s.substring(1, s.length()); + } + if (!host.equals(s)) { + throw new MalformedCookieException( + "Illegal domain attribute \"" + cookie.getDomain() + + "\". Domain of origin: \"" + host + "\""); + } + } + } else { + if (!host.equals(cookie.getDomain())) { + throw new MalformedCookieException( + "Illegal domain attribute \"" + cookie.getDomain() + + "\". Domain of origin: \"" + host + "\""); + } + } + + // another security check... we musn't allow the server to give us a + // cookie that doesn't match this path + + if (!path.startsWith(cookie.getPath())) { + throw new MalformedCookieException( + "Illegal path attribute \"" + cookie.getPath() + + "\". Path of origin: \"" + path + "\""); + } + } + + + /** + * Return true if the cookie should be submitted with a request + * with given attributes, false otherwise. + * @param host the host to which the request is being submitted + * @param port the port to which the request is being submitted (ignored) + * @param path the path to which the request is being submitted + * @param secure true if the request is using a secure connection + * @param cookie {@link Cookie} to be matched + * @return true if the cookie matches the criterium + */ + + public boolean match(String host, int port, String path, + boolean secure, final Cookie cookie) { + + LOG.trace("enter CookieSpecBase.match(" + + "String, int, String, boolean, Cookie"); + + if (host == null) { + throw new IllegalArgumentException( + "Host of origin may not be null"); + } + if (host.trim().equals("")) { + throw new IllegalArgumentException( + "Host of origin may not be blank"); + } + if (port < 0) { + throw new IllegalArgumentException("Invalid port: " + port); + } + if (path == null) { + throw new IllegalArgumentException( + "Path of origin may not be null."); + } + if (cookie == null) { + throw new IllegalArgumentException("Cookie may not be null"); + } + if (path.trim().equals("")) { + path = PATH_DELIM; + } + host = host.toLowerCase(); + if (cookie.getDomain() == null) { + LOG.warn("Invalid cookie state: domain not specified"); + return false; + } + if (cookie.getPath() == null) { + LOG.warn("Invalid cookie state: path not specified"); + return false; + } + + return + // only add the cookie if it hasn't yet expired + (cookie.getExpiryDate() == null + || cookie.getExpiryDate().after(new Date())) + // and the domain pattern matches + && (domainMatch(host, cookie.getDomain())) + // and the path is null or matching + && (pathMatch(path, cookie.getPath())) + // and if the secure flag is set, only if the request is + // actually secure + && (cookie.getSecure() ? secure : true); + } + + /** + * Performs domain-match as implemented in common browsers. + * @param host The target host. + * @param domain The cookie domain attribute. + * @return true if the specified host matches the given domain. + */ + public boolean domainMatch(final String host, String domain) { + if (host.equals(domain)) { + return true; + } + if (!domain.startsWith(".")) { + domain = "." + domain; + } + return host.endsWith(domain) || host.equals(domain.substring(1)); + } + + /** + * Performs path-match as implemented in common browsers. + * @param path The target path. + * @param topmostPath The cookie path attribute. + * @return true if the paths match + */ + public boolean pathMatch(final String path, final String topmostPath) { + boolean match = path.startsWith (topmostPath); + // if there is a match and these values are not exactly the same we have + // to make sure we're not matcing "/foobar" and "/foo" + if (match && path.length() != topmostPath.length()) { + if (!topmostPath.endsWith(PATH_DELIM)) { + match = (path.charAt(topmostPath.length()) == PATH_DELIM_CHAR); + } + } + return match; + } + + /** + * Return an array of {@link Cookie}s that should be submitted with a + * request with given attributes, false otherwise. + * @param host the host to which the request is being submitted + * @param port the port to which the request is being submitted (currently + * ignored) + * @param path the path to which the request is being submitted + * @param secure true if the request is using a secure protocol + * @param cookies an array of Cookies to be matched + * @return an array of Cookies matching the criterium + */ + + public Cookie[] match(String host, int port, String path, + boolean secure, final Cookie cookies[]) { + + LOG.trace("enter CookieSpecBase.match(" + + "String, int, String, boolean, Cookie[])"); + + if (cookies == null) { + return null; + } + List matching = new LinkedList(); + for (int i = 0; i < cookies.length; i++) { + if (match(host, port, path, secure, cookies[i])) { + addInPathOrder(matching, cookies[i]); + } + } + return (Cookie[]) matching.toArray(new Cookie[matching.size()]); + } + + + /** + * Adds the given cookie into the given list in descending path order. That + * is, more specific path to least specific paths. This may not be the + * fastest algorythm, but it'll work OK for the small number of cookies + * we're generally dealing with. + * + * @param list - the list to add the cookie to + * @param addCookie - the Cookie to add to list + */ + private static void addInPathOrder(List list, Cookie addCookie) { + int i = 0; + + for (i = 0; i < list.size(); i++) { + Cookie c = (Cookie) list.get(i); + if (addCookie.compare(addCookie, c) > 0) { + break; + } + } + list.add(i, addCookie); + } + + /** + * Return a string suitable for sending in a "Cookie" header + * @param cookie a {@link Cookie} to be formatted as string + * @return a string suitable for sending in a "Cookie" header. + */ + public String formatCookie(Cookie cookie) { + LOG.trace("enter CookieSpecBase.formatCookie(Cookie)"); + if (cookie == null) { + throw new IllegalArgumentException("Cookie may not be null"); + } + StringBuffer buf = new StringBuffer(); + buf.append(cookie.getName()); + buf.append("="); + String s = cookie.getValue(); + if (s != null) { + buf.append(s); + } + return buf.toString(); + } + + /** + * Create a "Cookie" header value containing all {@link Cookie}s in + * cookies suitable for sending in a "Cookie" header + * @param cookies an array of {@link Cookie}s to be formatted + * @return a string suitable for sending in a Cookie header. + * @throws IllegalArgumentException if an input parameter is illegal + */ + + public String formatCookies(Cookie[] cookies) + throws IllegalArgumentException { + LOG.trace("enter CookieSpecBase.formatCookies(Cookie[])"); + if (cookies == null) { + throw new IllegalArgumentException("Cookie array may not be null"); + } + if (cookies.length == 0) { + throw new IllegalArgumentException("Cookie array may not be empty"); + } + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < cookies.length; i++) { + if (i > 0) { + buffer.append("; "); + } + buffer.append(formatCookie(cookies[i])); + } + return buffer.toString(); + } + + + /** + * Create a "Cookie" {@link Header} containing all {@link Cookie}s + * in cookies. + * @param cookies an array of {@link Cookie}s to be formatted as a " + * Cookie" header + * @return a "Cookie" {@link Header}. + */ + public Header formatCookieHeader(Cookie[] cookies) { + LOG.trace("enter CookieSpecBase.formatCookieHeader(Cookie[])"); + return new Header("Cookie", formatCookies(cookies)); + } + + + /** + * Create a "Cookie" {@link Header} containing the {@link Cookie}. + * @param cookie Cookies to be formatted as a Cookie + * header + * @return a Cookie header. + */ + public Header formatCookieHeader(Cookie cookie) { + LOG.trace("enter CookieSpecBase.formatCookieHeader(Cookie)"); + return new Header("Cookie", formatCookie(cookie)); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/IgnoreCookiesSpec.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/IgnoreCookiesSpec.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/IgnoreCookiesSpec.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,152 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/IgnoreCookiesSpec.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.cookie; + +import java.util.Collection; + +import org.apache.commons.httpclient.Cookie; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.NameValuePair; + +/** + * A cookie spec that does nothing. Cookies are neither parsed, formatted nor matched. + * It can be used to effectively disable cookies altogether. + * + * @since 3.0 + */ +public class IgnoreCookiesSpec implements CookieSpec { + + /** + * + */ + public IgnoreCookiesSpec() { + super(); + } + + /** + * Returns an empty {@link Cookie cookie} array. All parameters are ignored. + */ + public Cookie[] parse(String host, int port, String path, boolean secure, String header) + throws MalformedCookieException { + return new Cookie[0]; + } + + /** + * @return null + */ + public Collection getValidDateFormats() { + return null; + } + + /** + * Does nothing. + */ + public void setValidDateFormats(Collection datepatterns) { + } + + /** + * @return null + */ + public String formatCookie(Cookie cookie) { + return null; + } + + /** + * @return null + */ + public Header formatCookieHeader(Cookie cookie) throws IllegalArgumentException { + return null; + } + + /** + * @return null + */ + public Header formatCookieHeader(Cookie[] cookies) throws IllegalArgumentException { + return null; + } + + /** + * @return null + */ + public String formatCookies(Cookie[] cookies) throws IllegalArgumentException { + return null; + } + + /** + * @return false + */ + public boolean match(String host, int port, String path, boolean secure, Cookie cookie) { + return false; + } + + /** + * Returns an empty {@link Cookie cookie} array. All parameters are ignored. + */ + public Cookie[] match(String host, int port, String path, boolean secure, Cookie[] cookies) { + return new Cookie[0]; + } + + /** + * Returns an empty {@link Cookie cookie} array. All parameters are ignored. + */ + public Cookie[] parse(String host, int port, String path, boolean secure, Header header) + throws MalformedCookieException, IllegalArgumentException { + return new Cookie[0]; + } + + /** + * Does nothing. + */ + public void parseAttribute(NameValuePair attribute, Cookie cookie) + throws MalformedCookieException, IllegalArgumentException { + } + + /** + * Does nothing. + */ + public void validate(String host, int port, String path, boolean secure, Cookie cookie) + throws MalformedCookieException, IllegalArgumentException { + } + + /** + * @return false + */ + public boolean domainMatch(final String host, final String domain) { + return false; + } + + /** + * @return false + */ + public boolean pathMatch(final String path, final String topmostPath) { + return false; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/MalformedCookieException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/MalformedCookieException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/MalformedCookieException.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,72 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/MalformedCookieException.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.cookie; + +import org.apache.commons.httpclient.ProtocolException; + +/** + * Signals that a cookie is in some way invalid or illegal in a given + * context + * + * @author Oleg Kalnichevski + * + * @since 2.0 + */ +public class MalformedCookieException extends ProtocolException { + + /** + * Creates a new MalformedCookieException with a null detail message. + */ + public MalformedCookieException() { + super(); + } + + /** + * Creates a new MalformedCookieException with a specified message string. + * + * @param message The exception detail message + */ + public MalformedCookieException(String message) { + super(message); + } + + /** + * Creates a new MalformedCookieException with the specified detail message and cause. + * + * @param message the exception detail message + * @param cause the Throwable that caused this exception, or null + * if the cause is unavailable, unknown, or not a Throwable + * + * @since 3.0 + */ + public MalformedCookieException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/NetscapeDraftSpec.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/NetscapeDraftSpec.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/NetscapeDraftSpec.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,270 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/NetscapeDraftSpec.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.cookie; + +import java.util.StringTokenizer; +import java.util.Date; +import java.util.Locale; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.text.ParseException; + +import org.apache.commons.httpclient.HeaderElement; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.Cookie; + +/** + *

      Netscape cookie draft specific cookie management functions + * + * @author B.C. Holmes + * @author Park, Sung-Gu + * @author Doug Sale + * @author Rod Waldhoff + * @author dIon Gillard + * @author Sean C. Sullivan + * @author John Evans + * @author Marc A. Saegesser + * @author Oleg Kalnichevski + * @author Mike Bowler + * + * @since 2.0 + */ + +public class NetscapeDraftSpec extends CookieSpecBase { + + /** Default constructor */ + public NetscapeDraftSpec() { + super(); + } + + /** + * Parses the Set-Cookie value into an array of Cookies. + * + *

      Syntax of the Set-Cookie HTTP Response Header:

      + * + *

      This is the format a CGI script would use to add to + * the HTTP headers a new piece of data which is to be stored by + * the client for later retrieval.

      + * + *
      +      *  Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
      +      * 
      + * + *

      Please note that Netscape draft specification does not fully + * conform to the HTTP header format. Netscape draft does not specify + * whether multiple cookies may be sent in one header. Hence, comma + * character may be present in unquoted cookie value or unquoted + * parameter value.

      + * + * @link http://wp.netscape.com/newsref/std/cookie_spec.html + * + * @param host the host from which the Set-Cookie value was + * received + * @param port the port from which the Set-Cookie value was + * received + * @param path the path from which the Set-Cookie value was + * received + * @param secure true when the Set-Cookie value was + * received over secure conection + * @param header the Set-Cookie received from the server + * @return an array of Cookies parsed from the Set-Cookie value + * @throws MalformedCookieException if an exception occurs during parsing + * + * @since 3.0 + */ + public Cookie[] parse(String host, int port, String path, + boolean secure, final String header) + throws MalformedCookieException { + + LOG.trace("enter NetscapeDraftSpec.parse(String, port, path, boolean, Header)"); + + if (host == null) { + throw new IllegalArgumentException("Host of origin may not be null"); + } + if (host.trim().equals("")) { + throw new IllegalArgumentException("Host of origin may not be blank"); + } + if (port < 0) { + throw new IllegalArgumentException("Invalid port: " + port); + } + if (path == null) { + throw new IllegalArgumentException("Path of origin may not be null."); + } + if (header == null) { + throw new IllegalArgumentException("Header may not be null."); + } + + if (path.trim().equals("")) { + path = PATH_DELIM; + } + host = host.toLowerCase(); + + String defaultPath = path; + int lastSlashIndex = defaultPath.lastIndexOf(PATH_DELIM); + if (lastSlashIndex >= 0) { + if (lastSlashIndex == 0) { + //Do not remove the very first slash + lastSlashIndex = 1; + } + defaultPath = defaultPath.substring(0, lastSlashIndex); + } + HeaderElement headerelement = new HeaderElement(header.toCharArray()); + Cookie cookie = new Cookie(host, + headerelement.getName(), + headerelement.getValue(), + defaultPath, + null, + false); + // cycle through the parameters + NameValuePair[] parameters = headerelement.getParameters(); + // could be null. In case only a header element and no parameters. + if (parameters != null) { + for (int j = 0; j < parameters.length; j++) { + parseAttribute(parameters[j], cookie); + } + } + return new Cookie[] {cookie}; + } + + + /** + * Parse the cookie attribute and update the corresponsing {@link Cookie} + * properties as defined by the Netscape draft specification + * + * @param attribute {@link NameValuePair} cookie attribute from the + * Set- Cookie + * @param cookie {@link Cookie} to be updated + * @throws MalformedCookieException if an exception occurs during parsing + */ + public void parseAttribute( + final NameValuePair attribute, final Cookie cookie) + throws MalformedCookieException { + + if (attribute == null) { + throw new IllegalArgumentException("Attribute may not be null."); + } + if (cookie == null) { + throw new IllegalArgumentException("Cookie may not be null."); + } + final String paramName = attribute.getName().toLowerCase(); + final String paramValue = attribute.getValue(); + + if (paramName.equals("expires")) { + + if (paramValue == null) { + throw new MalformedCookieException( + "Missing value for expires attribute"); + } + try { + DateFormat expiryFormat = new SimpleDateFormat( + "EEE, dd-MMM-yyyy HH:mm:ss z", Locale.US); + Date date = expiryFormat.parse(paramValue); + cookie.setExpiryDate(date); + } catch (ParseException e) { + throw new MalformedCookieException("Invalid expires " + + "attribute: " + e.getMessage()); + } + } else { + super.parseAttribute(attribute, cookie); + } + } + + /** + * Performs domain-match as described in the Netscape draft. + * @param host The target host. + * @param domain The cookie domain attribute. + * @return true if the specified host matches the given domain. + */ + public boolean domainMatch(final String host, final String domain) { + return host.endsWith(domain); + } + + /** + * Performs Netscape draft compliant {@link Cookie} validation + * + * @param host the host from which the {@link Cookie} was received + * @param port the port from which the {@link Cookie} was received + * @param path the path from which the {@link Cookie} was received + * @param secure true when the {@link Cookie} was received + * using a secure connection + * @param cookie The cookie to validate. + * @throws MalformedCookieException if an exception occurs during + * validation + */ + public void validate(String host, int port, String path, + boolean secure, final Cookie cookie) + throws MalformedCookieException { + + LOG.trace("enterNetscapeDraftCookieProcessor " + + "RCF2109CookieProcessor.validate(Cookie)"); + // Perform generic validation + super.validate(host, port, path, secure, cookie); + // Perform Netscape Cookie draft specific validation + if (host.indexOf(".") >= 0) { + int domainParts = new StringTokenizer(cookie.getDomain(), ".") + .countTokens(); + + if (isSpecialDomain(cookie.getDomain())) { + if (domainParts < 2) { + throw new MalformedCookieException("Domain attribute \"" + + cookie.getDomain() + + "\" violates the Netscape cookie specification for " + + "special domains"); + } + } else { + if (domainParts < 3) { + throw new MalformedCookieException("Domain attribute \"" + + cookie.getDomain() + + "\" violates the Netscape cookie specification"); + } + } + } + } + + /** + * Checks if the given domain is in one of the seven special + * top level domains defined by the Netscape cookie specification. + * @param domain The domain. + * @return True if the specified domain is "special" + */ + private static boolean isSpecialDomain(final String domain) { + final String ucDomain = domain.toUpperCase(); + if (ucDomain.endsWith(".COM") + || ucDomain.endsWith(".EDU") + || ucDomain.endsWith(".NET") + || ucDomain.endsWith(".GOV") + || ucDomain.endsWith(".MIL") + || ucDomain.endsWith(".ORG") + || ucDomain.endsWith(".INT")) { + return true; + } + return false; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/RFC2109Spec.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/RFC2109Spec.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/RFC2109Spec.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,285 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/RFC2109Spec.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.cookie; + +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.Cookie; +import org.apache.commons.httpclient.util.ParameterFormatter; + +/** + *

      RFC 2109 specific cookie management functions + * + * @author B.C. Holmes + * @author Park, Sung-Gu + * @author Doug Sale + * @author Rod Waldhoff + * @author dIon Gillard + * @author Sean C. Sullivan + * @author John Evans + * @author Marc A. Saegesser + * @author Oleg Kalnichevski + * @author Mike Bowler + * + * @since 2.0 + */ + +public class RFC2109Spec extends CookieSpecBase { + + private final ParameterFormatter formatter; + + /** Default constructor */ + public RFC2109Spec() { + super(); + this.formatter = new ParameterFormatter(); + this.formatter.setAlwaysUseQuotes(true); + } + + /** + * Parse RFC 2109 specific cookie attribute and update the corresponsing + * {@link Cookie} properties. + * + * @param attribute {@link NameValuePair} cookie attribute from the + * Set- Cookie + * @param cookie {@link Cookie} to be updated + * @throws MalformedCookieException if an exception occurs during parsing + */ + public void parseAttribute( + final NameValuePair attribute, final Cookie cookie) + throws MalformedCookieException { + + if (attribute == null) { + throw new IllegalArgumentException("Attribute may not be null."); + } + if (cookie == null) { + throw new IllegalArgumentException("Cookie may not be null."); + } + final String paramName = attribute.getName().toLowerCase(); + final String paramValue = attribute.getValue(); + + if (paramName.equals("path")) { + if (paramValue == null) { + throw new MalformedCookieException( + "Missing value for path attribute"); + } + if (paramValue.trim().equals("")) { + throw new MalformedCookieException( + "Blank value for path attribute"); + } + cookie.setPath(paramValue); + cookie.setPathAttributeSpecified(true); + } else if (paramName.equals("version")) { + + if (paramValue == null) { + throw new MalformedCookieException( + "Missing value for version attribute"); + } + try { + cookie.setVersion(Integer.parseInt(paramValue)); + } catch (NumberFormatException e) { + throw new MalformedCookieException("Invalid version: " + + e.getMessage()); + } + + } else { + super.parseAttribute(attribute, cookie); + } + } + + /** + * Performs RFC 2109 compliant {@link Cookie} validation + * + * @param host the host from which the {@link Cookie} was received + * @param port the port from which the {@link Cookie} was received + * @param path the path from which the {@link Cookie} was received + * @param secure true when the {@link Cookie} was received using a + * secure connection + * @param cookie The cookie to validate + * @throws MalformedCookieException if an exception occurs during + * validation + */ + public void validate(String host, int port, String path, + boolean secure, final Cookie cookie) throws MalformedCookieException { + + LOG.trace("enter RFC2109Spec.validate(String, int, String, " + + "boolean, Cookie)"); + + // Perform generic validation + super.validate(host, port, path, secure, cookie); + // Perform RFC 2109 specific validation + + if (cookie.getName().indexOf(' ') != -1) { + throw new MalformedCookieException("Cookie name may not contain blanks"); + } + if (cookie.getName().startsWith("$")) { + throw new MalformedCookieException("Cookie name may not start with $"); + } + + if (cookie.isDomainAttributeSpecified() + && (!cookie.getDomain().equals(host))) { + + // domain must start with dot + if (!cookie.getDomain().startsWith(".")) { + throw new MalformedCookieException("Domain attribute \"" + + cookie.getDomain() + + "\" violates RFC 2109: domain must start with a dot"); + } + // domain must have at least one embedded dot + int dotIndex = cookie.getDomain().indexOf('.', 1); + if (dotIndex < 0 || dotIndex == cookie.getDomain().length() - 1) { + throw new MalformedCookieException("Domain attribute \"" + + cookie.getDomain() + + "\" violates RFC 2109: domain must contain an embedded dot"); + } + host = host.toLowerCase(); + if (!host.endsWith(cookie.getDomain())) { + throw new MalformedCookieException( + "Illegal domain attribute \"" + cookie.getDomain() + + "\". Domain of origin: \"" + host + "\""); + } + // host minus domain may not contain any dots + String hostWithoutDomain = host.substring(0, host.length() + - cookie.getDomain().length()); + if (hostWithoutDomain.indexOf('.') != -1) { + throw new MalformedCookieException("Domain attribute \"" + + cookie.getDomain() + + "\" violates RFC 2109: host minus domain may not contain any dots"); + } + } + } + + /** + * Performs domain-match as defined by the RFC2109. + * @param host The target host. + * @param domain The cookie domain attribute. + * @return true if the specified host matches the given domain. + * + * @since 3.0 + */ + public boolean domainMatch(String host, String domain) { + boolean match = host.equals(domain) + || (domain.startsWith(".") && host.endsWith(domain)); + + return match; + } + + /** + * Return a name/value string suitable for sending in a "Cookie" + * header as defined in RFC 2109 for backward compatibility with cookie + * version 0 + * @param buffer The string buffer to use for output + * @param param The parameter. + * @param version The cookie version + */ + private void formatParam(final StringBuffer buffer, final NameValuePair param, int version) { + if (version < 1) { + buffer.append(param.getName()); + buffer.append("="); + if (param.getValue() != null) { + buffer.append(param.getValue()); + } + } else { + this.formatter.format(buffer, param); + } + } + + /** + * Return a string suitable for sending in a "Cookie" header + * as defined in RFC 2109 for backward compatibility with cookie version 0 + * @param buffer The string buffer to use for output + * @param cookie The {@link Cookie} to be formatted as string + * @param version The version to use. + */ + private void formatCookieAsVer(final StringBuffer buffer, final Cookie cookie, int version) { + String value = cookie.getValue(); + if (value == null) { + value = ""; + } + formatParam(buffer, new NameValuePair(cookie.getName(), value), version); + if ((cookie.getPath() != null) && cookie.isPathAttributeSpecified()) { + buffer.append("; "); + formatParam(buffer, new NameValuePair("$Path", cookie.getPath()), version); + } + if ((cookie.getDomain() != null) + && cookie.isDomainAttributeSpecified()) { + buffer.append("; "); + formatParam(buffer, new NameValuePair("$Domain", cookie.getDomain()), version); + } + } + + /** + * Return a string suitable for sending in a "Cookie" header as + * defined in RFC 2109 + * @param cookie a {@link Cookie} to be formatted as string + * @return a string suitable for sending in a "Cookie" header. + */ + public String formatCookie(Cookie cookie) { + LOG.trace("enter RFC2109Spec.formatCookie(Cookie)"); + if (cookie == null) { + throw new IllegalArgumentException("Cookie may not be null"); + } + int version = cookie.getVersion(); + StringBuffer buffer = new StringBuffer(); + formatParam(buffer, + new NameValuePair("$Version", Integer.toString(version)), + version); + buffer.append("; "); + formatCookieAsVer(buffer, cookie, version); + return buffer.toString(); + } + + /** + * Create a RFC 2109 compliant "Cookie" header value containing all + * {@link Cookie}s in cookies suitable for sending in a "Cookie" + * header + * @param cookies an array of {@link Cookie}s to be formatted + * @return a string suitable for sending in a Cookie header. + */ + public String formatCookies(Cookie[] cookies) { + LOG.trace("enter RFC2109Spec.formatCookieHeader(Cookie[])"); + int version = Integer.MAX_VALUE; + // Pick the lowerest common denominator + for (int i = 0; i < cookies.length; i++) { + Cookie cookie = cookies[i]; + if (cookie.getVersion() < version) { + version = cookie.getVersion(); + } + } + final StringBuffer buffer = new StringBuffer(); + formatParam(buffer, + new NameValuePair("$Version", Integer.toString(version)), + version); + for (int i = 0; i < cookies.length; i++) { + buffer.append("; "); + formatCookieAsVer(buffer, cookies[i], version); + } + return buffer.toString(); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/cookie/package.html 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,11 @@ + + + + Package Documentation for org.apache.commons.httpclient.cookie + + + Provides cookie handling in conjunction with {@link org.apache.commons.httpclient.Cookie}. + + @since 2.0 + + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,106 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + * [Additional notices, if required by prior licensing conditions] + * + */ +package org.apache.commons.httpclient.methods; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * A RequestEntity that contains an array of bytes. + * + * @since 3.0 + */ +public class ByteArrayRequestEntity implements RequestEntity { + + /** The content */ + private byte[] content; + + /** The content type */ + private String contentType; + + /** + * Creates a new entity with the given content. + * @param content The content to set. + */ + public ByteArrayRequestEntity(byte[] content) { + this(content, null); + } + + /** + * Creates a new entity with the given content and content type. + * @param content The content to set. + * @param contentType The content type to set or null. + */ + public ByteArrayRequestEntity(byte[] content, String contentType) { + super(); + if (content == null) { + throw new IllegalArgumentException("The content cannot be null"); + } + this.content = content; + this.contentType = contentType; + } + + /** + * @return true + */ + public boolean isRepeatable() { + return true; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() + */ + public String getContentType() { + return contentType; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream) + */ + public void writeRequest(OutputStream out) throws IOException { + out.write(content); + } + + /** + * @return The length of the content. + */ + public long getContentLength() { + return content.length; + } + + /** + * @return Returns the content. + */ + public byte[] getContent() { + return content; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/DeleteMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/DeleteMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/DeleteMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,95 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/DeleteMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import org.apache.commons.httpclient.HttpMethodBase; + + +/** + * Implements the HTTP DELETE method. + *

      + * The HTTP DELETE method is defined in section 9.7 of + * RFC2616: + *

      + * The DELETE method requests that the origin server delete the resource + * identified by the Request-URI. This method MAY be overridden by human + * intervention (or other means) on the origin server. + *
      + *

      + * + * @author Remy Maucherat + * @author B.C. Holmes + * @author Jeff Dever + * + * @version $Revision: 1.1 $ + * @since 1.0 + */ +public class DeleteMethod + extends HttpMethodBase { + + + // ----------------------------------------------------------- Constructors + + + /** + * No-arg constructor. + * + * @since 1.0 + */ + public DeleteMethod() { + } + + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 1.0 + */ + public DeleteMethod(String uri) { + super(uri); + } + + + // ----------------------------------------------------- HttpMethod Methods + + /** + * Returns "DELETE". + * @return "DELETE" + * + * @since 2.0 + */ + public String getName() { + return "DELETE"; + } + + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java 22 Aug 2012 17:30:36 -0000 1.1 @@ -0,0 +1,547 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v 1.1 2012/08/22 17:30:36 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:36 $ + * + * ==================================================================== + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.commons.httpclient.ChunkedOutputStream; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.HttpVersion; +import org.apache.commons.httpclient.ProtocolException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This abstract class serves as a foundation for all HTTP methods + * that can enclose an entity within requests + * + * @author Oleg Kalnichevski + * @author Jeff Dever + * + * @since 2.0beta1 + * @version $Revision: 1.1 $ + */ +public abstract class EntityEnclosingMethod extends ExpectContinueMethod { + + // ----------------------------------------- Static variables/initializers + + /** + * The content length will be calculated automatically. This implies + * buffering of the content. + * @deprecated Use {@link InputStreamRequestEntity#CONTENT_LENGTH_AUTO}. + */ + public static final long CONTENT_LENGTH_AUTO = InputStreamRequestEntity.CONTENT_LENGTH_AUTO; + + /** + * The request will use chunked transfer encoding. Content length is not + * calculated and the content is not buffered.
      + * @deprecated Use {@link #setContentChunked(boolean)}. + */ + public static final long CONTENT_LENGTH_CHUNKED = -1; + + /** LOG object for this class. */ + private static final Log LOG = LogFactory.getLog(EntityEnclosingMethod.class); + + /** The unbuffered request body, if any. */ + private InputStream requestStream = null; + + /** The request body as string, if any. */ + private String requestString = null; + + private RequestEntity requestEntity; + + /** Counts how often the request was sent to the server. */ + private int repeatCount = 0; + + /** The content length of the requestBodyStream or one of + * CONTENT_LENGTH_AUTO and CONTENT_LENGTH_CHUNKED. + * + * @deprecated + */ + private long requestContentLength = InputStreamRequestEntity.CONTENT_LENGTH_AUTO; + + private boolean chunked = false; + + // ----------------------------------------------------------- Constructors + + /** + * No-arg constructor. + * + * @since 2.0 + */ + public EntityEnclosingMethod() { + super(); + setFollowRedirects(false); + } + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 2.0 + */ + public EntityEnclosingMethod(String uri) { + super(uri); + setFollowRedirects(false); + } + + /** + * Returns true if there is a request body to be sent. + * + *

      This method must be overridden by sub-classes that implement + * alternative request content input methods + *

      + * + * @return boolean + * + * @since 2.0beta1 + */ + protected boolean hasRequestContent() { + LOG.trace("enter EntityEnclosingMethod.hasRequestContent()"); + return (this.requestEntity != null) + || (this.requestStream != null) + || (this.requestString != null); + } + + /** + * Clears the request body. + * + *

      This method must be overridden by sub-classes that implement + * alternative request content input methods.

      + * + * @since 2.0beta1 + */ + protected void clearRequestBody() { + LOG.trace("enter EntityEnclosingMethod.clearRequestBody()"); + this.requestStream = null; + this.requestString = null; + this.requestEntity = null; + } + + /** + * Generates the request body. + * + *

      This method must be overridden by sub-classes that implement + * alternative request content input methods.

      + * + * @return request body as an array of bytes. If the request content + * has not been set, returns null. + * + * @since 2.0beta1 + */ + protected byte[] generateRequestBody() { + LOG.trace("enter EntityEnclosingMethod.renerateRequestBody()"); + return null; + } + + protected RequestEntity generateRequestEntity() { + + byte[] requestBody = generateRequestBody(); + if (requestBody != null) { + // use the request body, if it exists. + // this is just for backwards compatability + this.requestEntity = new ByteArrayRequestEntity(requestBody); + } else if (this.requestStream != null) { + this.requestEntity = new InputStreamRequestEntity( + requestStream, + requestContentLength); + this.requestStream = null; + } else if (this.requestString != null) { + String charset = getRequestCharSet(); + try { + this.requestEntity = new StringRequestEntity( + requestString, null, charset); + } catch (UnsupportedEncodingException e) { + if (LOG.isWarnEnabled()) { + LOG.warn(charset + " not supported"); + } + this.requestEntity = new StringRequestEntity( + requestString); + } + } + + return this.requestEntity; + } + + /** + * Entity enclosing requests cannot be redirected without user intervention + * according to RFC 2616. + * + * @return false. + * + * @since 2.0 + */ + public boolean getFollowRedirects() { + return false; + } + + + /** + * Entity enclosing requests cannot be redirected without user intervention + * according to RFC 2616. + * + * @param followRedirects must always be false + */ + public void setFollowRedirects(boolean followRedirects) { + if (followRedirects == true) { + throw new IllegalArgumentException("Entity enclosing requests cannot be redirected without user intervention"); + } + super.setFollowRedirects(false); + } + + /** + * Sets length information about the request body. + * + *

      + * Note: If you specify a content length the request is unbuffered. This + * prevents redirection and automatic retry if a request fails the first + * time. This means that the HttpClient can not perform authorization + * automatically but will throw an Exception. You will have to set the + * necessary 'Authorization' or 'Proxy-Authorization' headers manually. + *

      + * + * @param length size in bytes or any of CONTENT_LENGTH_AUTO, + * CONTENT_LENGTH_CHUNKED. If number of bytes or CONTENT_LENGTH_CHUNKED + * is specified the content will not be buffered internally and the + * Content-Length header of the request will be used. In this case + * the user is responsible to supply the correct content length. + * If CONTENT_LENGTH_AUTO is specified the request will be buffered + * before it is sent over the network. + * + * @deprecated Use {@link #setContentChunked(boolean)} or + * {@link #setRequestEntity(RequestEntity)} + */ + public void setRequestContentLength(int length) { + LOG.trace("enter EntityEnclosingMethod.setRequestContentLength(int)"); + this.requestContentLength = length; + } + + /** + * Returns the request's charset. The charset is parsed from the request entity's + * content type, unless the content type header has been set manually. + * + * @see RequestEntity#getContentType() + * + * @since 3.0 + */ + public String getRequestCharSet() { + if (getRequestHeader("Content-Type") == null) { + // check the content type from request entity + // We can't call getRequestEntity() since it will probably call + // this method. + if (this.requestEntity != null) { + return getContentCharSet( + new Header("Content-Type", requestEntity.getContentType())); + } else { + return super.getRequestCharSet(); + } + } else { + return super.getRequestCharSet(); + } + } + + /** + * Sets length information about the request body. + * + *

      + * Note: If you specify a content length the request is unbuffered. This + * prevents redirection and automatic retry if a request fails the first + * time. This means that the HttpClient can not perform authorization + * automatically but will throw an Exception. You will have to set the + * necessary 'Authorization' or 'Proxy-Authorization' headers manually. + *

      + * + * @param length size in bytes or any of CONTENT_LENGTH_AUTO, + * CONTENT_LENGTH_CHUNKED. If number of bytes or CONTENT_LENGTH_CHUNKED + * is specified the content will not be buffered internally and the + * Content-Length header of the request will be used. In this case + * the user is responsible to supply the correct content length. + * If CONTENT_LENGTH_AUTO is specified the request will be buffered + * before it is sent over the network. + * + * @deprecated Use {@link #setContentChunked(boolean)} or + * {@link #setRequestEntity(RequestEntity)} + */ + public void setRequestContentLength(long length) { + LOG.trace("enter EntityEnclosingMethod.setRequestContentLength(int)"); + this.requestContentLength = length; + } + + /** + * Sets whether or not the content should be chunked. + * + * @param chunked true if the content should be chunked + * + * @since 3.0 + */ + public void setContentChunked(boolean chunked) { + this.chunked = chunked; + } + + /** + * Returns the length of the request body. + * + * @return number of bytes in the request body + */ + protected long getRequestContentLength() { + LOG.trace("enter EntityEnclosingMethod.getRequestContentLength()"); + + if (!hasRequestContent()) { + return 0; + } + if (this.chunked) { + return -1; + } + if (this.requestEntity == null) { + this.requestEntity = generateRequestEntity(); + } + return (this.requestEntity == null) ? 0 : this.requestEntity.getContentLength(); + } + + /** + * Populates the request headers map to with additional + * {@link org.apache.commons.httpclient.Header headers} to be submitted to + * the given {@link HttpConnection}. + * + *

      + * This implementation adds tt>Content-Length or Transfer-Encoding + * headers. + *

      + * + *

      + * Subclasses may want to override this method to to add additional + * headers, and may choose to invoke this implementation (via + * super) to add the "standard" headers. + *

      + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #writeRequestHeaders + * + * @since 3.0 + */ + protected void addRequestHeaders(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter EntityEnclosingMethod.addRequestHeaders(HttpState, " + + "HttpConnection)"); + + super.addRequestHeaders(state, conn); + addContentLengthRequestHeader(state, conn); + + // only use the content type of the request entity if it has not already been + // set manually + if (getRequestHeader("Content-Type") == null) { + RequestEntity requestEntity = getRequestEntity(); + if (requestEntity != null && requestEntity.getContentType() != null) { + setRequestHeader("Content-Type", requestEntity.getContentType()); + } + } + } + + /** + * Generates Content-Length or Transfer-Encoding: Chunked + * request header, as long as no Content-Length request header + * already exists. + * + * @param state current state of http requests + * @param conn the connection to use for I/O + * + * @throws IOException when errors occur reading or writing to/from the + * connection + * @throws HttpException when a recoverable error occurs + */ + protected void addContentLengthRequestHeader(HttpState state, + HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter EntityEnclosingMethod.addContentLengthRequestHeader(" + + "HttpState, HttpConnection)"); + + if ((getRequestHeader("content-length") == null) + && (getRequestHeader("Transfer-Encoding") == null)) { + long len = getRequestContentLength(); + if (len < 0) { + if (getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1)) { + addRequestHeader("Transfer-Encoding", "chunked"); + } else { + throw new ProtocolException(getEffectiveVersion() + + " does not support chunk encoding"); + } + } else { + addRequestHeader("Content-Length", String.valueOf(len)); + } + } + } + + /** + * Sets the request body to be the specified inputstream. + * + * @param body Request body content as {@link java.io.InputStream} + * + * @deprecated use {@link #setRequestEntity(RequestEntity)} + */ + public void setRequestBody(InputStream body) { + LOG.trace("enter EntityEnclosingMethod.setRequestBody(InputStream)"); + clearRequestBody(); + this.requestStream = body; + } + + /** + * Sets the request body to be the specified string. + * The string will be submitted, using the encoding + * specified in the Content-Type request header.
      + * Example: setRequestHeader("Content-type", "text/xml; charset=UTF-8");
      + * Would use the UTF-8 encoding. + * If no charset is specified, the + * {@link org.apache.commons.httpclient.HttpConstants#DEFAULT_CONTENT_CHARSET default} + * content encoding is used (ISO-8859-1). + * + * @param body Request body content as a string + * + * @deprecated use {@link #setRequestEntity(RequestEntity)} + */ + public void setRequestBody(String body) { + LOG.trace("enter EntityEnclosingMethod.setRequestBody(String)"); + clearRequestBody(); + this.requestString = body; + } + + /** + * Writes the request body to the given {@link HttpConnection connection}. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @return true + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected boolean writeRequestBody(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace( + "enter EntityEnclosingMethod.writeRequestBody(HttpState, HttpConnection)"); + + if (!hasRequestContent()) { + LOG.debug("Request body has not been specified"); + return true; + } + if (this.requestEntity == null) { + this.requestEntity = generateRequestEntity(); + } + if (requestEntity == null) { + LOG.debug("Request body is empty"); + return true; + } + + long contentLength = getRequestContentLength(); + + if ((this.repeatCount > 0) && !requestEntity.isRepeatable()) { + throw new ProtocolException( + "Unbuffered entity enclosing request can not be repeated."); + } + + this.repeatCount++; + + OutputStream outstream = conn.getRequestOutputStream(); + + if (contentLength < 0) { + outstream = new ChunkedOutputStream(outstream); + } + + requestEntity.writeRequest(outstream); + + // This is hardly the most elegant solution to closing chunked stream + if (outstream instanceof ChunkedOutputStream) { + ((ChunkedOutputStream) outstream).finish(); + } + + outstream.flush(); + + LOG.debug("Request body sent"); + return true; + } + + /** + * Recycles the HTTP method so that it can be used again. + * Note that all of the instance variables will be reset + * once this method has been called. This method will also + * release the connection being used by this HTTP method. + * + * @see #releaseConnection() + * + * @deprecated no longer supported and will be removed in the future + * version of HttpClient + */ + public void recycle() { + LOG.trace("enter EntityEnclosingMethod.recycle()"); + clearRequestBody(); + this.requestContentLength = InputStreamRequestEntity.CONTENT_LENGTH_AUTO; + this.repeatCount = 0; + this.chunked = false; + super.recycle(); + } + + /** + * @return Returns the requestEntity. + * + * @since 3.0 + */ + public RequestEntity getRequestEntity() { + return generateRequestEntity(); + } + + /** + * @param requestEntity The requestEntity to set. + * + * @since 3.0 + */ + public void setRequestEntity(RequestEntity requestEntity) { + clearRequestBody(); + this.requestEntity = requestEntity; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ExpectContinueMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ExpectContinueMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ExpectContinueMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,204 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/ExpectContinueMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import java.io.IOException; +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.HttpVersion; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

      + * This abstract class serves as a foundation for all HTTP methods + * that support 'Expect: 100-continue' handshake. + *

      + * + *

      + * The purpose of the 100 (Continue) status (refer to section 10.1.1 + * of the RFC 2616 for more details) 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. In some cases, + * it might either be inappropriate or highly inefficient for the + * client to send the body if the server will reject the message + * without looking at the body. + *

      + * + *

      + * '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. + *

      + * + * @author Oleg Kalnichevski + * + * @since 2.0beta1 + */ + +public abstract class ExpectContinueMethod extends HttpMethodBase { + + /** LOG object for this class. */ + private static final Log LOG = LogFactory.getLog(ExpectContinueMethod.class); + + /** + * No-arg constructor. + * + * @since 2.0 + */ + public ExpectContinueMethod() { + super(); + } + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 2.0 + */ + public ExpectContinueMethod(String uri) { + super(uri); + } + + /** + *

      + * Returns true if the 'Expect: 100-Continue' handshake + * is activated. The purpose of the 'Expect: 100-Continue' + * handshake 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. + *

      + * + * @return true if 'Expect: 100-Continue' handshake is to + * be used, false otherwise. + * + * @since 2.0beta1 + * + * @deprecated Use {@link HttpMethodParams} + * + * @see #getParams() + * @see HttpMethodParams + * @see HttpMethodParams#USE_EXPECT_CONTINUE + */ + public boolean getUseExpectHeader() { + return getParams().getBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false); + } + + /** + *

      + * Activates 'Expect: 100-Continue' handshake. The purpose of + * the 'Expect: 100-Continue' handshake 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. + *

      + * + *

      + * The use of the 'Expect: 100-continue' handshake can result in + * noticable peformance improvement for entity enclosing requests + * (such as POST and PUT) that require the target server's + * authentication. + *

      + * + *

      + * '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. + *

      + * + * @param value boolean value + * + * @since 2.0beta1 + * + * @deprecated Use {@link HttpMethodParams} + * + * @see #getParams() + * @see HttpMethodParams + * @see HttpMethodParams#USE_EXPECT_CONTINUE + */ + public void setUseExpectHeader(boolean value) { + getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, value); + } + + /** + * Returns true if there is a request body to be sent. + * 'Expect: 100-continue' handshake may not be used if request + * body is not present + * + * @return boolean + * + * @since 2.0beta1 + */ + protected abstract boolean hasRequestContent(); + + /** + * Sets the Expect header if it has not already been set, + * in addition to the "standard" set of headers. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected void addRequestHeaders(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter ExpectContinueMethod.addRequestHeaders(HttpState, HttpConnection)"); + + super.addRequestHeaders(state, conn); + // If the request is being retried, the header may already be present + boolean headerPresent = (getRequestHeader("Expect") != null); + // See if the expect header should be sent + // = HTTP/1.1 or higher + // = request body present + + if (getParams().isParameterTrue(HttpMethodParams.USE_EXPECT_CONTINUE) + && getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1) + && hasRequestContent()) + { + if (!headerPresent) { + setRequestHeader("Expect", "100-continue"); + } + } else { + if (headerPresent) { + removeRequestHeader("Expect"); + } + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/GetMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/GetMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/GetMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,128 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/GetMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Implements the HTTP GET method. + *

      + * The HTTP GET method is defined in section 9.3 of + * RFC2616: + *

      + * 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. + *
      + *

      + *

      + * GetMethods will follow redirect requests from the http server by default. + * This behavour can be disabled by calling setFollowRedirects(false).

      + * + * @author Remy Maucherat + * @author Sung-Gu Park + * @author Sean C. Sullivan + * @author Mike Bowler + * @author Jeff Dever + * + * @version $Revision: 1.1 $ + * @since 1.0 + */ +public class GetMethod extends HttpMethodBase { + + // -------------------------------------------------------------- Constants + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(GetMethod.class); + + // ----------------------------------------------------------- Constructors + + /** + * No-arg constructor. + * + * @since 1.0 + */ + public GetMethod() { + setFollowRedirects(true); + } + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 1.0 + */ + public GetMethod(String uri) { + super(uri); + LOG.trace("enter GetMethod(String)"); + setFollowRedirects(true); + } + + // --------------------------------------------------------- Public Methods + + /** + * Returns "GET". + * + * @return "GET" + * + * @since 2.0 + */ + public String getName() { + return "GET"; + } + + // ------------------------------------------------------------- Properties + + /** + * Recycles the HTTP method so that it can be used again. + * Note that all of the instance variables will be reset + * once this method has been called. This method will also + * release the connection being used by this HTTP method. + * + * @see #releaseConnection() + * + * @since 1.0 + * + * @deprecated no longer supported and will be removed in the future + * version of HttpClient + */ + public void recycle() { + LOG.trace("enter GetMethod.recycle()"); + + super.recycle(); + setFollowRedirects(true); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/HeadMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/HeadMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/HeadMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,218 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/HeadMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import java.io.IOException; + +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.ProtocolException; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Implements the HTTP HEAD method. + *

      + * The HTTP HEAD method is defined in section 9.4 of + * RFC2616: + *

      + * 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. + *
      + *

      + * + * @author Remy Maucherat + * @author Mike Bowler + * @author Jeff Dever + * @author oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * @since 1.0 + */ +public class HeadMethod extends HttpMethodBase { + //~ Static variables/initializers + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HeadMethod.class); + + //~ Constructors + + /** + * No-arg constructor. + * + * @since 1.0 + */ + public HeadMethod() { + setFollowRedirects(true); + } + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 1.0 + */ + public HeadMethod(String uri) { + super(uri); + setFollowRedirects(true); + } + + //~ Methods + + /** + * Returns "HEAD". + * + * @return "HEAD" + * + * @since 2.0 + */ + public String getName() { + return "HEAD"; + } + + /** + * Recycles the HTTP method so that it can be used again. + * Note that all of the instance variables will be reset + * once this method has been called. This method will also + * release the connection being used by this HTTP method. + * + * @see #releaseConnection() + * + * @since 1.0 + * + * @deprecated no longer supported and will be removed in the future + * version of HttpClient + */ + public void recycle() { + super.recycle(); + setFollowRedirects(true); + } + + /** + * Overrides {@link HttpMethodBase} method to not read a response + * body, despite the presence of a Content-Length or + * Transfer-Encoding header. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #readResponse + * @see #processResponseBody + * + * @since 2.0 + */ + protected void readResponseBody(HttpState state, HttpConnection conn) + throws HttpException, IOException { + LOG.trace( + "enter HeadMethod.readResponseBody(HttpState, HttpConnection)"); + + int bodyCheckTimeout = + getParams().getIntParameter(HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, -1); + + if (bodyCheckTimeout < 0) { + responseBodyConsumed(); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Check for non-compliant response body. Timeout in " + + bodyCheckTimeout + " ms"); + } + boolean responseAvailable = false; + try { + responseAvailable = conn.isResponseAvailable(bodyCheckTimeout); + } catch (IOException e) { + LOG.debug("An IOException occurred while testing if a response was available," + + " we will assume one is not.", + e); + responseAvailable = false; + } + if (responseAvailable) { + if (getParams().isParameterTrue(HttpMethodParams.REJECT_HEAD_BODY)) { + throw new ProtocolException( + "Body content may not be sent in response to HTTP HEAD request"); + } else { + LOG.warn("Body content returned in response to HTTP HEAD"); + } + super.readResponseBody(state, conn); + } + } + + } + + /** + * Returns non-compliant response body check timeout. + * + * @return The period of time in milliseconds to wait for a response + * body from a non-compliant server. -1 returned when + * non-compliant response body check is disabled + * + * @deprecated Use {@link HttpMethodParams} + * + * @see #getParams() + * @see HttpMethodParams + * @see HttpMethodParams#HEAD_BODY_CHECK_TIMEOUT + */ + public int getBodyCheckTimeout() { + return getParams().getIntParameter(HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, -1); + } + + /** + * Sets non-compliant response body check timeout. + * + * @param timeout The period of time in milliseconds to wait for a response + * body from a non-compliant server. -1 can be used to + * disable non-compliant response body check + * + * @deprecated Use {@link HttpMethodParams} + * + * @see #getParams() + * @see HttpMethodParams + * @see HttpMethodParams#HEAD_BODY_CHECK_TIMEOUT + */ + public void setBodyCheckTimeout(int timeout) { + getParams().setIntParameter(HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, timeout); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,198 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + * [Additional notices, if required by prior licensing conditions] + * + */ +package org.apache.commons.httpclient.methods; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A RequestEntity that contains an InputStream. + * + * @since 3.0 + */ +public class InputStreamRequestEntity implements RequestEntity { + + /** + * The content length will be calculated automatically. This implies + * buffering of the content. + */ + public static final int CONTENT_LENGTH_AUTO = -2; + + private static final Log LOG = LogFactory.getLog(InputStreamRequestEntity.class); + + private long contentLength; + + private InputStream content; + + /** The buffered request body, if any. */ + private byte[] buffer = null; + + /** The content type */ + private String contentType; + + /** + * Creates a new InputStreamRequestEntity with the given content and a content type of + * {@link #CONTENT_LENGTH_AUTO}. + * @param content The content to set. + */ + public InputStreamRequestEntity(InputStream content) { + this(content, null); + } + + /** + * Creates a new InputStreamRequestEntity with the given content, content type, and a + * content length of {@link #CONTENT_LENGTH_AUTO}. + * @param content The content to set. + * @param contentType The type of the content, or null. + */ + public InputStreamRequestEntity(InputStream content, String contentType) { + this(content, CONTENT_LENGTH_AUTO, contentType); + } + + /** + * Creates a new InputStreamRequestEntity with the given content and content length. + * @param content The content to set. + * @param contentLength The content size in bytes or a negative number if not known. + * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to + * determine its size when {@link #getContentLength()} is called. + */ + public InputStreamRequestEntity(InputStream content, long contentLength) { + this(content, contentLength, null); + } + + /** + * Creates a new InputStreamRequestEntity with the given content, content length, and + * content type. + * @param content The content to set. + * @param contentLength The content size in bytes or a negative number if not known. + * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to + * determine its size when {@link #getContentLength()} is called. + * @param contentType The type of the content, or null. + */ + public InputStreamRequestEntity(InputStream content, long contentLength, String contentType) { + if (content == null) { + throw new IllegalArgumentException("The content cannot be null"); + } + this.content = content; + this.contentLength = contentLength; + this.contentType = contentType; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() + */ + public String getContentType() { + return contentType; + } + + /** + * Buffers request body input stream. + */ + private void bufferContent() { + + if (this.buffer != null) { + // Already been buffered + return; + } + if (this.content != null) { + try { + ByteArrayOutputStream tmp = new ByteArrayOutputStream(); + byte[] data = new byte[4096]; + int l = 0; + while ((l = this.content.read(data)) >= 0) { + tmp.write(data, 0, l); + } + this.buffer = tmp.toByteArray(); + this.content = null; + this.contentLength = buffer.length; + } catch (IOException e) { + LOG.error(e.getMessage(), e); + this.buffer = null; + this.content = null; + this.contentLength = 0; + } + } + } + + /** + * Tests if this method is repeatable. Only true if the content has been + * buffered. + * + * @see #getContentLength() + */ + public boolean isRepeatable() { + return buffer != null; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream) + */ + public void writeRequest(OutputStream out) throws IOException { + + if (content != null) { + byte[] tmp = new byte[4096]; + int total = 0; + int i = 0; + while ((i = content.read(tmp)) >= 0) { + out.write(tmp, 0, i); + total += i; + } + } else if (buffer != null) { + out.write(buffer); + } else { + throw new IllegalStateException("Content must be set before entity is written"); + } + } + + /** + * Gets the content length. If the content length has not been set, the content will be + * buffered to determine the actual content length. + */ + public long getContentLength() { + if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) { + bufferContent(); + } + return contentLength; + } + + /** + * @return Returns the content. + */ + public InputStream getContent() { + return content; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/MultipartPostMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/MultipartPostMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/MultipartPostMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,332 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/MultipartPostMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Implements the HTTP multipart POST method. + *

      + * The HTTP multipart POST method is defined in section 3.3 of + * RFC1867: + *

      + * The media-type multipart/form-data follows the rules of all multipart + * MIME data streams as outlined in RFC 1521. The multipart/form-data contains + * a series of parts. Each part is expected to contain a content-disposition + * header where the value is "form-data" and a name attribute specifies + * the field name within the form, e.g., 'content-disposition: form-data; + * name="xxxxx"', where xxxxx is the field name corresponding to that field. + * Field names originally in non-ASCII character sets may be encoded using + * the method outlined in RFC 1522. + *
      + *

      + *

      + * + * @author Matthew Albright + * @author Jeff Dever + * @author Adrian Sutton + * @author Mark Diggory + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @since 2.0 + * + * @deprecated Use {@link org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity} + * in conjunction with {@link org.apache.commons.httpclient.methods.PostMethod} instead. + */ +public class MultipartPostMethod extends ExpectContinueMethod { + + /** The Content-Type for multipart/form-data. */ + public static final String MULTIPART_FORM_CONTENT_TYPE = + "multipart/form-data"; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(MultipartPostMethod.class); + + /** The parameters for this method */ + private final List parameters = new ArrayList(); + + /** + * No-arg constructor. + */ + public MultipartPostMethod() { + super(); + } + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + */ + public MultipartPostMethod(String uri) { + super(uri); + } + + /** + * Returns true + * + * @return true + * + * @since 2.0beta1 + */ + protected boolean hasRequestContent() { + return true; + } + + /** + * Returns "POST". + * @return "POST" + */ + public String getName() { + return "POST"; + } + + /** + * Adds a text field part + * + * @param parameterName The name of the parameter. + * @param parameterValue The value of the parameter. + */ + public void addParameter(String parameterName, String parameterValue) { + LOG.trace("enter addParameter(String parameterName, String parameterValue)"); + Part param = new StringPart(parameterName, parameterValue); + parameters.add(param); + } + + /** + * Adds a binary file part + * + * @param parameterName The name of the parameter + * @param parameterFile The name of the file. + * @throws FileNotFoundException If the file cannot be found. + */ + public void addParameter(String parameterName, File parameterFile) + throws FileNotFoundException { + LOG.trace("enter MultipartPostMethod.addParameter(String parameterName, " + + "File parameterFile)"); + Part param = new FilePart(parameterName, parameterFile); + parameters.add(param); + } + + /** + * Adds a binary file part with the given file name + * + * @param parameterName The name of the parameter + * @param fileName The file name + * @param parameterFile The file + * @throws FileNotFoundException If the file cannot be found. + */ + public void addParameter(String parameterName, String fileName, File parameterFile) + throws FileNotFoundException { + LOG.trace("enter MultipartPostMethod.addParameter(String parameterName, " + + "String fileName, File parameterFile)"); + Part param = new FilePart(parameterName, fileName, parameterFile); + parameters.add(param); + } + + /** + * Adds a part. + * + * @param part The part to add. + */ + public void addPart (final Part part) { + LOG.trace("enter addPart(Part part)"); + parameters.add(part); + } + + /** + * Returns all parts. + * + * @return an array of containing all parts + */ + public Part[] getParts() { + return (Part[]) parameters.toArray(new Part[parameters.size()]); + } + + /** + * Adds a Content-Length request header, as long as no + * Content-Length request header already exists. + * + * @param state current state of http requests + * @param conn the connection to use for I/O + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @since 3.0 + */ + protected void addContentLengthRequestHeader(HttpState state, + HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter EntityEnclosingMethod.addContentLengthRequestHeader(" + + "HttpState, HttpConnection)"); + + if (getRequestHeader("Content-Length") == null) { + long len = getRequestContentLength(); + addRequestHeader("Content-Length", String.valueOf(len)); + } + removeRequestHeader("Transfer-Encoding"); + } + + /** + * Adds a Content-Type request header. + * + * @param state current state of http requests + * @param conn the connection to use for I/O + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @since 3.0 + */ + protected void addContentTypeRequestHeader(HttpState state, + HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter EntityEnclosingMethod.addContentTypeRequestHeader(" + + "HttpState, HttpConnection)"); + + if (!parameters.isEmpty()) { + StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE); + if (Part.getBoundary() != null) { + buffer.append("; boundary="); + buffer.append(Part.getBoundary()); + } + setRequestHeader("Content-Type", buffer.toString()); + } + } + + /** + * Populates the request headers map to with additional + * {@link org.apache.commons.httpclient.Header headers} to be submitted to + * the given {@link HttpConnection}. + * + *

      + * This implementation adds tt>Content-Length and Content-Type + * headers, when appropriate. + *

      + * + *

      + * Subclasses may want to override this method to to add additional + * headers, and may choose to invoke this implementation (via + * super) to add the "standard" headers. + *

      + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + * + * @see #writeRequestHeaders + */ + protected void addRequestHeaders(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter MultipartPostMethod.addRequestHeaders(HttpState state, " + + "HttpConnection conn)"); + super.addRequestHeaders(state, conn); + addContentLengthRequestHeader(state, conn); + addContentTypeRequestHeader(state, conn); + } + + /** + * Writes the request body to the given {@link HttpConnection connection}. + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @return true + * + * @throws IOException if an I/O (transport) error occurs. Some transport exceptions + * can be recovered from. + * @throws HttpException if a protocol exception occurs. Usually protocol exceptions + * cannot be recovered from. + */ + protected boolean writeRequestBody(HttpState state, HttpConnection conn) + throws IOException, HttpException { + LOG.trace("enter MultipartPostMethod.writeRequestBody(HttpState state, " + + "HttpConnection conn)"); + OutputStream out = conn.getRequestOutputStream(); + Part.sendParts(out, getParts()); + return true; + } + + /** + *

      Return the length of the request body.

      + * + *

      Once this method has been invoked, the request parameters cannot be + * altered until the method is {@link #recycle recycled}.

      + * + * @return The request content length. + */ + protected long getRequestContentLength() throws IOException { + LOG.trace("enter MultipartPostMethod.getRequestContentLength()"); + return Part.getLengthOfParts(getParts()); + } + + + /** + * Recycles the HTTP method so that it can be used again. + * Note that all of the instance variables will be reset + * once this method has been called. This method will also + * release the connection being used by this HTTP method. + * + * @see #releaseConnection() + * + * @deprecated no longer supported and will be removed in the future + * version of HttpClient + */ + public void recycle() { + LOG.trace("enter MultipartPostMethod.recycle()"); + super.recycle(); + parameters.clear(); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/OptionsMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/OptionsMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/OptionsMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,191 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/OptionsMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.HttpState; + +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.Log; +import java.util.Enumeration; +import java.util.StringTokenizer; +import java.util.Vector; + + +/** + * Implements the HTTP OPTIONS method. + *

      + * The HTTP OPTIONS method is defined in section 9.2 of + * RFC2616: + *

      + * 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. + *
      + *

      + * + * @author Remy Maucherat + * @author Mike Bowler + * @author Jeff Dever + * + * @version $Revision: 1.1 $ + * @since 1.0 + */ +public class OptionsMethod + extends HttpMethodBase { + + + // --------------------------------------------------------- Class Variables + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(OptionsMethod.class); + + // ----------------------------------------------------------- Constructors + + + /** + * Method constructor. + * + * @since 1.0 + */ + public OptionsMethod() { + } + + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 1.0 + */ + public OptionsMethod(String uri) { + super(uri); + } + + + // ----------------------------------------------------- Instance Variables + + + /** + * Methods allowed. + */ + private Vector methodsAllowed = new Vector(); + + + // --------------------------------------------------------- Public Methods + + /** + * Get the name. + * @return "OPTIONS" + * @since 2.0 + */ + public String getName() { + return "OPTIONS"; + } + + + /** + * Is the specified method allowed ? + * + * @param method The method to check. + * @return true if the specified method is allowed. + * @since 1.0 + */ + public boolean isAllowed(String method) { + checkUsed(); + return methodsAllowed.contains(method); + } + + + /** + * Get a list of allowed methods. + * @return An enumeration of all the allowed methods. + * + * @since 1.0 + */ + public Enumeration getAllowedMethods() { + checkUsed(); + return methodsAllowed.elements(); + } + + + // ----------------------------------------------------- HttpMethod Methods + + /** + *

      + * This implementation will parse the Allow header to obtain + * the set of methods supported by the resource identified by the Request-URI. + *

      + * + * @param state the {@link HttpState state} information associated with this method + * @param conn the {@link HttpConnection connection} used to execute + * this HTTP method + * + * @see #readResponse + * @see #readResponseHeaders + * @since 2.0 + */ + protected void processResponseHeaders(HttpState state, HttpConnection conn) { + LOG.trace("enter OptionsMethod.processResponseHeaders(HttpState, HttpConnection)"); + + Header allowHeader = getResponseHeader("allow"); + if (allowHeader != null) { + String allowHeaderValue = allowHeader.getValue(); + StringTokenizer tokenizer = + new StringTokenizer(allowHeaderValue, ","); + while (tokenizer.hasMoreElements()) { + String methodAllowed = + tokenizer.nextToken().trim().toUpperCase(); + methodsAllowed.addElement(methodAllowed); + } + } + } + + /** + * Return true if the method needs a content-length header in the request. + * + * @return true if a content-length header will be expected by the server + * + * @since 1.0 + * + * @deprecated only entity enclosing methods set content length header + */ + public boolean needContentLength() { + return false; + } + + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PostMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PostMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PostMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,410 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PostMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import java.util.Iterator; +import java.util.Vector; + +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Implements the HTTP POST method. + *

      + * The HTTP POST method is defined in section 9.5 of + * RFC2616: + *

      + * 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: + *
        + *
      • Annotation of existing resources
      • + *
      • Posting a message to a bulletin board, newsgroup, mailing list, or + * similar group of articles
      • + *
      • Providing a block of data, such as the result of submitting a form, + * to a data-handling process
      • + *
      • Extending a database through an append operation
      • + *
      + *
      + *

      + * + * @author Remy Maucherat + * @author Doug Sale + * @author Jeff Dever + * @author Ortwin Gl???ck + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * @since 1.0 + */ +public class PostMethod extends EntityEnclosingMethod { + // -------------------------------------------------------------- Constants + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(PostMethod.class); + + /** The Content-Type for www-form-urlencoded. */ + public static final String FORM_URL_ENCODED_CONTENT_TYPE = + "application/x-www-form-urlencoded"; + + /** + * The buffered request body consisting of NameValuePairs. + */ + private Vector params = new Vector(); + + // ----------------------------------------------------------- Constructors + + /** + * No-arg constructor. + * + * @since 1.0 + */ + public PostMethod() { + super(); + } + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 1.0 + */ + public PostMethod(String uri) { + super(uri); + } + + // ----------------------------------------------------- Instance Methods + + /** + * Returns "POST". + * + * @return "POST" + * + * @since 2.0 + */ + public String getName() { + return "POST"; + } + + + /** + * Returns true if there is a request body to be sent. + * + *

      This method must be overwritten by sub-classes that implement + * alternative request content input methods + *

      + * + * @return boolean + * + * @since 2.0beta1 + */ + protected boolean hasRequestContent() { + LOG.trace("enter PostMethod.hasRequestContent()"); + if (!this.params.isEmpty()) { + return true; + } else { + return super.hasRequestContent(); + } + } + + /** + * Clears request body. + * + *

      This method must be overwritten by sub-classes that implement + * alternative request content input methods

      + * + * @since 2.0beta1 + */ + protected void clearRequestBody() { + LOG.trace("enter PostMethod.clearRequestBody()"); + this.params.clear(); + super.clearRequestBody(); + } + + /** + * Generates a request entity from the post parameters, if present. Calls + * {@link EntityEnclosingMethod#generateRequestBody()} if parameters have not been set. + * + * @since 3.0 + */ + protected RequestEntity generateRequestEntity() { + if (!this.params.isEmpty()) { + // Use a ByteArrayRequestEntity instead of a StringRequestEntity. + // This is to avoid potential encoding issues. Form url encoded strings + // are ASCII by definition but the content type may not be. Treating the content + // as bytes allows us to keep the current charset without worrying about how + // this charset will effect the encoding of the form url encoded string. + String content = EncodingUtil.formUrlEncode(getParameters(), getRequestCharSet()); + ByteArrayRequestEntity entity = new ByteArrayRequestEntity( + EncodingUtil.getAsciiBytes(content), + FORM_URL_ENCODED_CONTENT_TYPE + ); + return entity; + } else { + return super.generateRequestEntity(); + } + } + + /** + * Sets the value of parameter with parameterName to parameterValue. This method + * does not preserve the initial insertion order. + * + * @param parameterName name of the parameter + * @param parameterValue value of the parameter + * + * @since 2.0 + */ + public void setParameter(String parameterName, String parameterValue) { + LOG.trace("enter PostMethod.setParameter(String, String)"); + + removeParameter(parameterName); + addParameter(parameterName, parameterValue); + } + + /** + * Gets the parameter of the specified name. If there exists more than one + * parameter with the name paramName, then only the first one is returned. + * + * @param paramName name of the parameter + * + * @return If a parameter exists with the name argument, the coresponding + * NameValuePair is returned. Otherwise null. + * + * @since 2.0 + * + */ + public NameValuePair getParameter(String paramName) { + LOG.trace("enter PostMethod.getParameter(String)"); + + if (paramName == null) { + return null; + } + + Iterator iter = this.params.iterator(); + + while (iter.hasNext()) { + NameValuePair parameter = (NameValuePair) iter.next(); + + if (paramName.equals(parameter.getName())) { + return parameter; + } + } + return null; + } + + /** + * Gets the parameters currently added to the PostMethod. If there are no + * parameters, a valid array is returned with zero elements. The returned + * array object contains an array of pointers to the internal data + * members. + * + * @return An array of the current parameters + * + * @since 2.0 + * + */ + public NameValuePair[] getParameters() { + LOG.trace("enter PostMethod.getParameters()"); + + int numPairs = this.params.size(); + Object[] objectArr = this.params.toArray(); + NameValuePair[] nvPairArr = new NameValuePair[numPairs]; + + for (int i = 0; i < numPairs; i++) { + nvPairArr[i] = (NameValuePair) objectArr[i]; + } + + return nvPairArr; + } + + /** + * Adds a new parameter to be used in the POST request body. + * + * @param paramName The parameter name to add. + * @param paramValue The parameter value to add. + * + * @throws IllegalArgumentException if either argument is null + * + * @since 1.0 + */ + public void addParameter(String paramName, String paramValue) + throws IllegalArgumentException { + LOG.trace("enter PostMethod.addParameter(String, String)"); + + if ((paramName == null) || (paramValue == null)) { + throw new IllegalArgumentException( + "Arguments to addParameter(String, String) cannot be null"); + } + super.clearRequestBody(); + this.params.add(new NameValuePair(paramName, paramValue)); + } + + /** + * Adds a new parameter to be used in the POST request body. + * + * @param param The parameter to add. + * + * @throws IllegalArgumentException if the argument is null or contains + * null values + * + * @since 2.0 + */ + public void addParameter(NameValuePair param) + throws IllegalArgumentException { + LOG.trace("enter PostMethod.addParameter(NameValuePair)"); + + if (param == null) { + throw new IllegalArgumentException("NameValuePair may not be null"); + } + addParameter(param.getName(), param.getValue()); + } + + /** + * Adds an array of parameters to be used in the POST request body. Logs a + * warning if the parameters argument is null. + * + * @param parameters The array of parameters to add. + * + * @since 2.0 + */ + public void addParameters(NameValuePair[] parameters) { + LOG.trace("enter PostMethod.addParameters(NameValuePair[])"); + + if (parameters == null) { + LOG.warn("Attempt to addParameters(null) ignored"); + } else { + super.clearRequestBody(); + for (int i = 0; i < parameters.length; i++) { + this.params.add(parameters[i]); + } + } + } + + /** + * Removes all parameters with the given paramName. If there is more than + * one parameter with the given paramName, all of them are removed. If + * there is just one, it is removed. If there are none, then the request + * is ignored. + * + * @param paramName The parameter name to remove. + * + * @return true if at least one parameter was removed + * + * @throws IllegalArgumentException When the parameter name passed is null + * + * @since 2.0 + */ + public boolean removeParameter(String paramName) + throws IllegalArgumentException { + LOG.trace("enter PostMethod.removeParameter(String)"); + + if (paramName == null) { + throw new IllegalArgumentException( + "Argument passed to removeParameter(String) cannot be null"); + } + boolean removed = false; + Iterator iter = this.params.iterator(); + + while (iter.hasNext()) { + NameValuePair pair = (NameValuePair) iter.next(); + + if (paramName.equals(pair.getName())) { + iter.remove(); + removed = true; + } + } + return removed; + } + + /** + * Removes all parameter with the given paramName and paramValue. If there + * is more than one parameter with the given paramName, only one is + * removed. If there are none, then the request is ignored. + * + * @param paramName The parameter name to remove. + * @param paramValue The parameter value to remove. + * + * @return true if a parameter was removed. + * + * @throws IllegalArgumentException when param name or value are null + * + * @since 2.0 + */ + public boolean removeParameter(String paramName, String paramValue) + throws IllegalArgumentException { + LOG.trace("enter PostMethod.removeParameter(String, String)"); + + if (paramName == null) { + throw new IllegalArgumentException("Parameter name may not be null"); + } + if (paramValue == null) { + throw new IllegalArgumentException("Parameter value may not be null"); + } + + Iterator iter = this.params.iterator(); + + while (iter.hasNext()) { + NameValuePair pair = (NameValuePair) iter.next(); + + if (paramName.equals(pair.getName()) + && paramValue.equals(pair.getValue())) { + iter.remove(); + return true; + } + } + + return false; + } + + /** + * Sets an array of parameters to be used in the POST request body + * + * @param parametersBody The array of parameters to add. + * + * @throws IllegalArgumentException when param parameters are null + * + * @since 2.0beta1 + */ + public void setRequestBody(NameValuePair[] parametersBody) + throws IllegalArgumentException { + LOG.trace("enter PostMethod.setRequestBody(NameValuePair[])"); + + if (parametersBody == null) { + throw new IllegalArgumentException("Array of parameters may not be null"); + } + clearRequestBody(); + addParameters(parametersBody); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PutMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PutMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PutMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,89 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/PutMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +/** + * Implements the HTTP PUT method. + *

      + * The HTTP PUT method is defined in section 9.6 of + * RFC2616: + *

      + * 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. + *
      + *

      + * + * @author Remy Maucherat + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author Jeff Dever + * + * @version $Revision: 1.1 $ + * @since 1.0 + */ +public class PutMethod extends EntityEnclosingMethod { + + // ----------------------------------------------------------- Constructors + + /** + * No-arg constructor. + * + * @since 1.0 + */ + public PutMethod() { + super(); + } + + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 1.0 + */ + public PutMethod(String uri) { + super(uri); + } + + // --------------------------------------------------------- Public Methods + + /** + * Return "PUT". + * @return "PUT" + * + * @since 2.0 + */ + public String getName() { + return "PUT"; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/RequestEntity.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/RequestEntity.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/RequestEntity.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,74 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/RequestEntity.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @since 3.0 + */ +public interface RequestEntity { + + /** + * Tests if {@link #writeRequest(OutputStream)} can be called more than once. + * + * @return true if the entity can be written to {@link OutputStream} more than once, + * false otherwise. + */ + boolean isRepeatable(); + + /** + * Writes the request entity to the given stream. + * @param out + * @throws IOException + */ + void writeRequest(OutputStream out) throws IOException; + + /** + * Gets the request entity's length. This method should return a non-negative value if the content + * length is known or a negative value if it is not. In the latter case the + * {@link org.apache.commons.httpclient.methods.EntityEnclosingMethod} will use chunk encoding to + * transmit the request entity. + * + * @return a non-negative value when content length is known or a negative value when content length + * is not known + */ + long getContentLength(); + + /** + * Gets the entity's content type. This content type will be used as the value for the + * "Content-Type" header. + * @return the entity's content type + * @see org.apache.commons.httpclient.HttpMethod#setRequestHeader(String, String) + */ + String getContentType(); + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/StringRequestEntity.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/StringRequestEntity.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/StringRequestEntity.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,182 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/StringRequestEntity.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + * [Additional notices, if required by prior licensing conditions] + * + */ +package org.apache.commons.httpclient.methods; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.commons.httpclient.HeaderElement; +import org.apache.commons.httpclient.NameValuePair; + +/** + * A RequestEntity that contains a String. + * + * @since 3.0 + */ +public class StringRequestEntity implements RequestEntity { + + /** The content */ + private byte[] content; + + /** The charset */ + private String charset; + + /** The content type (i.e. text/html; charset=EUC-JP). */ + private String contentType; + + /** + *

      Creates a new entity with the given content. This constructor + * will use the default platform charset to convert the content string + * and will provide no content type.

      + * + *

      This constructor may be deprecated or changed to use the + * default HTTP content charset (ISO-8859-1) in the release 3.1

      + * + *

      It is strongly recommended to use + * {@link #StringRequestEntity(String, String, String)} constructor + * instead.

      + * + * @see #StringRequestEntity(String, String, String) + * + * @param content The content to set. + */ + public StringRequestEntity(String content) { + super(); + if (content == null) { + throw new IllegalArgumentException("The content cannot be null"); + } + this.contentType = null; + this.charset = null; + this.content = content.getBytes(); + } + + /** + * Creates a new entity with the given content, content type, and charset. + * + * @param content The content to set. + * @param contentType The type of the content, or null. The value retured + * by {@link #getContentType()}. If this content type contains a charset and the charset + * parameter is null, the content's type charset will be used. + * @param charset The charset of the content, or null. Used to convert the + * content to bytes. If the content type does not contain a charset and charset is not null, + * then the charset will be appended to the content type. + */ + public StringRequestEntity(String content, String contentType, String charset) + throws UnsupportedEncodingException { + super(); + if (content == null) { + throw new IllegalArgumentException("The content cannot be null"); + } + + this.contentType = contentType; + this.charset = charset; + + // resolve the content type and the charset + if (contentType != null) { + HeaderElement[] values = HeaderElement.parseElements(contentType); + NameValuePair charsetPair = null; + for (int i = 0; i < values.length; i++) { + if ((charsetPair = values[i].getParameterByName("charset")) != null) { + // charset found + break; + } + } + if (charset == null && charsetPair != null) { + // use the charset from the content type + this.charset = charsetPair.getValue(); + } else if (charset != null && charsetPair == null) { + // append the charset to the content type + this.contentType = contentType + "; charset=" + charset; + } + } + if (this.charset != null) { + this.content = content.getBytes(this.charset); + } else { + this.content = content.getBytes(); + } + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() + */ + public String getContentType() { + return contentType; + } + + /** + * @return true + */ + public boolean isRepeatable() { + return true; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream) + */ + public void writeRequest(OutputStream out) throws IOException { + if (out == null) { + throw new IllegalArgumentException("Output stream may not be null"); + } + out.write(this.content); + out.flush(); + } + + /** + * @return The length of the content. + */ + public long getContentLength() { + return this.content.length; + } + + /** + * @return Returns the content. + */ + public String getContent() { + if (this.charset != null) { + try { + return new String(this.content, this.charset); + } catch (UnsupportedEncodingException e) { + return new String(this.content); + } + } else { + return new String(this.content); + } + } + + /** + * @return Returns the charset used to convert the content to bytes. null if + * no charset as been specified. + */ + public String getCharset() { + return charset; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/TraceMethod.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/TraceMethod.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/TraceMethod.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,107 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/TraceMethod.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods; + +import org.apache.commons.httpclient.HttpMethodBase; + +/** + * Implements the HTTP TRACE method. + *

      + * The HTTP TRACE method is defined in section 9.6 of + * RFC2616: + *

      + * 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. + *
      + *

      + * + * @author Sean C. Sullivan + * @author Mike Bowler + * @author Jeff Dever + * + * @version $Revision: 1.1 $ + * @since 2.0 + * + */ +public class TraceMethod extends HttpMethodBase { + + //~ Constructors + + /** + * Constructor specifying a URI. + * + * @param uri either an absolute or relative URI + * + * @since 2.0 + * + */ + public TraceMethod(String uri) { + super(uri); + setFollowRedirects(false); + } + + //~ Methods + + /** + * Returns "TRACE". + * + * @return "TRACE" + * + * @since 2.0 + * + */ + public String getName() { + return "TRACE"; + } + + /** + * Recycles the HTTP method so that it can be used again. + * Note that all of the instance variables will be reset + * once this method has been called. This method will also + * release the connection being used by this HTTP method. + * + * @see #releaseConnection() + * + * @since 2.0 + * + * @deprecated no longer supported and will be removed in the future + * version of HttpClient + */ + public void recycle() { + super.recycle(); + setFollowRedirects(false); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/package.html 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,11 @@ + + + + Package Documentation for org.apache.commons.httpclient.methods + + + Classes implementing {@link org.apache.commons.httpclient.HttpMethod} for the base HTTP methods. + + @since 1.0 + + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,86 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods.multipart; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * A PartSource that reads from a byte array. This class should be used when + * the data to post is already loaded into memory. + * + * @author Michael Becke + * + * @since 2.0 + */ +public class ByteArrayPartSource implements PartSource { + + /** Name of the source file. */ + private String fileName; + + /** Byte array of the source file. */ + private byte[] bytes; + + /** + * Constructor for ByteArrayPartSource. + * + * @param fileName the name of the file these bytes represent + * @param bytes the content of this part + */ + public ByteArrayPartSource(String fileName, byte[] bytes) { + + this.fileName = fileName; + this.bytes = bytes; + + } + + /** + * @see PartSource#getLength() + */ + public long getLength() { + return bytes.length; + } + + /** + * @see PartSource#getFileName() + */ + public String getFileName() { + return fileName; + } + + /** + * @see PartSource#createInputStream() + */ + public InputStream createInputStream() throws IOException { + return new ByteArrayInputStream(bytes); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePart.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePart.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePart.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,251 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePart.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods.multipart; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class implements a part of a Multipart post object that + * consists of a file. + * + * @author Matthew Albright + * @author Jeff Dever + * @author Adrian Sutton + * @author Michael Becke + * @author Mark Diggory + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @since 2.0 + * + */ +public class FilePart extends PartBase { + + /** Default content encoding of file attachments. */ + public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; + + /** Default charset of file attachments. */ + public static final String DEFAULT_CHARSET = "ISO-8859-1"; + + /** Default transfer encoding of file attachments. */ + public static final String DEFAULT_TRANSFER_ENCODING = "binary"; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(FilePart.class); + + /** Attachment's file name */ + protected static final String FILE_NAME = "; filename="; + + /** Attachment's file name as a byte array */ + private static final byte[] FILE_NAME_BYTES = + EncodingUtil.getAsciiBytes(FILE_NAME); + + /** Source of the file part. */ + private PartSource source; + + /** + * FilePart Constructor. + * + * @param name the name for this part + * @param partSource the source for this part + * @param contentType the content type for this part, if null the + * {@link #DEFAULT_CONTENT_TYPE default} is used + * @param charset the charset encoding for this part, if null the + * {@link #DEFAULT_CHARSET default} is used + */ + public FilePart(String name, PartSource partSource, String contentType, String charset) { + + super( + name, + contentType == null ? DEFAULT_CONTENT_TYPE : contentType, + charset == null ? "ISO-8859-1" : charset, + DEFAULT_TRANSFER_ENCODING + ); + + if (partSource == null) { + throw new IllegalArgumentException("Source may not be null"); + } + this.source = partSource; + } + + /** + * FilePart Constructor. + * + * @param name the name for this part + * @param partSource the source for this part + */ + public FilePart(String name, PartSource partSource) { + this(name, partSource, null, null); + } + + /** + * FilePart Constructor. + * + * @param name the name of the file part + * @param file the file to post + * + * @throws FileNotFoundException if the file is not a normal + * file or if it is not readable. + */ + public FilePart(String name, File file) + throws FileNotFoundException { + this(name, new FilePartSource(file), null, null); + } + + /** + * FilePart Constructor. + * + * @param name the name of the file part + * @param file the file to post + * @param contentType the content type for this part, if null the + * {@link #DEFAULT_CONTENT_TYPE default} is used + * @param charset the charset encoding for this part, if null the + * {@link #DEFAULT_CHARSET default} is used + * + * @throws FileNotFoundException if the file is not a normal + * file or if it is not readable. + */ + public FilePart(String name, File file, String contentType, String charset) + throws FileNotFoundException { + this(name, new FilePartSource(file), contentType, charset); + } + + /** + * FilePart Constructor. + * + * @param name the name of the file part + * @param fileName the file name + * @param file the file to post + * + * @throws FileNotFoundException if the file is not a normal + * file or if it is not readable. + */ + public FilePart(String name, String fileName, File file) + throws FileNotFoundException { + this(name, new FilePartSource(fileName, file), null, null); + } + + /** + * FilePart Constructor. + * + * @param name the name of the file part + * @param fileName the file name + * @param file the file to post + * @param contentType the content type for this part, if null the + * {@link #DEFAULT_CONTENT_TYPE default} is used + * @param charset the charset encoding for this part, if null the + * {@link #DEFAULT_CHARSET default} is used + * + * @throws FileNotFoundException if the file is not a normal + * file or if it is not readable. + */ + public FilePart(String name, String fileName, File file, String contentType, String charset) + throws FileNotFoundException { + this(name, new FilePartSource(fileName, file), contentType, charset); + } + + /** + * Write the disposition header to the output stream + * @param out The output stream + * @throws IOException If an IO problem occurs + * @see Part#sendDispositionHeader(OutputStream) + */ + protected void sendDispositionHeader(OutputStream out) + throws IOException { + LOG.trace("enter sendDispositionHeader(OutputStream out)"); + super.sendDispositionHeader(out); + String filename = this.source.getFileName(); + if (filename != null) { + out.write(FILE_NAME_BYTES); + out.write(QUOTE_BYTES); + out.write(EncodingUtil.getAsciiBytes(filename)); + out.write(QUOTE_BYTES); + } + } + + /** + * Write the data in "source" to the specified stream. + * @param out The output stream. + * @throws IOException if an IO problem occurs. + * @see org.apache.commons.httpclient.methods.multipart.Part#sendData(OutputStream) + */ + protected void sendData(OutputStream out) throws IOException { + LOG.trace("enter sendData(OutputStream out)"); + if (lengthOfData() == 0) { + + // this file contains no data, so there is nothing to send. + // we don't want to create a zero length buffer as this will + // cause an infinite loop when reading. + LOG.debug("No data to send."); + return; + } + + byte[] tmp = new byte[4096]; + InputStream instream = source.createInputStream(); + try { + int len; + while ((len = instream.read(tmp)) >= 0) { + out.write(tmp, 0, len); + } + } finally { + // we're done with the stream, close it + instream.close(); + } + } + + /** + * Returns the source of the file part. + * + * @return The source. + */ + protected PartSource getSource() { + LOG.trace("enter getSource()"); + return this.source; + } + + /** + * Return the length of the data. + * @return The length. + * @throws IOException if an IO problem occurs + * @see org.apache.commons.httpclient.methods.multipart.Part#lengthOfData() + */ + protected long lengthOfData() throws IOException { + LOG.trace("enter lengthOfData()"); + return source.getLength(); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePartSource.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePartSource.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePartSource.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,130 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/FilePartSource.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods.multipart; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +/** + * A PartSource that reads from a File. + * + * @author Michael Becke + * @author Mark Diggory + * @author Mike Bowler + * + * @since 2.0 + */ +public class FilePartSource implements PartSource { + + /** File part file. */ + private File file = null; + + /** File part file name. */ + private String fileName = null; + + /** + * Constructor for FilePartSource. + * + * @param file the FilePart source File. + * + * @throws FileNotFoundException if the file does not exist or + * cannot be read + */ + public FilePartSource(File file) throws FileNotFoundException { + this.file = file; + if (file != null) { + if (!file.isFile()) { + throw new FileNotFoundException("File is not a normal file."); + } + if (!file.canRead()) { + throw new FileNotFoundException("File is not readable."); + } + this.fileName = file.getName(); + } + } + + /** + * Constructor for FilePartSource. + * + * @param fileName the file name of the FilePart + * @param file the source File for the FilePart + * + * @throws FileNotFoundException if the file does not exist or + * cannot be read + */ + public FilePartSource(String fileName, File file) + throws FileNotFoundException { + this(file); + if (fileName != null) { + this.fileName = fileName; + } + } + + /** + * Return the length of the file + * @return the length of the file. + * @see PartSource#getLength() + */ + public long getLength() { + if (this.file != null) { + return this.file.length(); + } else { + return 0; + } + } + + /** + * Return the current filename + * @return the filename. + * @see PartSource#getFileName() + */ + public String getFileName() { + return (fileName == null) ? "noname" : fileName; + } + + /** + * Return a new {@link FileInputStream} for the current filename. + * @return the new input stream. + * @throws IOException If an IO problem occurs. + * @see PartSource#createInputStream() + */ + public InputStream createInputStream() throws IOException { + if (this.file != null) { + return new FileInputStream(this.file); + } else { + return new ByteArrayInputStream(new byte[] {}); + } + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/MultipartRequestEntity.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/MultipartRequestEntity.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/MultipartRequestEntity.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,188 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/MultipartRequestEntity.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ +package org.apache.commons.httpclient.methods.multipart; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Random; + +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Implements a request entity suitable for an HTTP multipart POST method. + *

      + * The HTTP multipart POST method is defined in section 3.3 of + * RFC1867: + *

      + * The media-type multipart/form-data follows the rules of all multipart + * MIME data streams as outlined in RFC 1521. The multipart/form-data contains + * a series of parts. Each part is expected to contain a content-disposition + * header where the value is "form-data" and a name attribute specifies + * the field name within the form, e.g., 'content-disposition: form-data; + * name="xxxxx"', where xxxxx is the field name corresponding to that field. + * Field names originally in non-ASCII character sets may be encoded using + * the method outlined in RFC 1522. + *
      + *

      + *

      This entity is designed to be used in conjunction with the + * {@link org.apache.commons.httpclient.methods.PostMethod post method} to provide + * multipart posts. Example usage:

      + * + * File f = new File("/path/fileToUpload.txt"); + * PostMethod filePost = new PostMethod("http://host/some_path"); + * Part[] parts = { + * new StringPart("param_name", "value"), + * new FilePart(f.getName(), f) + * }; + * filePost.setRequestEntity( + * new MultipartRequestEntity(parts, filePost.getParams()) + * ); + * HttpClient client = new HttpClient(); + * int status = client.executeMethod(filePost); + * + * + * @since 3.0 + */ +public class MultipartRequestEntity implements RequestEntity { + + private static final Log log = LogFactory.getLog(MultipartRequestEntity.class); + + /** The Content-Type for multipart/form-data. */ + private static final String MULTIPART_FORM_CONTENT_TYPE = "multipart/form-data"; + + /** + * The pool of ASCII chars to be used for generating a multipart boundary. + */ + private static byte[] MULTIPART_CHARS = EncodingUtil.getAsciiBytes( + "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + /** + * Generates a random multipart boundary string. + * @return + */ + private static byte[] generateMultipartBoundary() { + Random rand = new Random(); + byte[] bytes = new byte[rand.nextInt(11) + 30]; // a random size from 30 to 40 + for (int i = 0; i < bytes.length; i++) { + bytes[i] = MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]; + } + return bytes; + } + + /** The MIME parts as set by the constructor */ + protected Part[] parts; + + private byte[] multipartBoundary; + + private HttpMethodParams params; + + /** + * Creates a new multipart entity containing the given parts. + * @param parts The parts to include. + * @param params The params of the HttpMethod using this entity. + */ + public MultipartRequestEntity(Part[] parts, HttpMethodParams params) { + if (parts == null) { + throw new IllegalArgumentException("parts cannot be null"); + } + if (params == null) { + throw new IllegalArgumentException("params cannot be null"); + } + this.parts = parts; + this.params = params; + } + + /** + * Returns the MIME boundary string that is used to demarcate boundaries of + * this part. The first call to this method will implicitly create a new + * boundary string. To create a boundary string first the + * HttpMethodParams.MULTIPART_BOUNDARY parameter is considered. Otherwise + * a random one is generated. + * + * @return The boundary string of this entity in ASCII encoding. + */ + protected byte[] getMultipartBoundary() { + if (multipartBoundary == null) { + String temp = (String) params.getParameter(HttpMethodParams.MULTIPART_BOUNDARY); + if (temp != null) { + multipartBoundary = EncodingUtil.getAsciiBytes(temp); + } else { + multipartBoundary = generateMultipartBoundary(); + } + } + return multipartBoundary; + } + + /** + * Returns true if all parts are repeatable, false otherwise. + * @see org.apache.commons.httpclient.methods.RequestEntity#isRepeatable() + */ + public boolean isRepeatable() { + for (int i = 0; i < parts.length; i++) { + if (!parts[i].isRepeatable()) { + return false; + } + } + return true; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#writeRequest(java.io.OutputStream) + */ + public void writeRequest(OutputStream out) throws IOException { + Part.sendParts(out, parts, getMultipartBoundary()); + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#getContentLength() + */ + public long getContentLength() { + try { + return Part.getLengthOfParts(parts, getMultipartBoundary()); + } catch (Exception e) { + log.error("An exception occurred while getting the length of the parts", e); + return 0; + } + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() + */ + public String getContentType() { + StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE); + buffer.append("; boundary="); + buffer.append(EncodingUtil.getAsciiString(getMultipartBoundary())); + return buffer.toString(); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/Part.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/Part.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/Part.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,437 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/Part.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods.multipart; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Abstract class for one Part of a multipart post object. + * + * @author Matthew Albright + * @author Jeff Dever + * @author Adrian Sutton + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @since 2.0 + */ +public abstract class Part { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(Part.class); + + /** + * The boundary + * @deprecated use {@link org.apache.commons.httpclient.params.HttpMethodParams#MULTIPART_BOUNDARY} + */ + protected static final String BOUNDARY = "----------------314159265358979323846"; + + /** + * The boundary as a byte array. + * @deprecated + */ + protected static final byte[] BOUNDARY_BYTES = EncodingUtil.getAsciiBytes(BOUNDARY); + + /** + * The default boundary to be used if {@link #setBoundaryBytes(byte[])) has not + * been called. + */ + private static final byte[] DEFAULT_BOUNDARY_BYTES = BOUNDARY_BYTES; + + /** Carriage return/linefeed */ + protected static final String CRLF = "\r\n"; + + /** Carriage return/linefeed as a byte array */ + protected static final byte[] CRLF_BYTES = EncodingUtil.getAsciiBytes(CRLF); + + /** Content dispostion characters */ + protected static final String QUOTE = "\""; + + /** Content dispostion as a byte array */ + protected static final byte[] QUOTE_BYTES = + EncodingUtil.getAsciiBytes(QUOTE); + + /** Extra characters */ + protected static final String EXTRA = "--"; + + /** Extra characters as a byte array */ + protected static final byte[] EXTRA_BYTES = + EncodingUtil.getAsciiBytes(EXTRA); + + /** Content dispostion characters */ + protected static final String CONTENT_DISPOSITION = "Content-Disposition: form-data; name="; + + /** Content dispostion as a byte array */ + protected static final byte[] CONTENT_DISPOSITION_BYTES = + EncodingUtil.getAsciiBytes(CONTENT_DISPOSITION); + + /** Content type header */ + protected static final String CONTENT_TYPE = "Content-Type: "; + + /** Content type header as a byte array */ + protected static final byte[] CONTENT_TYPE_BYTES = + EncodingUtil.getAsciiBytes(CONTENT_TYPE); + + /** Content charset */ + protected static final String CHARSET = "; charset="; + + /** Content charset as a byte array */ + protected static final byte[] CHARSET_BYTES = + EncodingUtil.getAsciiBytes(CHARSET); + + /** Content type header */ + protected static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding: "; + + /** Content type header as a byte array */ + protected static final byte[] CONTENT_TRANSFER_ENCODING_BYTES = + EncodingUtil.getAsciiBytes(CONTENT_TRANSFER_ENCODING); + + /** + * Return the boundary string. + * @return the boundary string + * @deprecated uses a constant string. Rather use {@link #getPartBoundary} + */ + public static String getBoundary() { + return BOUNDARY; + } + + /** + * The ASCII bytes to use as the multipart boundary. + */ + private byte[] boundaryBytes; + + /** + * Return the name of this part. + * @return The name. + */ + public abstract String getName(); + + /** + * Returns the content type of this part. + * @return the content type, or null to exclude the content type header + */ + public abstract String getContentType(); + + /** + * Return the character encoding of this part. + * @return the character encoding, or null to exclude the character + * encoding header + */ + public abstract String getCharSet(); + + /** + * Return the transfer encoding of this part. + * @return the transfer encoding, or null to exclude the transfer encoding header + */ + public abstract String getTransferEncoding(); + + /** + * Gets the part boundary to be used. + * @return the part boundary as an array of bytes. + * + * @since 3.0 + */ + protected byte[] getPartBoundary() { + if (boundaryBytes == null) { + // custom boundary bytes have not been set, use the default. + return DEFAULT_BOUNDARY_BYTES; + } else { + return boundaryBytes; + } + } + + /** + * Sets the part boundary. Only meant to be used by + * {@link Part#sendParts(OutputStream, Part[], byte[])} + * and {@link Part#getLengthOfParts(Part[], byte[])} + * @param boundaryBytes An array of ASCII bytes. + * @since 3.0 + */ + void setPartBoundary(byte[] boundaryBytes) { + this.boundaryBytes = boundaryBytes; + } + + /** + * Tests if this part can be sent more than once. + * @return true if {@link #sendData(OutputStream)} can be successfully called + * more than once. + * @since 3.0 + */ + public boolean isRepeatable() { + return true; + } + + /** + * Write the start to the specified output stream + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + protected void sendStart(OutputStream out) throws IOException { + LOG.trace("enter sendStart(OutputStream out)"); + out.write(EXTRA_BYTES); + out.write(getPartBoundary()); + out.write(CRLF_BYTES); + } + + /** + * Write the content disposition header to the specified output stream + * + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + protected void sendDispositionHeader(OutputStream out) throws IOException { + LOG.trace("enter sendDispositionHeader(OutputStream out)"); + out.write(CONTENT_DISPOSITION_BYTES); + out.write(QUOTE_BYTES); + out.write(EncodingUtil.getAsciiBytes(getName())); + out.write(QUOTE_BYTES); + } + + /** + * Write the content type header to the specified output stream + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + protected void sendContentTypeHeader(OutputStream out) throws IOException { + LOG.trace("enter sendContentTypeHeader(OutputStream out)"); + String contentType = getContentType(); + if (contentType != null) { + out.write(CRLF_BYTES); + out.write(CONTENT_TYPE_BYTES); + out.write(EncodingUtil.getAsciiBytes(contentType)); + String charSet = getCharSet(); + if (charSet != null) { + out.write(CHARSET_BYTES); + out.write(EncodingUtil.getAsciiBytes(charSet)); + } + } + } + + /** + * Write the content transfer encoding header to the specified + * output stream + * + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + protected void sendTransferEncodingHeader(OutputStream out) throws IOException { + LOG.trace("enter sendTransferEncodingHeader(OutputStream out)"); + String transferEncoding = getTransferEncoding(); + if (transferEncoding != null) { + out.write(CRLF_BYTES); + out.write(CONTENT_TRANSFER_ENCODING_BYTES); + out.write(EncodingUtil.getAsciiBytes(transferEncoding)); + } + } + + /** + * Write the end of the header to the output stream + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + protected void sendEndOfHeader(OutputStream out) throws IOException { + LOG.trace("enter sendEndOfHeader(OutputStream out)"); + out.write(CRLF_BYTES); + out.write(CRLF_BYTES); + } + + /** + * Write the data to the specified output stream + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + protected abstract void sendData(OutputStream out) throws IOException; + + /** + * Return the length of the main content + * + * @return long The length. + * @throws IOException If an IO problem occurs + */ + protected abstract long lengthOfData() throws IOException; + + /** + * Write the end data to the output stream. + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + protected void sendEnd(OutputStream out) throws IOException { + LOG.trace("enter sendEnd(OutputStream out)"); + out.write(CRLF_BYTES); + } + + /** + * Write all the data to the output stream. + * If you override this method make sure to override + * #length() as well + * + * @param out The output stream + * @throws IOException If an IO problem occurs. + */ + public void send(OutputStream out) throws IOException { + LOG.trace("enter send(OutputStream out)"); + sendStart(out); + sendDispositionHeader(out); + sendContentTypeHeader(out); + sendTransferEncodingHeader(out); + sendEndOfHeader(out); + sendData(out); + sendEnd(out); + } + + + /** + * Return the full length of all the data. + * If you override this method make sure to override + * #send(OutputStream) as well + * + * @return long The length. + * @throws IOException If an IO problem occurs + */ + public long length() throws IOException { + LOG.trace("enter length()"); + if (lengthOfData() < 0) { + return -1; + } + ByteArrayOutputStream overhead = new ByteArrayOutputStream(); + sendStart(overhead); + sendDispositionHeader(overhead); + sendContentTypeHeader(overhead); + sendTransferEncodingHeader(overhead); + sendEndOfHeader(overhead); + sendEnd(overhead); + return overhead.size() + lengthOfData(); + } + + /** + * Return a string representation of this object. + * @return A string representation of this object. + * @see java.lang.Object#toString() + */ + public String toString() { + return this.getName(); + } + + /** + * Write all parts and the last boundary to the specified output stream. + * + * @param out The stream to write to. + * @param parts The parts to write. + * + * @throws IOException If an I/O error occurs while writing the parts. + */ + public static void sendParts(OutputStream out, final Part[] parts) + throws IOException { + sendParts(out, parts, DEFAULT_BOUNDARY_BYTES); + } + + /** + * Write all parts and the last boundary to the specified output stream. + * + * @param out The stream to write to. + * @param parts The parts to write. + * @param partBoundary The ASCII bytes to use as the part boundary. + * + * @throws IOException If an I/O error occurs while writing the parts. + * + * @since 3.0 + */ + public static void sendParts(OutputStream out, Part[] parts, byte[] partBoundary) + throws IOException { + + if (parts == null) { + throw new IllegalArgumentException("Parts may not be null"); + } + if (partBoundary == null || partBoundary.length == 0) { + throw new IllegalArgumentException("partBoundary may not be empty"); + } + for (int i = 0; i < parts.length; i++) { + // set the part boundary before the part is sent + parts[i].setPartBoundary(partBoundary); + parts[i].send(out); + } + out.write(EXTRA_BYTES); + out.write(partBoundary); + out.write(EXTRA_BYTES); + out.write(CRLF_BYTES); + } + + /** + * Return the total sum of all parts and that of the last boundary + * + * @param parts The parts. + * @return The total length + * + * @throws IOException If an I/O error occurs while writing the parts. + */ + public static long getLengthOfParts(Part[] parts) + throws IOException { + return getLengthOfParts(parts, DEFAULT_BOUNDARY_BYTES); + } + + /** + * Gets the length of the multipart message including the given parts. + * + * @param parts The parts. + * @param partBoundary The ASCII bytes to use as the part boundary. + * @return The total length + * + * @throws IOException If an I/O error occurs while writing the parts. + * + * @since 3.0 + */ + public static long getLengthOfParts(Part[] parts, byte[] partBoundary) throws IOException { + LOG.trace("getLengthOfParts(Parts[])"); + if (parts == null) { + throw new IllegalArgumentException("Parts may not be null"); + } + long total = 0; + for (int i = 0; i < parts.length; i++) { + // set the part boundary before we calculate the part's length + parts[i].setPartBoundary(partBoundary); + long l = parts[i].length(); + if (l < 0) { + return -1; + } + total += l; + } + total += EXTRA_BYTES.length; + total += partBoundary.length; + total += EXTRA_BYTES.length; + total += CRLF_BYTES.length; + return total; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartBase.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartBase.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartBase.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,145 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartBase.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods.multipart; + + +/** + * Provides setters and getters for the basic Part properties. + * + * @author Michael Becke + */ +public abstract class PartBase extends Part { + + /** Name of the file part. */ + private String name; + + /** Content type of the file part. */ + private String contentType; + + /** Content encoding of the file part. */ + private String charSet; + + /** The transfer encoding. */ + private String transferEncoding; + + /** + * Constructor. + * + * @param name The name of the part + * @param contentType The content type, or null + * @param charSet The character encoding, or null + * @param transferEncoding The transfer encoding, or null + */ + public PartBase(String name, String contentType, String charSet, String transferEncoding) { + + if (name == null) { + throw new IllegalArgumentException("Name must not be null"); + } + this.name = name; + this.contentType = contentType; + this.charSet = charSet; + this.transferEncoding = transferEncoding; + } + + /** + * Returns the name. + * @return The name. + * @see org.apache.commons.httpclient.methods.multipart.Part#getName() + */ + public String getName() { + return this.name; + } + + /** + * Returns the content type of this part. + * @return String The name. + */ + public String getContentType() { + return this.contentType; + } + + /** + * Return the character encoding of this part. + * @return String The name. + */ + public String getCharSet() { + return this.charSet; + } + + /** + * Returns the transfer encoding of this part. + * @return String The name. + */ + public String getTransferEncoding() { + return transferEncoding; + } + + /** + * Sets the character encoding. + * + * @param charSet the character encoding, or null to exclude the character + * encoding header + */ + public void setCharSet(String charSet) { + this.charSet = charSet; + } + + /** + * Sets the content type. + * + * @param contentType the content type, or null to exclude the content type header + */ + public void setContentType(String contentType) { + this.contentType = contentType; + } + + /** + * Sets the part name. + * + * @param name + */ + public void setName(String name) { + if (name == null) { + throw new IllegalArgumentException("Name must not be null"); + } + this.name = name; + } + + /** + * Sets the transfer encoding. + * + * @param transferEncoding the transfer encoding, or null to exclude the + * transfer encoding header + */ + public void setTransferEncoding(String transferEncoding) { + this.transferEncoding = transferEncoding; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartSource.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartSource.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartSource.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,71 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/PartSource.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods.multipart; + +import java.io.IOException; +import java.io.InputStream; + +/** + * An interface for providing access to data when posting MultiPart messages. + * + * @see FilePart + * + * @author Michael Becke + * + * @since 2.0 + */ +public interface PartSource { + + /** + * Gets the number of bytes contained in this source. + * + * @return a value >= 0 + */ + long getLength(); + + /** + * Gets the name of the file this source represents. + * + * @return the fileName used for posting a MultiPart file part + */ + String getFileName(); + + /** + * Gets a new InputStream for reading this source. This method can be + * called more than once and should therefore return a new stream every + * time. + * + * @return a new InputStream + * + * @throws IOException if an error occurs when creating the InputStream + */ + InputStream createInputStream() throws IOException; + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/StringPart.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/StringPart.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/StringPart.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,147 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/StringPart.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.methods.multipart; + +import java.io.OutputStream; +import java.io.IOException; + +import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Simple string parameter for a multipart post + * + * @author Matthew Albright + * @author Jeff Dever + * @author Mike Bowler + * @author Oleg Kalnichevski + * + * @since 2.0 + */ +public class StringPart extends PartBase { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(StringPart.class); + + /** Default content encoding of string parameters. */ + public static final String DEFAULT_CONTENT_TYPE = "text/plain"; + + /** Default charset of string parameters*/ + public static final String DEFAULT_CHARSET = "US-ASCII"; + + /** Default transfer encoding of string parameters*/ + public static final String DEFAULT_TRANSFER_ENCODING = "8bit"; + + /** Contents of this StringPart. */ + private byte[] content; + + /** The String value of this part. */ + private String value; + + /** + * Constructor. + * + * @param name The name of the part + * @param value the string to post + * @param charset the charset to be used to encode the string, if null + * the {@link #DEFAULT_CHARSET default} is used + */ + public StringPart(String name, String value, String charset) { + + super( + name, + DEFAULT_CONTENT_TYPE, + charset == null ? DEFAULT_CHARSET : charset, + DEFAULT_TRANSFER_ENCODING + ); + if (value == null) { + throw new IllegalArgumentException("Value may not be null"); + } + if (value.indexOf(0) != -1) { + // See RFC 2048, 2.8. "8bit Data" + throw new IllegalArgumentException("NULs may not be present in string parts"); + } + this.value = value; + } + + /** + * Constructor. + * + * @param name The name of the part + * @param value the string to post + */ + public StringPart(String name, String value) { + this(name, value, null); + } + + /** + * Gets the content in bytes. Bytes are lazily created to allow the charset to be changed + * after the part is created. + * + * @return the content in bytes + */ + private byte[] getContent() { + if (content == null) { + content = EncodingUtil.getBytes(value, getCharSet()); + } + return content; + } + + /** + * Writes the data to the given OutputStream. + * @param out the OutputStream to write to + * @throws IOException if there is a write error + */ + protected void sendData(OutputStream out) throws IOException { + LOG.trace("enter sendData(OutputStream)"); + out.write(getContent()); + } + + /** + * Return the length of the data. + * @return The length of the data. + * @throws IOException If an IO problem occurs + * @see org.apache.commons.httpclient.methods.multipart.Part#lengthOfData() + */ + protected long lengthOfData() throws IOException { + LOG.trace("enter lengthOfData()"); + return getContent().length; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.multipart.BasePart#setCharSet(java.lang.String) + */ + public void setCharSet(String charSet) { + super.setCharSet(charSet); + this.content = null; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/methods/multipart/package.html 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,11 @@ + + + + Package Documentation for org.apache.commons.httpclient.methods.multipart + + + Provides Multipart support classes for the {@link org.apache.commons.httpclient.methods.MultipartPostMethod}. + + @since 2.0 + + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParams.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParams.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParams.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,253 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParams.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class represents a collection of HTTP protocol parameters. Protocol parameters + * may be linked together to form a hierarchy. If a particular parameter value has not been + * explicitly defined in the collection itself, its value will be drawn from the parent + * collection of parameters. + * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * + * @since 3.0 + */ +public class DefaultHttpParams implements HttpParams, Serializable, Cloneable { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(DefaultHttpParams.class); + + /** HttpParams class factory. */ + private static HttpParamsFactory httpParamsFactory = new DefaultHttpParamsFactory(); + + /** + * Gets the default HttpParams to be used. + * + * @return the value returned from HttpParamsFactory#getDefaultParams() + * + * @see HttpParamsFactory#getDefaultParams() + */ + public static HttpParams getDefaultParams() { + return httpParamsFactory.getDefaultParams(); + } + + /** + * Sets the factory that will provide the default HttpParams. + * + * @param httpParamsFactory an instance of HttpParamsFactory + * + * @see #getDefaultParams() + */ + public static void setHttpParamsFactory(HttpParamsFactory httpParamsFactory) { + if (httpParamsFactory == null) { + throw new IllegalArgumentException("httpParamsFactory may not be null"); + } + DefaultHttpParams.httpParamsFactory = httpParamsFactory; + } + + /** The set of default values to defer to */ + private HttpParams defaults = null; + + /** Hash map of HTTP parameters that this collection contains */ + private HashMap parameters = null; + + /** + * Creates a new collection of parameters with the given parent. + * The collection will defer to its parent for a default value + * if a particular parameter is not explicitly set in the collection + * itself. + * + * @param defaults the parent collection to defer to, if a parameter + * is not explictly set in the collection itself. + */ + public DefaultHttpParams(final HttpParams defaults) { + super(); + this.defaults = defaults; + } + + /** + * Creates a new collection of parameters with the collection returned + * by {@link #getDefaultParams()} as a parent. The collection will defer + * to its parent for a default value if a particular parameter is not + * explicitly set in the collection itself. + * + * @see #getDefaultParams() + */ + public DefaultHttpParams() { + this(getDefaultParams()); + } + + public synchronized HttpParams getDefaults() { + return this.defaults; + } + + public synchronized void setDefaults(final HttpParams params) { + this.defaults = params; + } + + public synchronized Object getParameter(final String name) { + // See if the parameter has been explicitly defined + Object param = null; + if (this.parameters != null) { + param = this.parameters.get(name); + } + if (param != null) { + // If so, return + return param; + } else { + // If not, see if defaults are available + if (this.defaults != null) { + // Return default parameter value + return this.defaults.getParameter(name); + } else { + // Otherwise, return null + return null; + } + } + } + + public synchronized void setParameter(final String name, final Object value) { + if (this.parameters == null) { + this.parameters = new HashMap(); + } + this.parameters.put(name, value); + if (LOG.isDebugEnabled()) { + LOG.debug("Set parameter " + name + " = " + value); + } + } + + /** + * Assigns the value to all the parameter with the given names + * + * @param names array of parameter name + * @param value parameter value + */ + public synchronized void setParameters(final String[] names, final Object value) { + for (int i = 0; i < names.length; i++) { + setParameter(names[i], value); + } + } + + public long getLongParameter(final String name, long defaultValue) { + Object param = getParameter(name); + if (param == null) { + return defaultValue; + } + return ((Long)param).longValue(); + } + + public void setLongParameter(final String name, long value) { + setParameter(name, new Long(value)); + } + + public int getIntParameter(final String name, int defaultValue) { + Object param = getParameter(name); + if (param == null) { + return defaultValue; + } + return ((Integer)param).intValue(); + } + + public void setIntParameter(final String name, int value) { + setParameter(name, new Integer(value)); + } + + public double getDoubleParameter(final String name, double defaultValue) { + Object param = getParameter(name); + if (param == null) { + return defaultValue; + } + return ((Double)param).doubleValue(); + } + + public void setDoubleParameter(final String name, double value) { + setParameter(name, new Double(value)); + } + + public boolean getBooleanParameter(final String name, boolean defaultValue) { + Object param = getParameter(name); + if (param == null) { + return defaultValue; + } + return ((Boolean)param).booleanValue(); + } + + public void setBooleanParameter(final String name, boolean value) { + setParameter(name, new Boolean(value)); + } + + public boolean isParameterSet(final String name) { + return getParameter(name) != null; + } + + public boolean isParameterSetLocally(final String name) { + return this.parameters != null && this.parameters.get(name) != null; + } + + public boolean isParameterTrue(final String name) { + return getBooleanParameter(name, false); + } + + public boolean isParameterFalse(final String name) { + return !getBooleanParameter(name, false); + } + + /** + * Removes all parameters from this collection. + */ + public void clear() { + this.parameters = null; + } + + /** + * Clones this collection of parameters. Please note that paramter values + * themselves are not cloned. + * + * @see java.io.Serializable + * @see java.lang.Object#clone() + */ + public Object clone() throws CloneNotSupportedException + { + DefaultHttpParams clone = (DefaultHttpParams)super.clone(); + if (this.parameters != null) { + clone.parameters = (HashMap)this.parameters.clone(); + } + clone.setDefaults(this.defaults); + return clone; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParamsFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParamsFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParamsFactory.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,144 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/DefaultHttpParamsFactory.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; +import org.apache.commons.httpclient.HttpVersion; +import org.apache.commons.httpclient.SimpleHttpConnectionManager; +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.httpclient.util.DateUtil; + +/** + * @since 3.0 + */ +public class DefaultHttpParamsFactory implements HttpParamsFactory { + + private HttpParams httpParams; + + /** + * + */ + public DefaultHttpParamsFactory() { + super(); + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.params.HttpParamsFactory#getDefaultParams() + */ + public synchronized HttpParams getDefaultParams() { + if (httpParams == null) { + httpParams = createParams(); + } + + return httpParams; + } + + protected HttpParams createParams() { + HttpClientParams params = new HttpClientParams(null); + + params.setParameter(HttpMethodParams.USER_AGENT, "Jakarta Commons-HttpClient/3.0"); + params.setVersion(HttpVersion.HTTP_1_1); + params.setConnectionManagerClass(SimpleHttpConnectionManager.class); + params.setCookiePolicy(CookiePolicy.RFC_2109); + params.setHttpElementCharset("US-ASCII"); + params.setContentCharset("ISO-8859-1"); + params.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); + + ArrayList datePatterns = new ArrayList(); + datePatterns.addAll( + Arrays.asList( + new String[] { + DateUtil.PATTERN_RFC1123, + DateUtil.PATTERN_RFC1036, + DateUtil.PATTERN_ASCTIME, + "EEE, dd-MMM-yyyy HH:mm:ss z", + "EEE, dd-MMM-yyyy HH-mm-ss z", + "EEE, dd MMM yy HH:mm:ss z", + "EEE dd-MMM-yyyy HH:mm:ss z", + "EEE dd MMM yyyy HH:mm:ss z", + "EEE dd-MMM-yyyy HH-mm-ss z", + "EEE dd-MMM-yy HH:mm:ss z", + "EEE dd MMM yy HH:mm:ss z", + "EEE,dd-MMM-yy HH:mm:ss z", + "EEE,dd-MMM-yyyy HH:mm:ss z", + "EEE, dd-MM-yyyy HH:mm:ss z", + } + ) + ); + params.setParameter(HttpMethodParams.DATE_PATTERNS, datePatterns); + + // TODO: To be removed. Provided for backward compatibility + String agent = null; + try { + agent = System.getProperty("httpclient.useragent"); + } catch (SecurityException ignore) { + } + if (agent != null) { + params.setParameter(HttpMethodParams.USER_AGENT, agent); + } + + // TODO: To be removed. Provided for backward compatibility + String preemptiveDefault = null; + try { + preemptiveDefault = System.getProperty("httpclient.authentication.preemptive"); + } catch (SecurityException ignore) { + } + if (preemptiveDefault != null) { + preemptiveDefault = preemptiveDefault.trim().toLowerCase(); + if (preemptiveDefault.equals("true")) { + params.setParameter(HttpClientParams.PREEMPTIVE_AUTHENTICATION, Boolean.TRUE); + } else if (preemptiveDefault.equals("false")) { + params.setParameter(HttpClientParams.PREEMPTIVE_AUTHENTICATION, Boolean.FALSE); + } + } + + // TODO: To be removed. Provided for backward compatibility + String defaultCookiePolicy = null; + try { + defaultCookiePolicy = System.getProperty("apache.commons.httpclient.cookiespec"); + } catch (SecurityException ignore) { + } + if (defaultCookiePolicy != null) { + if ("COMPATIBILITY".equalsIgnoreCase(defaultCookiePolicy)) { + params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); + } else if ("NETSCAPE_DRAFT".equalsIgnoreCase(defaultCookiePolicy)) { + params.setCookiePolicy(CookiePolicy.NETSCAPE); + } else if ("RFC2109".equalsIgnoreCase(defaultCookiePolicy)) { + params.setCookiePolicy(CookiePolicy.RFC_2109); + } + } + + return params; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HostParams.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HostParams.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HostParams.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,101 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HostParams.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +/** + * This class represents a collection of HTTP protocol parameters applicable to + * {@link org.apache.commons.httpclient.HostConfiguration instances of HostConfiguration}. + * Protocol parameters may be linked together to form a hierarchy. If a particular + * parameter value has not been explicitly defined in the collection itself, its + * value will be drawn from the parent collection of parameters. + * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * + * @since 3.0 + */ +public class HostParams extends DefaultHttpParams { + + /** + * Defines the request headers to be sent per default with each request. + *

      + * This parameter expects a value of type {@link java.util.Collection}. The + * collection is expected to contain {@link org.apache.commons.httpclient.Header}s. + *

      + */ + public static final String DEFAULT_HEADERS = "http.default-headers"; + + /** + * Creates a new collection of parameters with the collection returned + * by {@link #getDefaultParams()} as a parent. The collection will defer + * to its parent for a default value if a particular parameter is not + * explicitly set in the collection itself. + * + * @see #getDefaultParams() + */ + public HostParams() { + super(); + } + + /** + * Creates a new collection of parameters with the given parent. + * The collection will defer to its parent for a default value + * if a particular parameter is not explicitly set in the collection + * itself. + * + * @param defaults the parent collection to defer to, if a parameter + * is not explictly set in the collection itself. + * + * @see #getDefaultParams() + */ + public HostParams(HttpParams defaults) { + super(defaults); + } + + /** + * Sets the virtual host name. + * + * @param hostname The host name + */ + public void setVirtualHost(final String hostname) { + setParameter(HttpMethodParams.VIRTUAL_HOST, hostname); + } + + /** + * Returns the virtual host name. + * + * @return The virtual host name + */ + public String getVirtualHost() { + return (String) getParameter(HttpMethodParams.VIRTUAL_HOST); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpClientParams.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpClientParams.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpClientParams.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,210 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpClientParams.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +/** + * This class represents a collection of HTTP protocol parameters applicable to + * {@link org.apache.commons.httpclient.HttpClient instances of HttpClient}. + * Protocol parameters may be linked together to form a hierarchy. If a particular + * parameter value has not been explicitly defined in the collection itself, its + * value will be drawn from the parent collection of parameters. + * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * + * @since 3.0 + */ +public class HttpClientParams extends HttpMethodParams { + + /** + * Sets the timeout in milliseconds used when retrieving an + * {@link org.apache.commons.httpclient.HttpConnection HTTP connection} from the + * {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager}. + *

      + * This parameter expects a value of type {@link Long}. + *

      + */ + public static final String CONNECTION_MANAGER_TIMEOUT = "http.connection-manager.timeout"; + + /** + * Defines the default + * {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager} + * class. + *

      + * This parameter expects a value of type {@link Class}. + *

      + */ + public static final String CONNECTION_MANAGER_CLASS = "http.connection-manager.class"; + + /** + * Defines whether authentication should be attempted preemptively. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String PREEMPTIVE_AUTHENTICATION = "http.authentication.preemptive"; + + /** + * Defines whether relative redirects should be rejected. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + 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. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + */ + 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 + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects"; + + /** + * Creates a new collection of parameters with the collection returned + * by {@link #getDefaultParams()} as a parent. The collection will defer + * to its parent for a default value if a particular parameter is not + * explicitly set in the collection itself. + * + * @see #getDefaultParams() + */ + public HttpClientParams() { + super(); + } + + /** + * Creates a new collection of parameters with the given parent. + * The collection will defer to its parent for a default value + * if a particular parameter is not explicitly set in the collection + * itself. + * + * @param defaults the parent collection to defer to, if a parameter + * is not explictly set in the collection itself. + * + * @see #getDefaultParams() + */ + public HttpClientParams(HttpParams defaults) { + super(defaults); + } + + /** + * Returns the timeout in milliseconds used when retrieving an + * {@link org.apache.commons.httpclient.HttpConnection HTTP connection} from the + * {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager}. + * + * @return timeout in milliseconds. + */ + public long getConnectionManagerTimeout() { + return getLongParameter(CONNECTION_MANAGER_TIMEOUT, 0); + } + + /** + * Sets the timeout in milliseconds used when retrieving an + * {@link org.apache.commons.httpclient.HttpConnection HTTP connection} from the + * {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager}. + * + * @param timeout the timeout in milliseconds + */ + public void setConnectionManagerTimeout(long timeout) { + setLongParameter(CONNECTION_MANAGER_TIMEOUT, timeout); + } + + /** + * Returns the default + * {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager} + * class. + * @return {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager} + * factory class. + */ + public Class getConnectionManagerClass() { + return (Class) getParameter(CONNECTION_MANAGER_CLASS); + } + + /** + * Sets {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager} + * class to be used der default. + * @param clazz + * {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection manager} + * factory class. + */ + public void setConnectionManagerClass(Class clazz) { + setParameter(CONNECTION_MANAGER_CLASS, clazz); + } + + /** + * Returns true if authentication should be attempted preemptively, + * false otherwise. + * + * @return true if authentication should be attempted preemptively, + * false otherwise. + */ + public boolean isAuthenticationPreemptive() { + return getBooleanParameter(PREEMPTIVE_AUTHENTICATION, false); + } + + /** + * Sets whether authentication should be attempted preemptively. + * + * @param value true if authentication should be attempted preemptively, + * false otherwise. + */ + public void setAuthenticationPreemptive(boolean value) { + setBooleanParameter(PREEMPTIVE_AUTHENTICATION, value); + } + + private static final String[] PROTOCOL_STRICTNESS_PARAMETERS = { + REJECT_RELATIVE_REDIRECT, + ALLOW_CIRCULAR_REDIRECTS + }; + + + public void makeStrict() { + super.makeStrict(); + setParameters(PROTOCOL_STRICTNESS_PARAMETERS, Boolean.TRUE); + } + + + public void makeLenient() { + super.makeLenient(); + setParameters(PROTOCOL_STRICTNESS_PARAMETERS, Boolean.FALSE); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionManagerParams.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionManagerParams.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionManagerParams.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,189 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionManagerParams.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; + +/** + * This class represents a collection of HTTP protocol parameters applicable to + * {@link org.apache.commons.httpclient.HttpConnectionManager HTTP connection managers}. + * Protocol parameters may be linked together to form a hierarchy. If a particular + * parameter value has not been explicitly defined in the collection itself, its + * value will be drawn from the parent collection of parameters. + * + * @author Oleg Kalnichevski + * @author Michael Becke + * + * @version $Revision: 1.1 $ + * + * @since 3.0 + */ +public class HttpConnectionManagerParams extends HttpConnectionParams { + + /** + * Defines the maximum number of connections allowed per host configuration. + * These values only apply to the number of connections from a particular instance + * of HttpConnectionManager. + *

      + * This parameter expects a value of type {@link java.util.Map}. The value + * should map instances of {@link org.apache.commons.httpclient.HostConfiguration} + * to {@link Integer integers}. The default value can be specified using + * {@link org.apache.commons.httpclient.HostConfiguration#ANY_HOST_CONFIGURATION}. + *

      + */ + public static final String MAX_HOST_CONNECTIONS = "http.connection-manager.max-per-host"; + + /** + * Defines the maximum number of connections allowed overall. This value only applies + * to the number of connections from a particular instance of HttpConnectionManager. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + */ + public static final String MAX_TOTAL_CONNECTIONS = "http.connection-manager.max-total"; + + /** + * Sets the default maximum number of connections allowed for a given + * host config. + * + * @param maxHostConnections The default maximum. + * + * @see #MAX_HOST_CONNECTIONS + */ + public void setDefaultMaxConnectionsPerHost(int maxHostConnections) { + setMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION, maxHostConnections); + } + + /** + * Sets the maximum number of connections to be used for the given host config. + * + * @param hostConfiguration The host config to set the maximum for. Use + * {@link HostConfiguration#ANY_HOST_CONFIGURATION} to configure the default value + * per host. + * @param maxHostConnections The maximum number of connections, > 0 + * + * @see #MAX_HOST_CONNECTIONS + */ + public void setMaxConnectionsPerHost( + HostConfiguration hostConfiguration, + int maxHostConnections) { + + if (maxHostConnections <= 0) { + throw new IllegalArgumentException("maxHostConnections must be greater than 0"); + } + + Map currentValues = (Map) getParameter(MAX_HOST_CONNECTIONS); + // param values are meant to be immutable so we'll make a copy + // to modify + Map newValues = null; + if (currentValues == null) { + newValues = new HashMap(); + } else { + newValues = new HashMap(currentValues); + } + newValues.put(hostConfiguration, new Integer(maxHostConnections)); + setParameter(MAX_HOST_CONNECTIONS, newValues); + } + + /** + * Gets the default maximum number of connections allowed for a given + * host config. + * + * @return The default maximum. + * + * @see #MAX_HOST_CONNECTIONS + */ + public int getDefaultMaxConnectionsPerHost() { + return getMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION); + } + + /** + * Gets the maximum number of connections to be used for a particular host config. If + * the value has not been specified for the given host the default value will be + * returned. + * + * @param hostConfiguration The host config. + * @return The maximum number of connections to be used for the given host config. + * + * @see #MAX_HOST_CONNECTIONS + */ + public int getMaxConnectionsPerHost(HostConfiguration hostConfiguration) { + + Map m = (Map) getParameter(MAX_HOST_CONNECTIONS); + if (m == null) { + // MAX_HOST_CONNECTIONS have not been configured, using the default value + return MultiThreadedHttpConnectionManager.DEFAULT_MAX_HOST_CONNECTIONS; + } else { + Integer max = (Integer) m.get(hostConfiguration); + if (max == null && hostConfiguration != HostConfiguration.ANY_HOST_CONFIGURATION) { + // the value has not been configured specifically for this host config, + // use the default value + return getMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION); + } else { + return ( + max == null + ? MultiThreadedHttpConnectionManager.DEFAULT_MAX_HOST_CONNECTIONS + : max.intValue() + ); + } + } + } + + /** + * Sets the maximum number of connections allowed. + * + * @param maxTotalConnections The maximum number of connections allowed. + * + * @see #MAX_TOTAL_CONNECTIONS + */ + public void setMaxTotalConnections(int maxTotalConnections) { + setIntParameter( + HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, + maxTotalConnections); + } + + /** + * Gets the maximum number of connections allowed. + * + * @return The maximum number of connections allowed. + * + * @see #MAX_TOTAL_CONNECTIONS + */ + public int getMaxTotalConnections() { + return getIntParameter( + HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, + MultiThreadedHttpConnectionManager.DEFAULT_MAX_TOTAL_CONNECTIONS); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionParams.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionParams.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionParams.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,305 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpConnectionParams.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +/** + * This class represents a collection of HTTP protocol parameters applicable to + * {@link org.apache.commons.httpclient.HttpConnection HTTP connections}. + * Protocol parameters may be linked together to form a hierarchy. If a particular + * parameter value has not been explicitly defined in the collection itself, its + * value will be drawn from the parent collection of parameters. + * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * + * @since 3.0 + */ +public class HttpConnectionParams extends DefaultHttpParams { + + /** + * Defines the default socket timeout (SO_TIMEOUT) in milliseconds which is the + * timeout for waiting for data. A timeout value of zero is interpreted as an infinite + * timeout. This value is used when no socket timeout is set in the + * {@link HttpMethodParams HTTP method parameters}. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + * @see java.net.SocketOptions#SO_TIMEOUT + */ + public static final String SO_TIMEOUT = "http.socket.timeout"; + + /** + * Determines whether Nagle's algorithm is to be used. The Nagle's algorithm + * tries to conserve bandwidth by minimizing the number of segments that are + * sent. When applications wish to decrease network latency and increase + * performance, they can disable Nagle's algorithm (that is enable TCP_NODELAY). + * Data will be sent earlier, at the cost of an increase in bandwidth consumption. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + * @see java.net.SocketOptions#TCP_NODELAY + */ + public static final String TCP_NODELAY = "http.tcp.nodelay"; + + /** + * Determines a hint the size of the underlying buffers used by the platform + * for outgoing network I/O. This value is a suggestion to the kernel from + * the application about the size of buffers to use for the data to be sent + * over the socket. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + * @see java.net.SocketOptions#SO_SNDBUF + */ + public static final String SO_SNDBUF = "http.socket.sendbuffer"; + + /** + * Determines a hint the size of the underlying buffers used by the platform + * for incoming network I/O. This value is a suggestion to the kernel from + * the application about the size of buffers to use for the data to be received + * over the socket. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + * @see java.net.SocketOptions#SO_RCVBUF + */ + public static final String SO_RCVBUF = "http.socket.receivebuffer"; + + /** + * Sets SO_LINGER with the specified linger time in seconds. The maximum timeout + * value is platform specific. Value 0 implies that the option is disabled. + * Value -1 implies that the JRE default is used. The setting only affects + * socket close. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + * @see java.net.SocketOptions#SO_LINGER + */ + public static final String SO_LINGER = "http.socket.linger"; + + /** + * Determines the timeout until a connection is etablished. A value of zero + * means the timeout is not used. The default value is zero. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + */ + public static final String CONNECTION_TIMEOUT = "http.connection.timeout"; + + /** + * Determines whether stale connection check is to be used. Disabling + * stale connection check may result in slight performance improvement + * at the risk of getting an I/O error when executing a request over a + * connection that has been closed at the server side. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String STALE_CONNECTION_CHECK = "http.connection.stalecheck"; + + /** + * Creates a new collection of parameters with the collection returned + * by {@link #getDefaultParams()} as a parent. The collection will defer + * to its parent for a default value if a particular parameter is not + * explicitly set in the collection itself. + * + * @see #getDefaultParams() + */ + public HttpConnectionParams() { + super(); + } + + /** + * Returns the default socket timeout (SO_TIMEOUT) in milliseconds which is the + * timeout for waiting for data. A timeout value of zero is interpreted as an infinite + * timeout. This value is used when no socket timeout is set in the + * {@link HttpMethodParams HTTP method parameters}. + * + * @return timeout in milliseconds + */ + public int getSoTimeout() { + return getIntParameter(SO_TIMEOUT, 0); + } + + /** + * Sets the default socket timeout (SO_TIMEOUT) in milliseconds which is the + * timeout for waiting for data. A timeout value of zero is interpreted as an infinite + * timeout. This value is used when no socket timeout is set in the + * {@link HttpMethodParams HTTP method parameters}. + * + * @param timeout Timeout in milliseconds + */ + public void setSoTimeout(int timeout) { + setIntParameter(SO_TIMEOUT, timeout); + } + + /** + * Determines whether Nagle's algorithm is to be used. The Nagle's algorithm + * tries to conserve bandwidth by minimizing the number of segments that are + * sent. When applications wish to decrease network latency and increase + * performance, they can disable Nagle's algorithm (that is enable TCP_NODELAY). + * Data will be sent earlier, at the cost of an increase in bandwidth consumption. + * + * @param value true if the Nagle's algorithm is to NOT be used + * (that is enable TCP_NODELAY), false otherwise. + */ + public void setTcpNoDelay(boolean value) { + setBooleanParameter(TCP_NODELAY, value); + } + + /** + * Tests if Nagle's algorithm is to be used. + * + * @return true if the Nagle's algorithm is to NOT be used + * (that is enable TCP_NODELAY), false otherwise. + */ + public boolean getTcpNoDelay() { + return getBooleanParameter(TCP_NODELAY, true); + } + + /** + * Returns a hint the size of the underlying buffers used by the platform for + * outgoing network I/O. This value is a suggestion to the kernel from the + * application about the size of buffers to use for the data to be sent over + * the socket. + * + * @return the hint size of the send buffer + */ + public int getSendBufferSize() { + return getIntParameter(SO_SNDBUF, -1); + } + + /** + * Sets a hint the size of the underlying buffers used by the platform for + * outgoing network I/O. This value is a suggestion to the kernel from the + * application about the size of buffers to use for the data to be sent over + * the socket. + * + * @param size the hint size of the send buffer + */ + public void setSendBufferSize(int size) { + setIntParameter(SO_SNDBUF, size); + } + + /** + * Returns a hint the size of the underlying buffers used by the platform + * for incoming network I/O. This value is a suggestion to the kernel from + * the application about the size of buffers to use for the data to be received + * over the socket. + * + * @return the hint size of the send buffer + */ + public int getReceiveBufferSize() { + return getIntParameter(SO_RCVBUF, -1); + } + + /** + * Sets a hint the size of the underlying buffers used by the platform + * for incoming network I/O. This value is a suggestion to the kernel from + * the application about the size of buffers to use for the data to be received + * over the socket. + * + * @param size the hint size of the send buffer + */ + public void setReceiveBufferSize(int size) { + setIntParameter(SO_RCVBUF, size); + } + + /** + * Returns linger-on-close timeout. Value 0 implies that the option is + * disabled. Value -1 implies that the JRE default is used. + * + * @return the linger-on-close timeout + */ + public int getLinger() { + return getIntParameter(SO_LINGER, -1); + } + + /** + * Returns linger-on-close timeout. This option disables/enables immediate return + * from a close() of a TCP Socket. Enabling this option with a non-zero Integer + * timeout means that a close() will block pending the transmission and + * acknowledgement of all data written to the peer, at which point the socket is + * closed gracefully. Value 0 implies that the option is + * disabled. Value -1 implies that the JRE default is used. + * + * @param value the linger-on-close timeout + */ + public void setLinger(int value) { + setIntParameter(SO_LINGER, value); + } + + /** + * Returns the timeout until a connection is etablished. A value of zero + * means the timeout is not used. The default value is zero. + * + * @return timeout in milliseconds. + */ + public int getConnectionTimeout() { + return getIntParameter(CONNECTION_TIMEOUT, 0); + } + + /** + * Sets the timeout until a connection is etablished. A value of zero + * means the timeout is not used. The default value is zero. + * + * @param timeout Timeout in milliseconds. + */ + public void setConnectionTimeout(int timeout) { + setIntParameter(CONNECTION_TIMEOUT, timeout); + } + + /** + * Tests whether stale connection check is to be used. Disabling + * stale connection check may result in slight performance improvement + * at the risk of getting an I/O error when executing a request over a + * connection that has been closed at the server side. + * + * @return true if stale connection check is to be used, + * false otherwise. + */ + public boolean isStaleCheckingEnabled() { + return getBooleanParameter(STALE_CONNECTION_CHECK, true); + } + + /** + * Defines whether stale connection check is to be used. Disabling + * stale connection check may result in slight performance improvement + * at the risk of getting an I/O error when executing a request over a + * connection that has been closed at the server side. + * + * @param value true if stale connection check is to be used, + * false otherwise. + */ + public void setStaleCheckingEnabled(boolean value) { + setBooleanParameter(STALE_CONNECTION_CHECK, value); + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpMethodParams.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpMethodParams.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpMethodParams.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,493 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpMethodParams.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +import org.apache.commons.httpclient.HttpVersion; +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class represents a collection of HTTP protocol parameters applicable to + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods}. Protocol + * parameters may be linked together to form a hierarchy. If a particular + * parameter value has not been explicitly defined in the collection itself, + * its value will be drawn from the parent collection of parameters. + * + * @author Oleg Kalnichevski + * @author Christian Kohlschuetter + * + * @version $Revision: 1.1 $ + * + * @since 3.0 + */ +public class HttpMethodParams extends DefaultHttpParams { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpMethodParams.class); + + /** + * Defines the content of the User-Agent header used by + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods}. + *

      + * This parameter expects a value of type {@link String}. + *

      + */ + public static final String USER_AGENT = "http.useragent"; + + /** + * Defines the {@link HttpVersion HTTP protocol version} used by + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods} per + * default. + *

      + * This parameter expects a value of type {@link HttpVersion}. + *

      + */ + public static final String PROTOCOL_VERSION = "http.protocol.version"; + + /** + * Defines whether {@link org.apache.commons.httpclient.HttpMethod HTTP methods} should + * reject ambiguous {@link org.apache.commons.httpclient.StatusLine HTTP status line}. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String UNAMBIGUOUS_STATUS_LINE = "http.protocol.unambiguous-statusline"; + + /** + * Defines whether {@link org.apache.commons.httpclient.Cookie cookies} should be put on + * a single {@link org.apache.commons.httpclient.Header response header}. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header"; + + /** + * Defines whether responses with an invalid Transfer-Encoding header should be + * rejected. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String STRICT_TRANSFER_ENCODING = "http.protocol.strict-transfer-encoding"; + + /** + * Defines whether the content body sent in response to + * {@link org.apache.commons.httpclient.methods.HeadMethod} should be rejected. + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String REJECT_HEAD_BODY = "http.protocol.reject-head-body"; + + /** + * Sets period of time in milliseconds to wait for a content body sent in response to + * {@link org.apache.commons.httpclient.methods.HeadMethod HEAD method} from a + * non-compliant server. If the parameter is not set or set to -1 non-compliant + * response body check is disabled. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + */ + public static final String HEAD_BODY_CHECK_TIMEOUT = "http.protocol.head-body-timeout"; + + /** + *

      + * Activates 'Expect: 100-Continue' handshake for the + * {@link org.apache.commons.httpclient.methods.ExpectContinueMethod + * entity enclosing methods}. The purpose of the 'Expect: 100-Continue' + * handshake 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. + *

      + * + *

      + * The use of the 'Expect: 100-continue' handshake can result in + * noticable peformance improvement for entity enclosing requests + * (such as POST and PUT) that require the target server's + * authentication. + *

      + * + *

      + * '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. + *

      + * + * This parameter expects a value of type {@link Boolean}. + */ + public static final String USE_EXPECT_CONTINUE = "http.protocol.expect-continue"; + + /** + * Defines the charset to be used when encoding + * {@link org.apache.commons.httpclient.Credentials}. If not defined then the + * {@link #HTTP_ELEMENT_CHARSET} should be used. + *

      + * This parameter expects a value of type {@link String}. + *

      + */ + public static final String CREDENTIAL_CHARSET = "http.protocol.credential-charset"; + + /** + * Defines the charset to be used for encoding HTTP protocol elements. + *

      + * This parameter expects a value of type {@link String}. + *

      + */ + public static final String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset"; + + /** + * Defines the charset to be used for encoding content body. + *

      + * This parameter expects a value of type {@link String}. + *

      + */ + public static final String HTTP_CONTENT_CHARSET = "http.protocol.content-charset"; + + /** + * Defines {@link CookiePolicy cookie policy} to be used for cookie management. + *

      + * This parameter expects a value of type {@link String}. + *

      + */ + public static final String COOKIE_POLICY = "http.protocol.cookie-policy"; + + /** + * Defines HttpClient's behavior when a response provides more bytes than + * expected (specified with Content-Length, for example). + *

      + * Such surplus data makes the HTTP connection unreliable for keep-alive + * requests, as malicious response data (faked headers etc.) can lead to undesired + * results on the next request using that connection. + *

      + *

      + * If this parameter is set to true, any detection of extra + * input data will generate a warning in the log. + *

      + *

      + * This parameter expects a value of type {@link Boolean}. + *

      + */ + public static final String WARN_EXTRA_INPUT = "http.protocol.warn-extra-input"; + + /** + * Defines the maximum number of ignorable lines before we expect + * a HTTP response's status code. + *

      + * With HTTP/1.1 persistent connections, the problem arises that + * broken scripts could return a wrong Content-Length + * (there are more bytes sent than specified).
      + * Unfortunately, in some cases, this is not possible after the bad response, + * but only before the next one.
      + * So, HttpClient must be able to skip those surplus lines this way. + *

      + *

      + * Set this to 0 to disallow any garbage/empty lines before the status line.
      + * To specify no limit, use {@link java.lang.Integer#MAX_VALUE} (default in lenient mode). + *

      + * + * This parameter expects a value of type {@link Integer}. + */ + public static final String STATUS_LINE_GARBAGE_LIMIT = "http.protocol.status-line-garbage-limit"; + + /** + * Sets the socket timeout (SO_TIMEOUT) in milliseconds to be used when executing the method. + * A timeout value of zero is interpreted as an infinite timeout. + *

      + * This parameter expects a value of type {@link Integer}. + *

      + * @see java.net.SocketOptions#SO_TIMEOUT + */ + public static final String SO_TIMEOUT = "http.socket.timeout"; + + /** + * The key used to look up the date patterns used for parsing. The String patterns are stored + * in a {@link java.util.Collection} and must be compatible with + * {@link java.text.SimpleDateFormat}. + *

      + * This parameter expects a value of type {@link java.util.Collection}. + *

      + */ + public static final String DATE_PATTERNS = "http.dateparser.patterns"; + + /** + * Sets the method retry handler parameter. + *

      + * This parameter expects a value of type {@link org.apache.commons.httpclient.HttpMethodRetryHandler}. + *

      + */ + public static final String RETRY_HANDLER = "http.method.retry-handler"; + + /** + * Sets the maximum buffered response size (in bytes) that triggers no warning. Buffered + * responses exceeding this size will trigger a warning in the log. + *

      + * This parameter expects a value if type {@link Integer}. + *

      + */ + public static final String BUFFER_WARN_TRIGGER_LIMIT = "http.method.response.buffer.warnlimit"; + + /** + * Defines the virtual host name. + *

      + * This parameter expects a value of type {@link java.lang.String}. + *

      + */ + public static final String VIRTUAL_HOST = "http.virtual-host"; + + /** + * Sets the value to use as the multipart boundary. + *

      + * This parameter expects a value if type {@link String}. + *

      + * @see org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity + */ + public static final String MULTIPART_BOUNDARY = "http.method.multipart.boundary"; + + /** + * Creates a new collection of parameters with the collection returned + * by {@link #getDefaultParams()} as a parent. The collection will defer + * to its parent for a default value if a particular parameter is not + * explicitly set in the collection itself. + * + * @see #getDefaultParams() + */ + public HttpMethodParams() { + super(getDefaultParams()); + } + + /** + * Creates a new collection of parameters with the given parent. + * The collection will defer to its parent for a default value + * if a particular parameter is not explicitly set in the collection + * itself. + * + * @param defaults the parent collection to defer to, if a parameter + * is not explictly set in the collection itself. + * + * @see #getDefaultParams() + */ + public HttpMethodParams(HttpParams defaults) { + super(defaults); + } + + /** + * Returns the charset to be used for writing HTTP headers. + * @return The charset + */ + public String getHttpElementCharset() { + String charset = (String) getParameter(HTTP_ELEMENT_CHARSET); + if (charset == null) { + LOG.warn("HTTP element charset not configured, using US-ASCII"); + charset = "US-ASCII"; + } + return charset; + } + + /** + * Sets the charset to be used for writing HTTP headers. + * @param charset The charset + */ + public void setHttpElementCharset(String charset) { + setParameter(HTTP_ELEMENT_CHARSET, charset); + } + + /** + * Returns the default charset to be used for writing content body, + * when no charset explicitly specified. + * @return The charset + */ + public String getContentCharset() { + String charset = (String) getParameter(HTTP_CONTENT_CHARSET); + if (charset == null) { + LOG.warn("Default content charset not configured, using ISO-8859-1"); + charset = "ISO-8859-1"; + } + return charset; + } + + /** + * Sets the default charset to be used for writing content body, + * when no charset explicitly specified. + * @param charset The charset + */ + public void setContentCharset(String charset) { + setParameter(HTTP_CONTENT_CHARSET, charset); + } + + /** + * Returns the charset to be used for {@link org.apache.commons.httpclient.Credentials}. If + * not configured the {@link #HTTP_ELEMENT_CHARSET HTTP element charset} is used. + * @return The charset + */ + public String getCredentialCharset() { + String charset = (String) getParameter(CREDENTIAL_CHARSET); + if (charset == null) { + LOG.debug("Credential charset not configured, using HTTP element charset"); + charset = getHttpElementCharset(); + } + return charset; + } + + /** + * Sets the charset to be used for writing HTTP headers. + * @param charset The charset + */ + public void setCredentialCharset(String charset) { + setParameter(CREDENTIAL_CHARSET, charset); + } + + /** + * Returns {@link HttpVersion HTTP protocol version} to be used by the + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods} that + * this collection of parameters applies to. + * + * @return {@link HttpVersion HTTP protocol version} + */ + public HttpVersion getVersion() { + Object param = getParameter(PROTOCOL_VERSION); + if (param == null) { + return HttpVersion.HTTP_1_1; + } + return (HttpVersion)param; + } + + /** + * Assigns the {@link HttpVersion HTTP protocol version} to be used by the + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods} that + * this collection of parameters applies to. + * + * @param version the {@link HttpVersion HTTP protocol version} + */ + public void setVersion(HttpVersion version) { + setParameter(PROTOCOL_VERSION, version); + } + + + /** + * Returns {@link CookiePolicy cookie policy} to be used by the + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods} + * this collection of parameters applies to. + * + * @return {@link CookiePolicy cookie policy} + */ + public String getCookiePolicy() { + Object param = getParameter(COOKIE_POLICY); + if (param == null) { + return CookiePolicy.DEFAULT; + } + return (String)param; + } + + /** + * Assigns the {@link CookiePolicy cookie policy} to be used by the + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods} + * this collection of parameters applies to. + * + * @param policy the {@link CookiePolicy cookie policy} + */ + public void setCookiePolicy(String policy) { + setParameter(COOKIE_POLICY, policy); + } + + /** + * Returns the default socket timeout (SO_TIMEOUT) in milliseconds which is the + * timeout for waiting for data. A timeout value of zero is interpreted as an infinite + * timeout. + * + * @return timeout in milliseconds + */ + public int getSoTimeout() { + return getIntParameter(SO_TIMEOUT, 0); + } + + /** + * Sets the default socket timeout (SO_TIMEOUT) in milliseconds which is the + * timeout for waiting for data. A timeout value of zero is interpreted as an infinite + * timeout. + * + * @param timeout Timeout in milliseconds + */ + public void setSoTimeout(int timeout) { + setIntParameter(SO_TIMEOUT, timeout); + } + + /** + * Sets the virtual host name. + * + * @param hostname The host name + */ + public void setVirtualHost(final String hostname) { + setParameter(VIRTUAL_HOST, hostname); + } + + /** + * Returns the virtual host name. + * + * @return The virtual host name + */ + public String getVirtualHost() { + return (String) getParameter(VIRTUAL_HOST); + } + + private static final String[] PROTOCOL_STRICTNESS_PARAMETERS = { + UNAMBIGUOUS_STATUS_LINE, + SINGLE_COOKIE_HEADER, + STRICT_TRANSFER_ENCODING, + REJECT_HEAD_BODY, + WARN_EXTRA_INPUT + }; + + /** + * Makes the {@link org.apache.commons.httpclient.HttpMethod HTTP methods} + * strictly follow the HTTP protocol specification (RFC 2616 and other relevant RFCs). + * It must be noted that popular HTTP agents have different degree of HTTP protocol + * compliance and some HTTP serves are programmed to expect the behaviour that does not + * strictly adhere to the HTTP specification. + */ + public void makeStrict() { + setParameters(PROTOCOL_STRICTNESS_PARAMETERS, Boolean.TRUE); + setIntParameter(STATUS_LINE_GARBAGE_LIMIT, 0); + } + + /** + * Makes the {@link org.apache.commons.httpclient.HttpMethod HTTP methods} + * attempt to mimic the exact behaviour of commonly used HTTP agents, + * which many HTTP servers expect, even though such behaviour may violate + * the HTTP protocol specification (RFC 2616 and other relevant RFCs). + */ + public void makeLenient() { + setParameters(PROTOCOL_STRICTNESS_PARAMETERS, Boolean.FALSE); + setIntParameter(STATUS_LINE_GARBAGE_LIMIT, Integer.MAX_VALUE); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParams.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParams.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParams.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,231 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParams.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +/** + * This interface represents a collection of HTTP protocol parameters. Protocol parameters + * may be linked together to form a hierarchy. If a particular parameter value has not been + * explicitly defined in the collection itself, its value will be drawn from the parent + * collection of parameters. + * + * @author Oleg Kalnichevski + * + * @version $Revision: 1.1 $ + * + * @since 3.0 + */ +public interface HttpParams { + + /** + * Returns the parent collection that this collection will defer to + * for a default value if a particular parameter is not explicitly + * set in the collection itself + * + * @return the parent collection to defer to, if a particular parameter + * is not explictly set in the collection itself. + * + * @see #setDefaults(HttpParams) + */ + public HttpParams getDefaults(); + + /** + * Assigns the parent collection that this collection will defer to + * for a default value if a particular parameter is not explicitly + * set in the collection itself + * + * @param params the parent collection to defer to, if a particular + * parameter is not explictly set in the collection itself. + * + * @see #getDefaults() + */ + public void setDefaults(final HttpParams params); + + /** + * Returns a parameter value with the given name. If the parameter is + * not explicitly defined in this collection, its value will be drawn + * from a higer level collection at which this parameter is defined. + * If the parameter is not explicitly set anywhere up the hierarchy, + * null value is returned. + * + * @param name the parent name. + * + * @return an object that represents the value of the parameter. + * + * @see #setParameter(String, Object) + */ + public Object getParameter(final String name); + + /** + * Assigns the value to the parameter with the given name + * + * @param name parameter name + * @param value parameter value + */ + public void setParameter(final String name, final Object value); + + /** + * Returns a {@link Long} parameter value with the given name. + * If the parameter is not explicitly defined in this collection, its + * value will be drawn from a higer level collection at which this parameter + * is defined. If the parameter is not explicitly set anywhere up the hierarchy, + * the default value is returned. + * + * @param name the parent name. + * @param defaultValue the default value. + * + * @return a {@link Long} that represents the value of the parameter. + * + * @see #setLongParameter(String, long) + */ + public long getLongParameter(final String name, long defaultValue); + + /** + * Assigns a {@link Long} to the parameter with the given name + * + * @param name parameter name + * @param value parameter value + */ + public void setLongParameter(final String name, long value); + + /** + * Returns an {@link Integer} parameter value with the given name. + * If the parameter is not explicitly defined in this collection, its + * value will be drawn from a higer level collection at which this parameter + * is defined. If the parameter is not explicitly set anywhere up the hierarchy, + * the default value is returned. + * + * @param name the parent name. + * @param defaultValue the default value. + * + * @return a {@link Integer} that represents the value of the parameter. + * + * @see #setIntParameter(String, int) + */ + public int getIntParameter(final String name, int defaultValue); + + /** + * Assigns an {@link Integer} to the parameter with the given name + * + * @param name parameter name + * @param value parameter value + */ + public void setIntParameter(final String name, int value); + + /** + * Returns a {@link Double} parameter value with the given name. + * If the parameter is not explicitly defined in this collection, its + * value will be drawn from a higer level collection at which this parameter + * is defined. If the parameter is not explicitly set anywhere up the hierarchy, + * the default value is returned. + * + * @param name the parent name. + * @param defaultValue the default value. + * + * @return a {@link Double} that represents the value of the parameter. + * + * @see #setDoubleParameter(String, double) + */ + public double getDoubleParameter(final String name, double defaultValue); + + /** + * Assigns a {@link Double} to the parameter with the given name + * + * @param name parameter name + * @param value parameter value + */ + public void setDoubleParameter(final String name, double value); + + /** + * Returns a {@link Boolean} parameter value with the given name. + * If the parameter is not explicitly defined in this collection, its + * value will be drawn from a higer level collection at which this parameter + * is defined. If the parameter is not explicitly set anywhere up the hierarchy, + * the default value is returned. + * + * @param name the parent name. + * @param defaultValue the default value. + * + * @return a {@link Boolean} that represents the value of the parameter. + * + * @see #setBooleanParameter(String, boolean) + */ + public boolean getBooleanParameter(final String name, boolean defaultValue); + + /** + * Assigns a {@link Boolean} to the parameter with the given name + * + * @param name parameter name + * @param value parameter value + */ + public void setBooleanParameter(final String name, boolean value); + + /** + * Returns true if the parameter is set at any level, false otherwise. + * + * @param name parameter name + * + * @return true if the parameter is set at any level, false + * otherwise. + */ + public boolean isParameterSet(final String name); + + /** + * Returns true if the parameter is set locally, false otherwise. + * + * @param name parameter name + * + * @return true if the parameter is set locally, false + * otherwise. + */ + public boolean isParameterSetLocally(final String name); + + /** + * Returns true if the parameter is set and is true, false + * otherwise. + * + * @param name parameter name + * + * @return true if the parameter is set and is true, false + * otherwise. + */ + public boolean isParameterTrue(final String name); + + /** + * Returns true if the parameter is either not set or is false, + * false otherwise. + * + * @param name parameter name + * + * @return true if the parameter is either not set or is false, + * false otherwise. + */ + public boolean isParameterFalse(final String name); + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParamsFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParamsFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParamsFactory.java 22 Aug 2012 17:30:39 -0000 1.1 @@ -0,0 +1,50 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/HttpParamsFactory.java,v 1.1 2012/08/22 17:30:39 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:39 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.params; + +/** + * A factory for getting the default set of parameters to use when creating an instance of + * HttpParams. + * + * @see org.apache.commons.httpclient.params.DefaultHttpParams#setHttpParamsFactory(HttpParamsFactory) + * + * @since 3.0 + */ +public interface HttpParamsFactory { + + /** + * Gets the default parameters. This method may be called more than once and is not required + * to always return the same value. + * + * @return an instance of HttpParams + */ + HttpParams getDefaultParams(); + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/params/package.html 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,11 @@ + + + + Package Documentation for org.apache.commons.httpclient.params + + + HttpClient preferences framework. + + @since 3.0 + + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ControllerThreadSocketFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ControllerThreadSocketFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ControllerThreadSocketFactory.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,163 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ControllerThreadSocketFactory.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.protocol; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.util.TimeoutController; + +/** + * This helper class is intedned to help work around the limitation of older Java versions + * (older than 1.4) that prevents from specifying a connection timeout when creating a + * socket. This factory executes a controller thread overssing the process of socket + * initialisation. If the socket constructor cannot be created within the specified time + * limit, the controller terminates and throws an {@link ConnectTimeoutException} + * + * @author Ortwin Glueck + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public final class ControllerThreadSocketFactory { + + private ControllerThreadSocketFactory() { + super(); + } + + /** + * This method spawns a controller thread overseeing the process of socket + * initialisation. If the socket constructor cannot be created within the specified time + * limit, the controller terminates and throws an {@link ConnectTimeoutException} + * + * @param host the host name/IP + * @param port the port on the host + * @param localAddress the local host name/IP to bind the socket to + * @param localPort the port on the local machine + * @param timeout the timeout value to be used in milliseconds. If the socket cannot be + * completed within the given time limit, it will be abandoned + * + * @return a connected Socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + * @throws ConnectTimeoutException if socket cannot be connected within the + * given time limit + * + */ + public static Socket createSocket( + final ProtocolSocketFactory socketfactory, + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + int timeout) + throws IOException, UnknownHostException, ConnectTimeoutException + { + SocketTask task = new SocketTask() { + public void doit() throws IOException { + setSocket(socketfactory.createSocket(host, port, localAddress, localPort)); + } + }; + try { + TimeoutController.execute(task, timeout); + } catch (TimeoutController.TimeoutException e) { + throw new ConnectTimeoutException( + "The host did not accept the connection within timeout of " + + timeout + " ms"); + } + Socket socket = task.getSocket(); + if (task.exception != null) { + throw task.exception; + } + return socket; + } + + public static Socket createSocket(final SocketTask task, int timeout) + throws IOException, UnknownHostException, ConnectTimeoutException + { + try { + TimeoutController.execute(task, timeout); + } catch (TimeoutController.TimeoutException e) { + throw new ConnectTimeoutException( + "The host did not accept the connection within timeout of " + + timeout + " ms"); + } + Socket socket = task.getSocket(); + if (task.exception != null) { + throw task.exception; + } + return socket; + } + + /** + * Helper class for wrapping socket based tasks. + */ + public static abstract class SocketTask implements Runnable { + /** The socket */ + private Socket socket; + /** The exception */ + private IOException exception; + + /** + * Set the socket. + * @param newSocket The new socket. + */ + protected void setSocket(final Socket newSocket) { + socket = newSocket; + } + + /** + * Return the socket. + * @return Socket The socket. + */ + protected Socket getSocket() { + return socket; + } + /** + * Perform the logic. + * @throws IOException If an IO problem occurs + */ + public abstract void doit() throws IOException; + + /** Execute the logic in this object and keep track of any exceptions. */ + public void run() { + try { + doit(); + } catch (IOException e) { + exception = e; + } + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/DefaultProtocolSocketFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/DefaultProtocolSocketFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/DefaultProtocolSocketFactory.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,156 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/DefaultProtocolSocketFactory.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.protocol; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.params.HttpConnectionParams; + +/** + * The default class for creating protocol sockets. This class just uses the + * {@link java.net.Socket socket} constructors. + * + * @author Michael Becke + * + * @since 2.0 + */ +public class DefaultProtocolSocketFactory implements ProtocolSocketFactory { + + /** + * The factory singleton. + */ + private static final DefaultProtocolSocketFactory factory = new DefaultProtocolSocketFactory(); + + /** + * Gets an singleton instance of the DefaultProtocolSocketFactory. + * @return a DefaultProtocolSocketFactory + */ + static DefaultProtocolSocketFactory getSocketFactory() { + return factory; + } + + /** + * Constructor for DefaultProtocolSocketFactory. + */ + public DefaultProtocolSocketFactory() { + super(); + } + + /** + * @see #createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket( + String host, + int port, + InetAddress localAddress, + int localPort + ) throws IOException, UnknownHostException { + return new Socket(host, port, localAddress, localPort); + } + + /** + * Attempts to get a new socket connection to the given host within the given time limit. + *

      + * This method employs several techniques to circumvent the limitations of older JREs that + * do not support connect timeout. When running in JRE 1.4 or above reflection is used to + * call Socket#connect(SocketAddress endpoint, int timeout) method. When executing in older + * JREs a controller thread is executed. The controller thread attempts to create a new socket + * within the given limit of time. If socket constructor does not return until the timeout + * expires, the controller terminates and throws an {@link ConnectTimeoutException} + *

      + * + * @param host the host name/IP + * @param port the port on the host + * @param localAddress the local host name/IP to bind the socket to + * @param localPort the port on the local machine + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + * @throws ConnectTimeoutException if socket cannot be connected within the + * given time limit + * + * @since 3.0 + */ + public Socket createSocket( + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + final HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + int timeout = params.getConnectionTimeout(); + if (timeout == 0) { + return createSocket(host, port, localAddress, localPort); + } else { + // To be eventually deprecated when migrated to Java 1.4 or above + Socket socket = ReflectionSocketFactory.createSocket( + "javax.net.SocketFactory", host, port, localAddress, localPort, timeout); + if (socket == null) { + socket = ControllerThreadSocketFactory.createSocket( + this, host, port, localAddress, localPort, timeout); + } + return socket; + } + } + + /** + * @see ProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException { + return new Socket(host, port); + } + + /** + * All instances of DefaultProtocolSocketFactory are the same. + */ + public boolean equals(Object obj) { + return ((obj != null) && obj.getClass().equals(DefaultProtocolSocketFactory.class)); + } + + /** + * All instances of DefaultProtocolSocketFactory have the same hash code. + */ + public int hashCode() { + return DefaultProtocolSocketFactory.class.hashCode(); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/Protocol.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/Protocol.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/Protocol.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,295 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/Protocol.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ +package org.apache.commons.httpclient.protocol; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.httpclient.util.LangUtils; + +/** + * A class to encapsulate the specifics of a protocol. This class class also + * provides the ability to customize the set and characteristics of the + * protocols used. + * + *

      One use case for modifying the default set of protocols would be to set a + * custom SSL socket factory. This would look something like the following: + *

       
      + * Protocol myHTTPS = new Protocol( "https", new MySSLSocketFactory(), 443 );
      + * 
      + * Protocol.registerProtocol( "https", myHTTPS );
      + * 
      + * + * @author Michael Becke + * @author Jeff Dever + * @author Mike Bowler + * + * @since 2.0 + */ +public class Protocol { + + /** The available protocols */ + private static final Map PROTOCOLS = Collections.synchronizedMap(new HashMap()); + + /** + * Registers a new protocol with the given identifier. If a protocol with + * the given ID already exists it will be overridden. This ID is the same + * one used to retrieve the protocol from getProtocol(String). + * + * @param id the identifier for this protocol + * @param protocol the protocol to register + * + * @see #getProtocol(String) + */ + public static void registerProtocol(String id, Protocol protocol) { + + if (id == null) { + throw new IllegalArgumentException("id is null"); + } + if (protocol == null) { + throw new IllegalArgumentException("protocol is null"); + } + + PROTOCOLS.put(id, protocol); + } + + /** + * Unregisters the protocol with the given ID. + * + * @param id the ID of the protocol to remove + */ + public static void unregisterProtocol(String id) { + + if (id == null) { + throw new IllegalArgumentException("id is null"); + } + + PROTOCOLS.remove(id); + } + + /** + * Gets the protocol with the given ID. + * + * @param id the protocol ID + * + * @return Protocol a protocol + * + * @throws IllegalStateException if a protocol with the ID cannot be found + */ + public static Protocol getProtocol(String id) + throws IllegalStateException { + + if (id == null) { + throw new IllegalArgumentException("id is null"); + } + + Protocol protocol = (Protocol) PROTOCOLS.get(id); + + if (protocol == null) { + protocol = lazyRegisterProtocol(id); + } + + return protocol; + } + + /** + * Lazily registers the protocol with the given id. + * + * @param id the protocol ID + * + * @return the lazily registered protocol + * + * @throws IllegalStateException if the protocol with id is not recognized + */ + private static Protocol lazyRegisterProtocol(String id) + throws IllegalStateException { + + if ("http".equals(id)) { + final Protocol http + = new Protocol("http", DefaultProtocolSocketFactory.getSocketFactory(), 80); + Protocol.registerProtocol("http", http); + return http; + } + + if ("https".equals(id)) { + final Protocol https + = new Protocol("https", SSLProtocolSocketFactory.getSocketFactory(), 443); + Protocol.registerProtocol("https", https); + return https; + } + + throw new IllegalStateException("unsupported protocol: '" + id + "'"); + } + + + /** the scheme of this protocol (e.g. http, https) */ + private String scheme; + + /** The socket factory for this protocol */ + private ProtocolSocketFactory socketFactory; + + /** The default port for this protocol */ + private int defaultPort; + + /** True if this protocol is secure */ + private boolean secure; + + /** + * Constructs a new Protocol. Whether the created protocol is secure depends on + * the class of factory. + * + * @param scheme the scheme (e.g. http, https) + * @param factory the factory for creating sockets for communication using + * this protocol + * @param defaultPort the port this protocol defaults to + */ + public Protocol(String scheme, ProtocolSocketFactory factory, int defaultPort) { + + if (scheme == null) { + throw new IllegalArgumentException("scheme is null"); + } + if (factory == null) { + throw new IllegalArgumentException("socketFactory is null"); + } + if (defaultPort <= 0) { + throw new IllegalArgumentException("port is invalid: " + defaultPort); + } + + this.scheme = scheme; + this.socketFactory = factory; + this.defaultPort = defaultPort; + this.secure = (factory instanceof SecureProtocolSocketFactory); + } + + /** + * Constructs a new Protocol. Whether the created protocol is secure depends on + * the class of factory. + * + * @param scheme the scheme (e.g. http, https) + * @param factory the factory for creating sockets for communication using + * this protocol + * @param defaultPort the port this protocol defaults to + * @deprecated Use the constructor that uses ProtocolSocketFactory, this version of + * the constructor is only kept for backwards API compatibility. + */ + public Protocol(String scheme, + SecureProtocolSocketFactory factory, int defaultPort) { + this(scheme, (ProtocolSocketFactory) factory, defaultPort); + } + + /** + * Returns the defaultPort. + * @return int + */ + public int getDefaultPort() { + return defaultPort; + } + + /** + * Returns the socketFactory. If secure the factory is a + * SecureProtocolSocketFactory. + * @return SocketFactory + */ + public ProtocolSocketFactory getSocketFactory() { + return socketFactory; + } + + /** + * Returns the scheme. + * @return The scheme + */ + public String getScheme() { + return scheme; + } + + /** + * Returns true if this protocol is secure + * @return true if this protocol is secure + */ + public boolean isSecure() { + return secure; + } + + /** + * Resolves the correct port for this protocol. Returns the given port if + * valid or the default port otherwise. + * + * @param port the port to be resolved + * + * @return the given port or the defaultPort + */ + public int resolvePort(int port) { + return port <= 0 ? getDefaultPort() : port; + } + + /** + * Return a string representation of this object. + * @return a string representation of this object. + */ + public String toString() { + return scheme + ":" + defaultPort; + } + + /** + * Return true if the specified object equals this object. + * @param obj The object to compare against. + * @return true if the objects are equal. + */ + public boolean equals(Object obj) { + + if (obj instanceof Protocol) { + + Protocol p = (Protocol) obj; + + return ( + defaultPort == p.getDefaultPort() + && scheme.equalsIgnoreCase(p.getScheme()) + && secure == p.isSecure() + && socketFactory.equals(p.getSocketFactory())); + + } else { + return false; + } + + } + + /** + * Return a hash code for this object + * @return The hash code. + */ + public int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.defaultPort); + hash = LangUtils.hashCode(hash, this.scheme.toLowerCase()); + hash = LangUtils.hashCode(hash, this.secure); + hash = LangUtils.hashCode(hash, this.socketFactory); + return hash; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ProtocolSocketFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ProtocolSocketFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ProtocolSocketFactory.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,123 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ProtocolSocketFactory.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.protocol; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.params.HttpConnectionParams; + +/** + * A factory for creating Sockets. + * + *

      Both {@link java.lang.Object#equals(java.lang.Object) Object.equals()} and + * {@link java.lang.Object#hashCode() Object.hashCode()} should be overridden appropriately. + * Protocol socket factories are used to uniquely identify Protocols and + * HostConfigurations, and equals() and hashCode() are + * required for the correct operation of some connection managers.

      + * + * @see Protocol + * + * @author Michael Becke + * @author Mike Bowler + * + * @since 2.0 + */ +public interface ProtocolSocketFactory { + + /** + * Gets a new socket connection to the given host. + * + * @param host the host name/IP + * @param port the port on the host + * @param localAddress the local host name/IP to bind the socket to + * @param localPort the port on the local machine + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + Socket createSocket( + String host, + int port, + InetAddress localAddress, + int localPort + ) throws IOException, UnknownHostException; + + /** + * Gets a new socket connection to the given host. + * + * @param host the host name/IP + * @param port the port on the host + * @param localAddress the local host name/IP to bind the socket to + * @param localPort the port on the local machine + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + * @throws ConnectTimeoutException if socket cannot be connected within the + * given time limit + * + * @since 3.0 + */ + Socket createSocket( + String host, + int port, + InetAddress localAddress, + int localPort, + HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException; + + /** + * Gets a new socket connection to the given host. + * + * @param host the host name/IP + * @param port the port on the host + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + Socket createSocket( + String host, + int port + ) throws IOException, UnknownHostException; + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ReflectionSocketFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ReflectionSocketFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ReflectionSocketFactory.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,168 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/ReflectionSocketFactory.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.protocol; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import org.apache.commons.httpclient.ConnectTimeoutException; + +/** + * This helper class uses refelction in order to execute Socket methods + * available in Java 1.4 and above + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public final class ReflectionSocketFactory { + + private static boolean REFLECTION_FAILED = false; + + private static Constructor INETSOCKETADDRESS_CONSTRUCTOR = null; + private static Method SOCKETCONNECT_METHOD = null; + private static Method SOCKETBIND_METHOD = null; + private static Class SOCKETTIMEOUTEXCEPTION_CLASS = null; + + private ReflectionSocketFactory() { + super(); + } + + /** + * This method attempts to execute Socket method available since Java 1.4 + * using reflection. If the methods are not available or could not be executed + * null is returned + * + * @param socketfactoryName name of the socket factory class + * @param host the host name/IP + * @param port the port on the host + * @param localAddress the local host name/IP to bind the socket to + * @param localPort the port on the local machine + * @param timeout the timeout value to be used in milliseconds. If the socket cannot be + * completed within the given time limit, it will be abandoned + * + * @return a connected Socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + * @throws ConnectTimeoutException if socket cannot be connected within the + * given time limit + * + */ + public static Socket createSocket( + final String socketfactoryName, + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + int timeout) + throws IOException, UnknownHostException, ConnectTimeoutException + { + if (REFLECTION_FAILED) { + //This is known to have failed before. Do not try it again + return null; + } + // This code uses reflection to essentially do the following: + // + // SocketFactory socketFactory = Class.forName(socketfactoryName).getDefault(); + // Socket socket = socketFactory.createSocket(); + // SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); + // SocketAddress remoteaddr = new InetSocketAddress(host, port); + // socket.bind(localaddr); + // socket.connect(remoteaddr, timeout); + // return socket; + try { + Class socketfactoryClass = Class.forName(socketfactoryName); + Method method = socketfactoryClass.getMethod("getDefault", + new Class[] {}); + Object socketfactory = method.invoke(null, + new Object[] {}); + method = socketfactoryClass.getMethod("createSocket", + new Class[] {}); + Socket socket = (Socket) method.invoke(socketfactory, new Object[] {}); + + if (INETSOCKETADDRESS_CONSTRUCTOR == null) { + Class addressClass = Class.forName("java.net.InetSocketAddress"); + INETSOCKETADDRESS_CONSTRUCTOR = addressClass.getConstructor( + new Class[] { InetAddress.class, Integer.TYPE }); + } + + Object remoteaddr = INETSOCKETADDRESS_CONSTRUCTOR.newInstance( + new Object[] { InetAddress.getByName(host), new Integer(port)}); + + Object localaddr = INETSOCKETADDRESS_CONSTRUCTOR.newInstance( + new Object[] { localAddress, new Integer(localPort)}); + + if (SOCKETCONNECT_METHOD == null) { + SOCKETCONNECT_METHOD = Socket.class.getMethod("connect", + new Class[] {Class.forName("java.net.SocketAddress"), Integer.TYPE}); + } + + if (SOCKETBIND_METHOD == null) { + SOCKETBIND_METHOD = Socket.class.getMethod("bind", + new Class[] {Class.forName("java.net.SocketAddress")}); + } + SOCKETBIND_METHOD.invoke(socket, new Object[] { localaddr}); + SOCKETCONNECT_METHOD.invoke(socket, new Object[] { remoteaddr, new Integer(timeout)}); + return socket; + } + catch (InvocationTargetException e) { + Throwable cause = e.getTargetException(); + if (SOCKETTIMEOUTEXCEPTION_CLASS == null) { + try { + SOCKETTIMEOUTEXCEPTION_CLASS = Class.forName("java.net.SocketTimeoutException"); + } catch (ClassNotFoundException ex) { + // At this point this should never happen. Really. + REFLECTION_FAILED = true; + return null; + } + } + if (SOCKETTIMEOUTEXCEPTION_CLASS.isInstance(cause)) { + throw new ConnectTimeoutException( + "The host did not accept the connection within timeout of " + + timeout + " ms", cause); + } + if (cause instanceof IOException) { + throw (IOException)cause; + } + return null; + } + catch (Exception e) { + REFLECTION_FAILED = true; + return null; + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,181 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.protocol; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import javax.net.ssl.SSLSocketFactory; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.params.HttpConnectionParams; + +/** + * A SecureProtocolSocketFactory that uses JSSE to create sockets. + * + * @author Michael Becke + * @author Mike Bowler + * + * @since 2.0 + */ +public class SSLProtocolSocketFactory implements SecureProtocolSocketFactory { + + /** + * The factory singleton. + */ + private static final SSLProtocolSocketFactory factory = new SSLProtocolSocketFactory(); + + /** + * Gets an singleton instance of the SSLProtocolSocketFactory. + * @return a SSLProtocolSocketFactory + */ + static SSLProtocolSocketFactory getSocketFactory() { + return factory; + } + + /** + * Constructor for SSLProtocolSocketFactory. + */ + public SSLProtocolSocketFactory() { + super(); + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket( + String host, + int port, + InetAddress clientHost, + int clientPort) + throws IOException, UnknownHostException { + return SSLSocketFactory.getDefault().createSocket( + host, + port, + clientHost, + clientPort + ); + } + + /** + * Attempts to get a new socket connection to the given host within the given time limit. + *

      + * This method employs several techniques to circumvent the limitations of older JREs that + * do not support connect timeout. When running in JRE 1.4 or above reflection is used to + * call Socket#connect(SocketAddress endpoint, int timeout) method. When executing in older + * JREs a controller thread is executed. The controller thread attempts to create a new socket + * within the given limit of time. If socket constructor does not return until the timeout + * expires, the controller terminates and throws an {@link ConnectTimeoutException} + *

      + * + * @param host the host name/IP + * @param port the port on the host + * @param localAddress the local host name/IP to bind the socket to + * @param localPort the port on the local machine + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + * + * @since 3.0 + */ + public Socket createSocket( + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + final HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + int timeout = params.getConnectionTimeout(); + if (timeout == 0) { + return createSocket(host, port, localAddress, localPort); + } else { + // To be eventually deprecated when migrated to Java 1.4 or above + Socket socket = ReflectionSocketFactory.createSocket( + "javax.net.ssl.SSLSocketFactory", host, port, localAddress, localPort, timeout); + if (socket == null) { + socket = ControllerThreadSocketFactory.createSocket( + this, host, port, localAddress, localPort, timeout); + } + return socket; + } + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException { + return SSLSocketFactory.getDefault().createSocket( + host, + port + ); + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) + */ + public Socket createSocket( + Socket socket, + String host, + int port, + boolean autoClose) + throws IOException, UnknownHostException { + return ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket( + socket, + host, + port, + autoClose + ); + } + + /** + * All instances of SSLProtocolSocketFactory are the same. + */ + public boolean equals(Object obj) { + return ((obj != null) && obj.getClass().equals(SSLProtocolSocketFactory.class)); + } + + /** + * All instances of SSLProtocolSocketFactory have the same hash code. + */ + public int hashCode() { + return SSLProtocolSocketFactory.class.hashCode(); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory.java 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,71 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory.java,v 1.1 2012/08/22 17:30:37 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:37 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.protocol; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * A ProtocolSocketFactory that is secure. + * + * @see org.apache.commons.httpclient.protocol.ProtocolSocketFactory + * + * @author Michael Becke + * @author Mike Bowler + * @since 2.0 + */ +public interface SecureProtocolSocketFactory extends ProtocolSocketFactory { + + /** + * Returns a socket connected to the given host that is layered over an + * existing socket. Used primarily for creating secure sockets through + * proxies. + * + * @param socket the existing socket + * @param host the host name/IP + * @param port the port on the host + * @param autoClose a flag for closing the underling socket when the created + * socket is closed + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + Socket createSocket( + Socket socket, + String host, + int port, + boolean autoClose + ) throws IOException, UnknownHostException; + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/protocol/package.html 22 Aug 2012 17:30:37 -0000 1.1 @@ -0,0 +1,11 @@ + + + + Package Documentation for org.apache.commons.httpclient.protocol + + + Provides protocol specific socket factory handling. + + @since 2.0 + + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParseException.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParseException.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParseException.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,56 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParseException.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + + +/** + * An exception to indicate an error parsing a date string. + * + * @see DateUtil + * + * @author Michael Becke + */ +public class DateParseException extends Exception { + + /** + * + */ + public DateParseException() { + super(); + } + + /** + * @param message the exception message + */ + public DateParseException(String message) { + super(message); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParser.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParser.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParser.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,141 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateParser.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.Locale; +import java.util.TimeZone; + +/** + * A utility class for parsing 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. + * + * @author Christopher Brown + * @author Michael Becke + * + * @deprecated Use {@link org.apache.commons.httpclient.util.DateUtil} + */ +public class DateParser { + + /** + * 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 = "EEEE, dd-MMM-yy HH:mm:ss zzz"; + + /** + * Date format pattern used to parse HTTP date headers in ANSI C + * asctime() format. + */ + public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy"; + + private static final Collection DEFAULT_PATTERNS = Arrays.asList( + new String[] { PATTERN_ASCTIME, PATTERN_RFC1036, PATTERN_RFC1123 } ); + /** + * 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 + * + * @throws DateParseException if the value could not be parsed using any of the + * supported date formats + */ + public static Date parseDate(String dateValue) throws DateParseException { + return parseDate(dateValue, 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 + * + * @throws DateParseException if none of the dataFormats could parse the dateValue + */ + public static Date parseDate( + String dateValue, + Collection dateFormats + ) throws DateParseException { + + if (dateValue == null) { + throw new IllegalArgumentException("dateValue is null"); + } + if (dateFormats == null) { + dateFormats = DEFAULT_PATTERNS; + } + // trim single quotes around date if present + // see issue #5279 + if (dateValue.length() > 1 + && dateValue.startsWith("'") + && dateValue.endsWith("'") + ) { + dateValue = dateValue.substring (1, dateValue.length() - 1); + } + + SimpleDateFormat dateParser = null; + Iterator formatIter = dateFormats.iterator(); + + while (formatIter.hasNext()) { + String format = (String) formatIter.next(); + if (dateParser == null) { + dateParser = new SimpleDateFormat(format, Locale.US); + dateParser.setTimeZone(TimeZone.getTimeZone("GMT")); + } else { + dateParser.applyPattern(format); + } + try { + return dateParser.parse(dateValue); + } catch (ParseException pe) { + // ignore this exception, we will try the next format + } + } + + // we were unable to parse the date + throw new DateParseException("Unable to parse the date " + dateValue); + } + + /** This class should not be instantiated. */ + private DateParser() { } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateUtil.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateUtil.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateUtil.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,209 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/DateUtil.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.Locale; +import java.util.TimeZone; + +/** + * 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. + * + * @author Christopher Brown + * @author Michael Becke + */ +public class DateUtil { + + /** + * 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 = "EEEE, dd-MMM-yy HH:mm:ss zzz"; + + /** + * Date format pattern used to parse HTTP date headers in ANSI C + * asctime() format. + */ + public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy"; + + private static final Collection DEFAULT_PATTERNS = Arrays.asList( + new String[] { PATTERN_ASCTIME, PATTERN_RFC1036, PATTERN_RFC1123 } ); + + private static final Date DEFAULT_TWO_DIGIT_YEAR_START; + + static { + Calendar calendar = Calendar.getInstance(); + calendar.set(2000, Calendar.JANUARY, 1, 0, 0); + DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime(); + } + + private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); + + /** + * 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 + * + * @throws DateParseException if the value could not be parsed using any of the + * supported date formats + */ + public static Date parseDate(String dateValue) throws DateParseException { + 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 + * + * @throws DateParseException if none of the dataFormats could parse the dateValue + */ + public static Date parseDate(String dateValue, Collection dateFormats) + throws DateParseException { + 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 + * startDate to startDate + 100 years. This value may + * be null. When null is given as a parameter, year + * 2000 will be used. + * + * @return the parsed date + * + * @throws DateParseException if none of the dataFormats could parse the dateValue + */ + public static Date parseDate( + String dateValue, + Collection dateFormats, + Date startDate + ) throws DateParseException { + + if (dateValue == null) { + throw new IllegalArgumentException("dateValue is null"); + } + if (dateFormats == null) { + dateFormats = DEFAULT_PATTERNS; + } + if (startDate == null) { + startDate = DEFAULT_TWO_DIGIT_YEAR_START; + } + // trim single quotes around date if present + // see issue #5279 + if (dateValue.length() > 1 + && dateValue.startsWith("'") + && dateValue.endsWith("'") + ) { + dateValue = dateValue.substring (1, dateValue.length() - 1); + } + + SimpleDateFormat dateParser = null; + Iterator formatIter = dateFormats.iterator(); + + while (formatIter.hasNext()) { + String format = (String) formatIter.next(); + if (dateParser == null) { + dateParser = new SimpleDateFormat(format, Locale.US); + dateParser.setTimeZone(TimeZone.getTimeZone("GMT")); + dateParser.set2DigitYearStart(startDate); + } else { + dateParser.applyPattern(format); + } + try { + return dateParser.parse(dateValue); + } catch (ParseException pe) { + // ignore this exception, we will try the next format + } + } + + // we were unable to parse the date + throw new DateParseException("Unable to parse the date " + dateValue); + } + + /** + * 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(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(Date date, String pattern) { + if (date == null) throw new IllegalArgumentException("date is null"); + if (pattern == null) throw new IllegalArgumentException("pattern is null"); + + SimpleDateFormat formatter = new SimpleDateFormat(pattern, Locale.US); + formatter.setTimeZone(GMT); + return formatter.format(date); + } + + /** This class should not be instantiated. */ + private DateUtil() { } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/EncodingUtil.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/EncodingUtil.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/EncodingUtil.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,287 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/EncodingUtil.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ +package org.apache.commons.httpclient.util; + +import java.io.UnsupportedEncodingException; + +import org.apache.commons.codec.net.URLCodec; +import org.apache.commons.httpclient.HttpClientError; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The home for utility methods that handle various encoding tasks. + * + * @author Michael Becke + * @author Oleg Kalnichevski + * + * @since 2.0 final + */ +public class EncodingUtil { + + /** Default content encoding chatset */ + private static final String DEFAULT_CHARSET = "ISO-8859-1"; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(EncodingUtil.class); + + /** + * Form-urlencoding routine. + * + * The default encoding for all forms is `application/x-www-form-urlencoded'. + * A form data set is represented in this media type as follows: + * + * The form field names and values are escaped: space characters are replaced + * by `+', and then reserved characters are escaped as per [URL]; that is, + * non-alphanumeric characters are replaced by `%HH', a percent sign and two + * hexadecimal digits representing the ASCII code of the character. Line breaks, + * as in multi-line text field values, are represented as CR LF pairs, i.e. `%0D%0A'. + * + *

      + * if the given charset is not supported, ISO-8859-1 is used instead. + *

      + * + * @param pairs the values to be encoded + * @param charset the character set of pairs to be encoded + * + * @return the urlencoded pairs + * + * @since 2.0 final + */ + public static String formUrlEncode(NameValuePair[] pairs, String charset) { + try { + return doFormUrlEncode(pairs, charset); + } catch (UnsupportedEncodingException e) { + LOG.error("Encoding not supported: " + charset); + try { + return doFormUrlEncode(pairs, DEFAULT_CHARSET); + } catch (UnsupportedEncodingException fatal) { + // Should never happen. ISO-8859-1 must be supported on all JVMs + throw new HttpClientError("Encoding not supported: " + + DEFAULT_CHARSET); + } + } + } + + /** + * Form-urlencoding routine. + * + * The default encoding for all forms is `application/x-www-form-urlencoded'. + * A form data set is represented in this media type as follows: + * + * The form field names and values are escaped: space characters are replaced + * by `+', and then reserved characters are escaped as per [URL]; that is, + * non-alphanumeric characters are replaced by `%HH', a percent sign and two + * hexadecimal digits representing the ASCII code of the character. Line breaks, + * as in multi-line text field values, are represented as CR LF pairs, i.e. `%0D%0A'. + * + * @param pairs the values to be encoded + * @param charset the character set of pairs to be encoded + * + * @return the urlencoded pairs + * @throws UnsupportedEncodingException if charset is not supported + * + * @since 2.0 final + */ + private static String doFormUrlEncode(NameValuePair[] pairs, String charset) + throws UnsupportedEncodingException + { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < pairs.length; i++) { + URLCodec codec = new URLCodec(); + NameValuePair pair = pairs[i]; + if (pair.getName() != null) { + if (i > 0) { + buf.append("&"); + } + buf.append(codec.encode(pair.getName(), charset)); + buf.append("="); + if (pair.getValue() != null) { + buf.append(codec.encode(pair.getValue(), charset)); + } + } + } + return buf.toString(); + } + + /** + * Converts the byte array of HTTP content characters to a string. If + * the specified charset is not supported, default system encoding + * is used. + * + * @param data the byte array to be encoded + * @param offset the index of the first byte to encode + * @param length the number of bytes to encode + * @param charset the desired character encoding + * @return The result of the conversion. + * + * @since 3.0 + */ + public static String getString( + final byte[] data, + int offset, + int length, + String charset + ) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + if (charset == null || charset.length() == 0) { + throw new IllegalArgumentException("charset may not be null or empty"); + } + + try { + return new String(data, offset, length, charset); + } catch (UnsupportedEncodingException e) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + charset + ". System encoding used"); + } + return new String(data, offset, length); + } + } + + + /** + * Converts the byte array of HTTP content characters to a string. If + * the specified charset is not supported, default system encoding + * is used. + * + * @param data the byte array to be encoded + * @param charset the desired character encoding + * @return The result of the conversion. + * + * @since 3.0 + */ + public static String getString(final byte[] data, String charset) { + return getString(data, 0, data.length, charset); + } + + /** + * Converts the specified string to a byte array. If the charset is not supported the + * default system charset is used. + * + * @param data the string to be encoded + * @param charset the desired character encoding + * @return The resulting byte array. + * + * @since 3.0 + */ + public static byte[] getBytes(final String data, String charset) { + + if (data == null) { + throw new IllegalArgumentException("data may not be null"); + } + + if (charset == null || charset.length() == 0) { + throw new IllegalArgumentException("charset may not be null or empty"); + } + + try { + return data.getBytes(charset); + } catch (UnsupportedEncodingException e) { + + if (LOG.isWarnEnabled()) { + LOG.warn("Unsupported encoding: " + charset + ". System encoding used."); + } + + return data.getBytes(); + } + } + + /** + * Converts the specified string to byte array of ASCII characters. + * + * @param data the string to be encoded + * @return The string as a byte array. + * + * @since 3.0 + */ + public static byte[] getAsciiBytes(final String data) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + try { + return data.getBytes("US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new HttpClientError("HttpClient requires ASCII support"); + } + } + + /** + * Converts the byte array of ASCII characters to a string. This method is + * to be used when decoding content of HTTP elements (such as response + * headers) + * + * @param data the byte array to be encoded + * @param offset the index of the first byte to encode + * @param length the number of bytes to encode + * @return The string representation of the byte array + * + * @since 3.0 + */ + public static String getAsciiString(final byte[] data, int offset, int length) { + + if (data == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + + try { + return new String(data, offset, length, "US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new HttpClientError("HttpClient requires ASCII support"); + } + } + + /** + * Converts the byte array of ASCII characters to a string. This method is + * to be used when decoding content of HTTP elements (such as response + * headers) + * + * @param data the byte array to be encoded + * @return The string representation of the byte array + * + * @since 3.0 + */ + public static String getAsciiString(final byte[] data) { + return getAsciiString(data, 0, data.length); + } + + /** + * This class should not be instantiated. + */ + private EncodingUtil() { + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ExceptionUtil.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ExceptionUtil.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ExceptionUtil.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,121 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ExceptionUtil.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ +package org.apache.commons.httpclient.util; + +import java.io.InterruptedIOException; +import java.lang.reflect.Method; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The home for utility methods that handle various exception-related tasks. + * + * @author Oleg Kalnichevski + * @author Laura Werner + * + * @since 3.0 + */ +public class ExceptionUtil { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(ExceptionUtil.class); + + /** A reference to Throwable's initCause method, or null if it's not there in this JVM */ + static private final Method INIT_CAUSE_METHOD = getInitCauseMethod(); + + /** A reference to SocketTimeoutExceptionClass class, or null if it's not there in this JVM */ + static private final Class SOCKET_TIMEOUT_CLASS = SocketTimeoutExceptionClass(); + + /** + * Returns a Method allowing access to + * {@link Throwable.initCause(Throwable) initCause} method of {@link Throwable}, + * or null if the method + * does not exist. + * + * @return A Method for Throwable.initCause, or + * null if unavailable. + */ + static private Method getInitCauseMethod() { + try { + Class[] paramsClasses = new Class[] { Throwable.class }; + return Throwable.class.getMethod("initCause", paramsClasses); + } catch (NoSuchMethodException e) { + return null; + } + } + + /** + * Returns SocketTimeoutExceptionClass or null if the class + * does not exist. + * + * @return SocketTimeoutExceptionClass, or null if unavailable. + */ + static private Class SocketTimeoutExceptionClass() { + try { + return Class.forName("java.net.SocketTimeoutException"); + } catch (ClassNotFoundException e) { + return null; + } + } + + /** + * If we're running on JDK 1.4 or later, initialize the cause for the given throwable. + * + * @param throwable The throwable. + * @param cause The cause of the throwable. + */ + public static void initCause(Throwable throwable, Throwable cause) { + if (INIT_CAUSE_METHOD != null) { + try { + INIT_CAUSE_METHOD.invoke(throwable, new Object[] { cause }); + } catch (Exception e) { + LOG.warn("Exception invoking Throwable.initCause", e); + } + } + } + + /** + * If SocketTimeoutExceptionClass is defined, returns true only if the + * exception is an instance of SocketTimeoutExceptionClass. If + * SocketTimeoutExceptionClass is undefined, always returns true. + * + * @param e an instance of InterruptedIOException class. + * + * @return true if the exception signals socket timeout, false + * otherwise. + */ + public static boolean isSocketTimeoutException(final InterruptedIOException e) { + if (SOCKET_TIMEOUT_CLASS != null) { + return SOCKET_TIMEOUT_CLASS.isInstance(e); + } else { + return true; + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/HttpURLConnection.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/HttpURLConnection.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/HttpURLConnection.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,503 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/HttpURLConnection.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.Header; + +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.Log; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.ProtocolException; +import java.security.Permission; + +/** + * Provides a HttpURLConnection wrapper around HttpClient's + * HttpMethod. This allows existing code to easily switch to + * HttpClieht without breaking existing interfaces using the JDK + * HttpURLConnection. + * + * Note 1: The current implementations wraps only a connected + * HttpMethod, ie a method that has alreayd been used to connect + * to an HTTP server. + * + * Note 2: It is a best try effort as different version of the JDK have + * different behaviours for HttpURLConnection (And I'm not even + * including the numerous HttpURLConnection bugs!). + * + * @author Vincent Massol + * @author Jeff Dever + * @author Mike Bowler + * + * @since 2.0 + * + * @version $Id: HttpURLConnection.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + */ +public class HttpURLConnection extends java.net.HttpURLConnection { + + // -------------------------------------------------------- Class Variables + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(HttpURLConnection.class); + + + // ----------------------------------------------------- Instance Variables + + /** + * The HttpMethod object that was used to connect to the + * HTTP server. It contains all the returned data. + */ + private HttpMethod method; + + /** + * The URL to which we are connected + */ + private URL url; + + + + // ----------------------------------------------------------- Constructors + + /** + * Creates an HttpURLConnection from a HttpMethod. + * + * @param method the theMethod that was used to connect to the HTTP + * server and which contains the returned data. + * @param url the URL to which we are connected (includes query string) + */ + public HttpURLConnection(HttpMethod method, URL url) { + super(url); + this.method = method; + this.url = url; + } + + /** + * Create an instance. + * @param url The URL. + * @see java.net.HttpURLConnection#HttpURLConnection(URL) + */ + protected HttpURLConnection(URL url) { + super(url); + throw new RuntimeException("An HTTP URL connection can only be " + + "constructed from a HttpMethod class"); + } + + + // --------------------------------------------------------- Public Methods + + /** + * Gets an input stream for the HttpMethod response body. + * @throws IOException If an IO problem occurs. + * @return The input stream. + * @see java.net.HttpURLConnection#getInputStream() + * @see org.apache.commons.httpclient.HttpMethod#getResponseBodyAsStream() + */ + public InputStream getInputStream() throws IOException { + LOG.trace("enter HttpURLConnection.getInputStream()"); + return this.method.getResponseBodyAsStream(); + } + + /** + * Not yet implemented. + * Return the error stream. + * @see java.net.HttpURLConnection#getErrorStream() + */ + public InputStream getErrorStream() { + LOG.trace("enter HttpURLConnection.getErrorStream()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#disconnect() + */ + public void disconnect() { + LOG.trace("enter HttpURLConnection.disconnect()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @throws IOException If an IO problem occurs. + * @see java.net.HttpURLConnection#connect() + */ + public void connect() throws IOException { + LOG.trace("enter HttpURLConnection.connect()"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @return true if we are using a proxy. + * @see java.net.HttpURLConnection#usingProxy() + */ + public boolean usingProxy() { + LOG.trace("enter HttpURLConnection.usingProxy()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Return the request method. + * @return The request method. + * @see java.net.HttpURLConnection#getRequestMethod() + * @see org.apache.commons.httpclient.HttpMethod#getName() + */ + public String getRequestMethod() { + LOG.trace("enter HttpURLConnection.getRequestMethod()"); + return this.method.getName(); + } + + /** + * Return the response code. + * @return The response code. + * @throws IOException If an IO problem occurs. + * @see java.net.HttpURLConnection#getResponseCode() + * @see org.apache.commons.httpclient.HttpMethod#getStatusCode() + */ + public int getResponseCode() throws IOException { + LOG.trace("enter HttpURLConnection.getResponseCode()"); + return this.method.getStatusCode(); + } + + /** + * Return the response message + * @return The response message + * @throws IOException If an IO problem occurs. + * @see java.net.HttpURLConnection#getResponseMessage() + * @see org.apache.commons.httpclient.HttpMethod#getStatusText() + */ + public String getResponseMessage() throws IOException { + LOG.trace("enter HttpURLConnection.getResponseMessage()"); + return this.method.getStatusText(); + } + + /** + * Return the header field + * @param name the name of the header + * @return the header field. + * @see java.net.HttpURLConnection#getHeaderField(String) + * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders() + */ + public String getHeaderField(String name) { + LOG.trace("enter HttpURLConnection.getHeaderField(String)"); + // Note: Return the last matching header in the Header[] array, as in + // the JDK implementation. + Header[] headers = this.method.getResponseHeaders(); + for (int i = headers.length - 1; i >= 0; i--) { + if (headers[i].getName().equalsIgnoreCase(name)) { + return headers[i].getValue(); + } + } + + return null; + } + + /** + * Return the header field key + * @param keyPosition The key position + * @return The header field key. + * @see java.net.HttpURLConnection#getHeaderFieldKey(int) + * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders() + */ + public String getHeaderFieldKey(int keyPosition) { + LOG.trace("enter HttpURLConnection.getHeaderFieldKey(int)"); + + // Note: HttpClient does not consider the returned Status Line as + // a response header. However, getHeaderFieldKey(0) is supposed to + // return null. Hence the special case below ... + + if (keyPosition == 0) { + return null; + } + + // Note: HttpClient does not currently keep headers in the same order + // that they are read from the HTTP server. + + Header[] headers = this.method.getResponseHeaders(); + if (keyPosition < 0 || keyPosition > headers.length) { + return null; + } + + return headers[keyPosition - 1].getName(); + } + + /** + * Return the header field at the specified position + * @param position The position + * @return The header field. + * @see java.net.HttpURLConnection#getHeaderField(int) + * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders() + */ + public String getHeaderField(int position) { + LOG.trace("enter HttpURLConnection.getHeaderField(int)"); + + // Note: HttpClient does not consider the returned Status Line as + // a response header. However, getHeaderField(0) is supposed to + // return the status line. Hence the special case below ... + + if (position == 0) { + return this.method.getStatusLine().toString(); + } + + // Note: HttpClient does not currently keep headers in the same order + // that they are read from the HTTP server. + + Header[] headers = this.method.getResponseHeaders(); + if (position < 0 || position > headers.length) { + return null; + } + + return headers[position - 1].getValue(); + } + + /** + * Return the URL + * @return The URL. + * @see java.net.HttpURLConnection#getURL() + */ + public URL getURL() { + LOG.trace("enter HttpURLConnection.getURL()"); + return this.url; + } + + // Note: We don't implement the following methods so that they default to + // the JDK implementation. They will all call + // getHeaderField(String) which we have overridden. + + // java.net.HttpURLConnection#getHeaderFieldDate(String, long) + // java.net.HttpURLConnection#getContentLength() + // java.net.HttpURLConnection#getContentType() + // java.net.HttpURLConnection#getContentEncoding() + // java.net.HttpURLConnection#getDate() + // java.net.HttpURLConnection#getHeaderFieldInt(String, int) + // java.net.HttpURLConnection#getExpiration() + // java.net.HttpURLConnection#getLastModified() + + /** + * Not available: the data must have already been retrieved. + */ + public void setInstanceFollowRedirects(boolean isFollowingRedirects) { + LOG.trace("enter HttpURLConnection.setInstanceFollowRedirects(boolean)"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + */ + public boolean getInstanceFollowRedirects() { + LOG.trace("enter HttpURLConnection.getInstanceFollowRedirects()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setRequestMethod(String) + */ + public void setRequestMethod(String method) throws ProtocolException { + LOG.trace("enter HttpURLConnection.setRequestMethod(String)"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getPermission() + */ + public Permission getPermission() throws IOException { + LOG.trace("enter HttpURLConnection.getPermission()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getContent() + */ + public Object getContent() throws IOException { + LOG.trace("enter HttpURLConnection.getContent()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not yet implemented. + */ + public Object getContent(Class[] classes) throws IOException { + LOG.trace("enter HttpURLConnection.getContent(Class[])"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * @see java.net.HttpURLConnection#getOutputStream() + */ + public OutputStream getOutputStream() throws IOException { + LOG.trace("enter HttpURLConnection.getOutputStream()"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setDoInput(boolean) + */ + public void setDoInput(boolean isInput) { + LOG.trace("enter HttpURLConnection.setDoInput()"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getDoInput() + */ + public boolean getDoInput() { + LOG.trace("enter HttpURLConnection.getDoInput()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setDoOutput(boolean) + */ + public void setDoOutput(boolean isOutput) { + LOG.trace("enter HttpURLConnection.setDoOutput()"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getDoOutput() + */ + public boolean getDoOutput() { + LOG.trace("enter HttpURLConnection.getDoOutput()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setAllowUserInteraction(boolean) + */ + public void setAllowUserInteraction(boolean isAllowInteraction) { + LOG.trace("enter HttpURLConnection.setAllowUserInteraction(boolean)"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getAllowUserInteraction() + */ + public boolean getAllowUserInteraction() { + LOG.trace("enter HttpURLConnection.getAllowUserInteraction()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setUseCaches(boolean) + */ + public void setUseCaches(boolean isUsingCaches) { + LOG.trace("enter HttpURLConnection.setUseCaches(boolean)"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getUseCaches() + */ + public boolean getUseCaches() { + LOG.trace("enter HttpURLConnection.getUseCaches()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setIfModifiedSince(long) + */ + public void setIfModifiedSince(long modificationDate) { + LOG.trace("enter HttpURLConnection.setIfModifiedSince(long)"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getIfModifiedSince() + */ + public long getIfModifiedSince() { + LOG.trace("enter HttpURLConnection.getIfmodifiedSince()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#getDefaultUseCaches() + */ + public boolean getDefaultUseCaches() { + LOG.trace("enter HttpURLConnection.getDefaultUseCaches()"); + throw new RuntimeException("Not implemented yet"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setDefaultUseCaches(boolean) + */ + public void setDefaultUseCaches(boolean isUsingCaches) { + LOG.trace("enter HttpURLConnection.setDefaultUseCaches(boolean)"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not available: the data must have already been retrieved. + * @see java.net.HttpURLConnection#setRequestProperty(String,String) + */ + public void setRequestProperty(String key, String value) { + LOG.trace("enter HttpURLConnection.setRequestProperty()"); + throw new RuntimeException("This class can only be used with already" + + "retrieved data"); + } + + /** + * Not yet implemented. + * @see java.net.HttpURLConnection#getRequestProperty(String) + */ + public String getRequestProperty(String key) { + LOG.trace("enter HttpURLConnection.getRequestProperty()"); + throw new RuntimeException("Not implemented yet"); + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionHandler.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionHandler.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionHandler.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,124 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionHandler.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ +package org.apache.commons.httpclient.util; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A helper class for connection managers to track idle connections. + * + *

      This class is not synchronized.

      + * + * @see org.apache.commons.httpclient.HttpConnectionManager#closeIdleConnections(long) + * + * @since 3.0 + */ +public class IdleConnectionHandler { + + private static final Log LOG = LogFactory.getLog(IdleConnectionHandler.class); + + /** Holds connections and the time they were added. */ + private Map connectionToAdded = new HashMap(); + + /** + * + */ + public IdleConnectionHandler() { + super(); + } + + /** + * Registers the given connection with this handler. The connection will be held until + * {@link #remove(HttpConnection)} or {@link #closeIdleConnections(long)} is called. + * + * @param connection the connection to add + * + * @see #remove(HttpConnection) + */ + public void add(HttpConnection connection) { + + Long timeAdded = new Long(System.currentTimeMillis()); + + if (LOG.isDebugEnabled()) { + LOG.debug("Adding connection at: " + timeAdded); + } + + connectionToAdded.put(connection, timeAdded); + } + + /** + * Removes the given connection from the list of connections to be closed when idle. + * @param connection + */ + public void remove(HttpConnection connection) { + connectionToAdded.remove(connection); + } + + /** + * Removes all connections referenced by this handler. + */ + public void removeAll() { + this.connectionToAdded.clear(); + } + + /** + * Closes connections that have been idle for at least the given amount of time. + * + * @param idleTime the minimum idle time, in milliseconds, for connections to be closed + */ + public void closeIdleConnections(long idleTime) { + + // the latest time for which connections will be closed + long idleTimeout = System.currentTimeMillis() - idleTime; + + if (LOG.isDebugEnabled()) { + LOG.debug("Checking for connections, idleTimeout: " + idleTimeout); + } + + Iterator connectionIter = connectionToAdded.keySet().iterator(); + + while (connectionIter.hasNext()) { + HttpConnection conn = (HttpConnection) connectionIter.next(); + Long connectionTime = (Long) connectionToAdded.get(conn); + if (connectionTime.longValue() <= idleTimeout) { + if (LOG.isDebugEnabled()) { + LOG.debug("Closing connection, connection time: " + connectionTime); + } + connectionIter.remove(); + conn.close(); + } + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionTimeoutThread.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionTimeoutThread.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionTimeoutThread.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,140 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/IdleConnectionTimeoutThread.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ +package org.apache.commons.httpclient.util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.httpclient.HttpConnectionManager; + +/** + * A utility class for periodically closing idle connections. + * + * @see org.apache.commons.httpclient.HttpConnectionManager#closeIdleConnections(long) + * + * @since 3.0 + */ +public class IdleConnectionTimeoutThread extends Thread { + + private List connectionManagers = new ArrayList(); + + private boolean shutdown = false; + + private long timeoutInterval = 1000; + + private long connectionTimeout = 3000; + + public IdleConnectionTimeoutThread() { + setDaemon(true); + } + + /** + * Adds a connection manager to be handled by this class. + * {@link HttpConnectionManager#closeIdleConnections(long)} will be called on the connection + * manager every {@link #setTimeoutInterval(long) timeoutInterval} milliseconds. + * + * @param connectionManager The connection manager to add + */ + public synchronized void addConnectionManager(HttpConnectionManager connectionManager) { + if (shutdown) { + throw new IllegalStateException("IdleConnectionTimeoutThread has been shutdown"); + } + this.connectionManagers.add(connectionManager); + } + + /** + * Removes the connection manager from this class. The idle connections from the connection + * manager will no longer be automatically closed by this class. + * + * @param connectionManager The connection manager to remove + */ + public synchronized void removeConnectionManager(HttpConnectionManager connectionManager) { + if (shutdown) { + throw new IllegalStateException("IdleConnectionTimeoutThread has been shutdown"); + } + this.connectionManagers.remove(connectionManager); + } + + /** + * Closes idle connections. + */ + public synchronized void run() { + while (!shutdown) { + Iterator iter = connectionManagers.iterator(); + + while (iter.hasNext()) { + HttpConnectionManager connectionManager = (HttpConnectionManager) iter.next(); + connectionManager.closeIdleConnections(connectionTimeout); + } + + try { + this.wait(timeoutInterval); + } catch (InterruptedException e) { + } + } + // clear out the connection managers now that we're shutdown + this.connectionManagers.clear(); + } + + /** + * Stops the thread used to close idle connections. This class cannot be used once shutdown. + */ + public synchronized void shutdown() { + this.shutdown = true; + this.notifyAll(); + } + + /** + * Sets the timeout value to use when testing for idle connections. + * + * @param connectionTimeout The connection timeout in milliseconds + * + * @see HttpConnectionManager#closeIdleConnections(long) + */ + public synchronized void setConnectionTimeout(long connectionTimeout) { + if (shutdown) { + throw new IllegalStateException("IdleConnectionTimeoutThread has been shutdown"); + } + this.connectionTimeout = connectionTimeout; + } + /** + * Sets the interval used by this class between closing idle connections. Idle + * connections will be closed every timeoutInterval milliseconds. + * + * @param timeoutInterval The timeout interval in milliseconds + */ + public synchronized void setTimeoutInterval(long timeoutInterval) { + if (shutdown) { + throw new IllegalStateException("IdleConnectionTimeoutThread has been shutdown"); + } + this.timeoutInterval = timeoutInterval; + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/LangUtils.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/LangUtils.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/LangUtils.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,65 @@ +/* + * $HeadURL: http://svn.apache.org/repos/asf/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + +/** + * A set of utility methods to help produce consistent Object#equals(Object) and + * Object#hashCode methods. + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class LangUtils { + + public static final int HASH_SEED = 17; + public static final int HASH_OFFSET = 37; + + private LangUtils() { + super(); + } + + public static int hashCode(final int seed, final int hashcode) { + return seed * HASH_OFFSET + hashcode; + } + + public static int hashCode(final int seed, final Object obj) { + return hashCode(seed, obj != null ? obj.hashCode() : 0); + } + + public static int hashCode(final int seed, final boolean b) { + return hashCode(seed, b ? 1 : 0); + } + + public static boolean equals(final Object obj1, final Object obj2) { + return obj1 == null ? obj2 == null : obj1.equals(obj2); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ParameterFormatter.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ParameterFormatter.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ParameterFormatter.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,241 @@ +/* + * $HeadURL: http://svn.apache.org/repos/asf/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/ParameterFormatter.java $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + +import org.apache.commons.httpclient.NameValuePair; + +/** + *

      + * This formatter produces a textual representation of attribute/value pairs. It + * comforms to the generic grammar and formatting rules outlined in the + * Section 2.1 + * and + * Section 3.6 + * of RFC 2616 + *

      + * 2.1 Augmented BNF + *

      + * Many HTTP/1.1 header field values consist of words separated by LWS or special + * characters. These special characters MUST be in a quoted string to be used within + * a parameter value (as defined in section 3.6). + *

      + *

      + * token          = 1*
      + * separators     = "(" | ")" | "<" | ">" | "@"
      + *                | "," | ";" | ":" | "\" | <">
      + *                | "/" | "[" | "]" | "?" | "="
      + *                | "{" | "}" | SP | HT
      + * 
      + *

      + * A string of text is parsed as a single word if it is quoted using double-quote marks. + *

      + *
      + * quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
      + * qdtext         = >
      + * 
      + *

      + * The backslash character ("\") MAY be used as a single-character quoting mechanism only + * within quoted-string and comment constructs. + *

      + *
      + * quoted-pair    = "\" CHAR
      + * 
      + * 3.6 Transfer Codings + *

      + * Parameters are in the form of attribute/value pairs. + *

      + *
      + * parameter               = attribute "=" value
      + * attribute               = token
      + * value                   = token | quoted-string
      + * 
      + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class ParameterFormatter { + + /** + * Special characters that can be used as separators in HTTP parameters. + * These special characters MUST be in a quoted string to be used within + * a parameter value + */ + private static final char[] SEPARATORS = { + '(', ')', '<', '>', '@', + ',', ';', ':', '\\', '"', + '/', '[', ']', '?', '=', + '{', '}', ' ', '\t' + }; + + /** + * Unsafe special characters that must be escaped using the backslash + * character + */ + private static final char[] UNSAFE_CHARS = { + '"', '\\' + }; + + /** + * This flag determines whether all parameter values must be enclosed in + * quotation marks, even if they do not contain any special characters + */ + private boolean alwaysUseQuotes = true; + + /** Default ParameterFormatter constructor */ + public ParameterFormatter() { + super(); + } + + private static boolean isOneOf(char[] chars, char ch) { + for (int i = 0; i < chars.length; i++) { + if (ch == chars[i]) { + return true; + } + } + return false; + } + + private static boolean isUnsafeChar(char ch) { + return isOneOf(UNSAFE_CHARS, ch); + } + + private static boolean isSeparator(char ch) { + return isOneOf(SEPARATORS, ch); + } + + /** + * Determines whether all parameter values must be enclosed in quotation + * marks, even if they do not contain any special characters + * + * @return true if all parameter values must be enclosed in + * quotation marks, false otherwise + */ + public boolean isAlwaysUseQuotes() { + return alwaysUseQuotes; + } + + /** + * Defines whether all parameter values must be enclosed in quotation + * marks, even if they do not contain any special characters + * + * @param alwaysUseQuotes + */ + public void setAlwaysUseQuotes(boolean alwaysUseQuotes) { + this.alwaysUseQuotes = alwaysUseQuotes; + } + + /** + * Formats the given parameter value using formatting rules defined + * in RFC 2616 + * + * @param buffer output buffer + * @param value the parameter value to be formatted + * @param alwaysUseQuotes true if the parameter value must + * be enclosed in quotation marks, even if it does not contain any special + * characters, false only if the parameter value contains + * potentially unsafe special characters + */ + public static void formatValue( + final StringBuffer buffer, final String value, boolean alwaysUseQuotes) { + if (buffer == null) { + throw new IllegalArgumentException("String buffer may not be null"); + } + if (value == null) { + throw new IllegalArgumentException("Value buffer may not be null"); + } + if (alwaysUseQuotes) { + buffer.append('"'); + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + if (isUnsafeChar(ch)) { + buffer.append('\\'); + } + buffer.append(ch); + } + buffer.append('"'); + } else { + int offset = buffer.length(); + boolean unsafe = false; + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + if (isSeparator(ch)) { + unsafe = true; + } + if (isUnsafeChar(ch)) { + buffer.append('\\'); + } + buffer.append(ch); + } + if (unsafe) { + buffer.insert(offset, '"'); + buffer.append('"'); + } + } + } + + /** + * Produces textual representaion of the attribute/value pair using + * formatting rules defined in RFC 2616 + * + * @param buffer output buffer + * @param param the parameter to be formatted + */ + public void format(final StringBuffer buffer, final NameValuePair param) { + if (buffer == null) { + throw new IllegalArgumentException("String buffer may not be null"); + } + if (param == null) { + throw new IllegalArgumentException("Parameter may not be null"); + } + buffer.append(param.getName()); + String value = param.getValue(); + if (value != null) { + buffer.append("="); + formatValue(buffer, value, this.alwaysUseQuotes); + } + } + + /** + * Produces textual representaion of the attribute/value pair using + * formatting rules defined in RFC 2616 + * + * @param param the parameter to be formatted + * + * @return RFC 2616 conformant textual representaion of the + * attribute/value pair + */ + public String format(final NameValuePair param) { + StringBuffer buffer = new StringBuffer(); + format(buffer, param); + return buffer.toString(); + } + +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ParameterParser.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ParameterParser.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ParameterParser.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,234 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/ParameterParser.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.httpclient.NameValuePair; + +/** + * A simple parser intended to parse sequences of name/value pairs. + * Parameter values are exptected to be enclosed in quotes if they + * contain unsafe characters, such as '=' characters or separators. + * Parameter values are optional and can be omitted. + * + *

      + * param1 = value; param2 = "anything goes; really"; param3 + *

      + * + * @author Oleg Kalnichevski + * + * @since 3.0 + */ +public class ParameterParser { + + /** String to be parsed */ + private char[] chars = null; + + /** Current position in the string */ + private int pos = 0; + + /** Maximum position in the string */ + private int len = 0; + + /** Start of a token */ + private int i1 = 0; + + /** End of a token */ + private int i2 = 0; + + /** Default ParameterParser constructor */ + public ParameterParser() { + super(); + } + + + /** Are there any characters left to parse? */ + private boolean hasChar() { + return this.pos < this.len; + } + + + /** A helper method to process the parsed token. */ + private String getToken(boolean quoted) { + // Trim leading white spaces + while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) { + i1++; + } + // Trim trailing white spaces + while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) { + i2--; + } + // Strip away quotes if necessary + if (quoted) { + if (((i2 - i1) >= 2) + && (chars[i1] == '"') + && (chars[i2 - 1] == '"')) { + i1++; + i2--; + } + } + String result = null; + if (i2 >= i1) { + result = new String(chars, i1, i2 - i1); + } + return result; + } + + + /** Is given character present in the array of characters? */ + private boolean isOneOf(char ch, char[] charray) { + boolean result = false; + for (int i = 0; i < charray.length; i++) { + if (ch == charray[i]) { + result = true; + break; + } + } + return result; + } + + + /** Parse out a token until any of the given terminators + * is encountered. */ + private String parseToken(final char[] terminators) { + char ch; + i1 = pos; + i2 = pos; + while (hasChar()) { + ch = chars[pos]; + if (isOneOf(ch, terminators)) { + break; + } + i2++; + pos++; + } + return getToken(false); + } + + + /** Parse out a token until any of the given terminators + * is encountered. Special characters in quoted tokens + * are escaped. */ + private String parseQuotedToken(final char[] terminators) { + char ch; + i1 = pos; + i2 = pos; + boolean quoted = false; + boolean charEscaped = false; + while (hasChar()) { + ch = chars[pos]; + if (!quoted && isOneOf(ch, terminators)) { + break; + } + if (!charEscaped && ch == '"') { + quoted = !quoted; + } + charEscaped = (!charEscaped && ch == '\\'); + i2++; + pos++; + + } + return getToken(true); + } + + /** + * Extracts a list of {@link NameValuePair}s from the given string. + * + * @param str the string that contains a sequence of name/value pairs + * @return a list of {@link NameValuePair}s + * + */ + public List parse(final String str, char separator) { + + if (str == null) { + return new ArrayList(); + } + return parse(str.toCharArray(), separator); + } + + /** + * Extracts a list of {@link NameValuePair}s from the given array of + * characters. + * + * @param chars the array of characters that contains a sequence of + * name/value pairs + * + * @return a list of {@link NameValuePair}s + */ + public List parse(final char[] chars, char separator) { + + if (chars == null) { + return new ArrayList(); + } + return parse(chars, 0, chars.length, separator); + } + + + /** + * Extracts a list of {@link NameValuePair}s from the given array of + * characters. + * + * @param chars the array of characters that contains a sequence of + * name/value pairs + * @param offset - the initial offset. + * @param length - the length. + * + * @return a list of {@link NameValuePair}s + */ + public List parse(final char[] chars, int offset, int length, char separator) { + + if (chars == null) { + return new ArrayList(); + } + List params = new ArrayList(); + this.chars = chars; + this.pos = offset; + this.len = length; + + String paramName = null; + String paramValue = null; + while (hasChar()) { + paramName = parseToken(new char[] {'=', separator}); + paramValue = null; + if (hasChar() && (chars[pos] == '=')) { + pos++; // skip '=' + paramValue = parseQuotedToken(new char[] {separator}); + } + if (hasChar() && (chars[pos] == separator)) { + pos++; // skip separator + } + if (paramName != null && !(paramName.equals("") && paramValue == null)) { + params.add(new NameValuePair(paramName, paramValue)); + } + } + return params; + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/TimeoutController.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/TimeoutController.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/TimeoutController.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,92 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/TimeoutController.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + +/** + *

      + * Executes a task with a specified timeout. + *

      + * @author Ortwin Glueck + * @author Mike Bowler + * @version $Revision: 1.1 $ + * @since 2.0 + */ +public final class TimeoutController { + + /** + * Do not instantiate objects of this class. Methods are static. + */ + private TimeoutController() { + } + + /** + * Executes task. Waits for timeout + * milliseconds for the task to end and returns. If the task does not return + * in time, the thread is interrupted and an Exception is thrown. + * The caller should override the Thread.interrupt() method to something that + * quickly makes the thread die or use Thread.isInterrupted(). + * @param task The thread to execute + * @param timeout The timeout in milliseconds. 0 means to wait forever. + * @throws TimeoutException if the timeout passes and the thread does not return. + */ + public static void execute(Thread task, long timeout) throws TimeoutException { + task.start(); + try { + task.join(timeout); + } catch (InterruptedException e) { + /* if somebody interrupts us he knows what he is doing */ + } + if (task.isAlive()) { + task.interrupt(); + throw new TimeoutException(); + } + } + + /** + * Executes task in a new deamon Thread and waits for the timeout. + * @param task The task to execute + * @param timeout The timeout in milliseconds. 0 means to wait forever. + * @throws TimeoutException if the timeout passes and the thread does not return. + */ + public static void execute(Runnable task, long timeout) throws TimeoutException { + Thread t = new Thread(task, "Timeout guard"); + t.setDaemon(true); + execute(t, timeout); + } + + /** + * Signals that the task timed out. + */ + public static class TimeoutException extends Exception { + /** Create an instance */ + public TimeoutException() { + } + } +} Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/URIUtil.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/URIUtil.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/URIUtil.java 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,657 @@ +/* + * $Header: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/URIUtil.java,v 1.1 2012/08/22 17:30:38 marcin Exp $ + * $Revision: 1.1 $ + * $Date: 2012/08/22 17:30:38 $ + * + * ==================================================================== + * + * Copyright 2002-2004 The Apache Software Foundation + * + * Licensed 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 + * . + * + */ + +package org.apache.commons.httpclient.util; + +import java.util.BitSet; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.net.URLCodec; +import org.apache.commons.httpclient.URI; +import org.apache.commons.httpclient.URIException; + +/** + * The URI escape and character encoding and decoding utility. + * It's compatible with {@link org.apache.commons.httpclient.HttpURL} rather + * than {@link org.apache.commons.httpclient.URI}. + * + * @author Sung-Gu + * @version $Revision: 1.1 $ $Date: 2002/03/14 15:14:01 + */ +public class URIUtil { + + // ----------------------------------------------------- Instance variables + + protected static final BitSet empty = new BitSet(1); + + // ---------------------------------------------------------- URI utilities + + /** + * Get the basename of an URI. It's possibly an empty string. + * + * @param uri a string regarded an URI + * @return the basename string; an empty string if the path ends with slash + */ + public static String getName(String uri) { + if (uri == null || uri.length() == 0) { return uri; } + String path = URIUtil.getPath(uri); + int at = path.lastIndexOf("/"); + int to = path.length(); + return (at >= 0) ? path.substring(at + 1, to) : path; + } + + + /** + * Get the query of an URI. + * + * @param uri a string regarded an URI + * @return the query string; null if empty or undefined + */ + public static String getQuery(String uri) { + if (uri == null || uri.length() == 0) { return null; } + // consider of net_path + int at = uri.indexOf("//"); + int from = uri.indexOf( + "/", + at >= 0 ? (uri.lastIndexOf("/", at - 1) >= 0 ? 0 : at + 2) : 0 + ); + // the authority part of URI ignored + int to = uri.length(); + // reuse the at and from variables to consider the query + at = uri.indexOf("?", from); + if (at >= 0) { + from = at + 1; + } else { + return null; + } + // check the fragment + if (uri.lastIndexOf("#") > from) { + to = uri.lastIndexOf("#"); + } + // get the path and query. + return (from < 0 || from == to) ? null : uri.substring(from, to); + } + + + /** + * Get the path of an URI. + * + * @param uri a string regarded an URI + * @return the path string + */ + public static String getPath(String uri) { + if (uri == null) { + return null; + } + // consider of net_path + int at = uri.indexOf("//"); + int from = uri.indexOf( + "/", + at >= 0 ? (uri.lastIndexOf("/", at - 1) >= 0 ? 0 : at + 2) : 0 + ); + // the authority part of URI ignored + int to = uri.length(); + // check the query + if (uri.indexOf('?', from) != -1) { + to = uri.indexOf('?', from); + } + // check the fragment + if (uri.lastIndexOf("#") > from && uri.lastIndexOf("#") < to) { + to = uri.lastIndexOf("#"); + } + // get only the path. + return (from < 0) ? (at >= 0 ? "/" : uri) : uri.substring(from, to); + } + + + /** + * Get the path and query of an URI. + * + * @param uri a string regarded an URI + * @return the path and query string + */ + public static String getPathQuery(String uri) { + if (uri == null) { + return null; + } + // consider of net_path + int at = uri.indexOf("//"); + int from = uri.indexOf( + "/", + at >= 0 ? (uri.lastIndexOf("/", at - 1) >= 0 ? 0 : at + 2) : 0 + ); + // the authority part of URI ignored + int to = uri.length(); + // Ignore the '?' mark so to ignore the query. + // check the fragment + if (uri.lastIndexOf("#") > from) { + to = uri.lastIndexOf("#"); + } + // get the path and query. + return (from < 0) ? (at >= 0 ? "/" : uri) : uri.substring(from, to); + } + + + /** + * Get the path of an URI and its rest part. + * + * @param uri a string regarded an URI + * @return the string from the path part + */ + public static String getFromPath(String uri) { + if (uri == null) { + return null; + } + // consider of net_path + int at = uri.indexOf("//"); + int from = uri.indexOf( + "/", + at >= 0 ? (uri.lastIndexOf("/", at - 1) >= 0 ? 0 : at + 2) : 0 + ); + // get the path and its rest. + return (from < 0) ? (at >= 0 ? "/" : uri) : uri.substring(from); + } + + // ----------------------------------------------------- Encoding utilities + + /** + * Get the all escaped and encoded string with the default protocl charset. + * It's the same function to use encode(String unescaped, Bitset + * empty, URI.getDefaultProtocolCharset()). + * + * @param unescaped an unescaped string + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + * @see #encode + */ + public static String encodeAll(String unescaped) throws URIException { + return encodeAll(unescaped, URI.getDefaultProtocolCharset()); + } + + + /** + * Get the all escaped and encoded string with a given charset. + * It's the same function to use encode(String unescaped, Bitset + * empty, String charset). + * + * @param unescaped an unescaped string + * @param charset the charset + * @return the escaped string + * + * @throws URIException if the charset is not supported + * + * @see #encode + */ + public static String encodeAll(String unescaped, String charset) + throws URIException { + + return encode(unescaped, empty, charset); + } + + + /** + * Escape and encode a string regarded as within the authority component of + * an URI with the default protocol charset. + * Within the authority component, the characters ";", ":", "@", "?", and + * "/" are reserved. + * + * @param unescaped an unescaped string + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + * @see #encode + */ + public static String encodeWithinAuthority(String unescaped) + throws URIException { + + return encodeWithinAuthority(unescaped, URI.getDefaultProtocolCharset()); + } + + + /** + * Escape and encode a string regarded as within the authority component of + * an URI with a given charset. + * Within the authority component, the characters ";", ":", "@", "?", and + * "/" are reserved. + * + * @param unescaped an unescaped string + * @param charset the charset + * @return the escaped string + * + * @throws URIException if the charset is not supported + * + * @see #encode + */ + public static String encodeWithinAuthority(String unescaped, String charset) + throws URIException { + + return encode(unescaped, URI.allowed_within_authority, charset); + } + + + /** + * Escape and encode a string regarded as the path and query components of + * an URI with the default protocol charset. + * + * @param unescaped an unescaped string + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + * @see #encode + */ + public static String encodePathQuery(String unescaped) throws URIException { + return encodePathQuery(unescaped, URI.getDefaultProtocolCharset()); + } + + + /** + * Escape and encode a string regarded as the path and query components of + * an URI with a given charset. + * + * @param unescaped an unescaped string + * @param charset the charset + * @return the escaped string + * + * @throws URIException if the charset is not supported + * + * @see #encode + */ + public static String encodePathQuery(String unescaped, String charset) + throws URIException { + + int at = unescaped.indexOf('?'); + if (at < 0) { + return encode(unescaped, URI.allowed_abs_path, charset); + } + // else + return encode(unescaped.substring(0, at), URI.allowed_abs_path, charset) + + '?' + encode(unescaped.substring(at + 1), URI.allowed_query, charset); + } + + + /** + * Escape and encode a string regarded as within the path component of an + * URI with the default protocol charset. + * The path may consist of a sequence of path segments separated by a + * single slash "/" character. Within a path segment, the characters + * "/", ";", "=", and "?" are reserved. + * + * @param unescaped an unescaped string + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + * @see #encode + */ + public static String encodeWithinPath(String unescaped) + throws URIException { + + return encodeWithinPath(unescaped, URI.getDefaultProtocolCharset()); + } + + + /** + * Escape and encode a string regarded as within the path component of an + * URI with a given charset. + * The path may consist of a sequence of path segments separated by a + * single slash "/" character. Within a path segment, the characters + * "/", ";", "=", and "?" are reserved. + * + * @param unescaped an unescaped string + * @param charset the charset + * @return the escaped string + * + * @throws URIException if the charset is not supported + * + * @see #encode + */ + public static String encodeWithinPath(String unescaped, String charset) + throws URIException { + + return encode(unescaped, URI.allowed_within_path, charset); + } + + + /** + * Escape and encode a string regarded as the path component of an URI with + * the default protocol charset. + * + * @param unescaped an unescaped string + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + * @see #encode + */ + public static String encodePath(String unescaped) throws URIException { + return encodePath(unescaped, URI.getDefaultProtocolCharset()); + } + + + /** + * Escape and encode a string regarded as the path component of an URI with + * a given charset. + * + * @param unescaped an unescaped string + * @param charset the charset + * @return the escaped string + * + * @throws URIException if the charset is not supported + * + * @see #encode + */ + public static String encodePath(String unescaped, String charset) + throws URIException { + + return encode(unescaped, URI.allowed_abs_path, charset); + } + + + /** + * Escape and encode a string regarded as within the query component of an + * URI with the default protocol charset. + * When a query comprise the name and value pairs, it is used in order + * to encode each name and value string. The reserved special characters + * within a query component are being included in encoding the query. + * + * @param unescaped an unescaped string + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + * @see #encode + */ + public static String encodeWithinQuery(String unescaped) + throws URIException { + + return encodeWithinQuery(unescaped, URI.getDefaultProtocolCharset()); + } + + + /** + * Escape and encode a string regarded as within the query component of an + * URI with a given charset. + * When a query comprise the name and value pairs, it is used in order + * to encode each name and value string. The reserved special characters + * within a query component are being included in encoding the query. + * + * @param unescaped an unescaped string + * @param charset the charset + * @return the escaped string + * + * @throws URIException if the charset is not supported + * + * @see #encode + */ + public static String encodeWithinQuery(String unescaped, String charset) + throws URIException { + + return encode(unescaped, URI.allowed_within_query, charset); + } + + + /** + * Escape and encode a string regarded as the query component of an URI with + * the default protocol charset. + * When a query string is not misunderstood the reserved special characters + * ("&", "=", "+", ",", and "$") within a query component, this method + * is recommended to use in encoding the whole query. + * + * @param unescaped an unescaped string + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + * @see #encode + */ + public static String encodeQuery(String unescaped) throws URIException { + return encodeQuery(unescaped, URI.getDefaultProtocolCharset()); + } + + + /** + * Escape and encode a string regarded as the query component of an URI with + * a given charset. + * When a query string is not misunderstood the reserved special characters + * ("&", "=", "+", ",", and "$") within a query component, this method + * is recommended to use in encoding the whole query. + * + * @param unescaped an unescaped string + * @param charset the charset + * @return the escaped string + * + * @throws URIException if the charset is not supported + * + * @see #encode + */ + public static String encodeQuery(String unescaped, String charset) + throws URIException { + + return encode(unescaped, URI.allowed_query, charset); + } + + + /** + * Escape and encode a given string with allowed characters not to be + * escaped and the default protocol charset. + * + * @param unescaped a string + * @param allowed allowed characters not to be escaped + * @return the escaped string + * + * @throws URIException if the default protocol charset is not supported + * + * @see URI#getDefaultProtocolCharset + */ + public static String encode(String unescaped, BitSet allowed) + throws URIException { + + return encode(unescaped, allowed, URI.getDefaultProtocolCharset()); + } + + + /** + * Escape and encode a given string with allowed characters not to be + * escaped and a given charset. + * + * @param unescaped a string + * @param allowed allowed characters not to be escaped + * @param charset the charset + * @return the escaped string + */ + public static String encode(String unescaped, BitSet allowed, + String charset) throws URIException { + byte[] rawdata = URLCodec.encodeUrl(allowed, + EncodingUtil.getBytes(unescaped, charset)); + return EncodingUtil.getAsciiString(rawdata); + } + + + /** + * Unescape and decode a given string regarded as an escaped string with the + * default protocol charset. + * + * @param escaped a string + * @return the unescaped string + * + * @throws URIException if the string cannot be decoded (invalid) + * + * @see URI#getDefaultProtocolCharset + */ + public static String decode(String escaped) throws URIException { + try { + byte[] rawdata = URLCodec.decodeUrl(EncodingUtil.getAsciiBytes(escaped)); + return EncodingUtil.getString(rawdata, URI.getDefaultProtocolCharset()); + } catch (DecoderException e) { + throw new URIException(e.getMessage()); + } + } + + /** + * Unescape and decode a given string regarded as an escaped string. + * + * @param escaped a string + * @param charset the charset + * @return the unescaped string + * + * @throws URIException if the charset is not supported + * + * @see Coder#decode + */ + public static String decode(String escaped, String charset) + throws URIException { + + return Coder.decode(escaped.toCharArray(), charset); + } + + // ---------------------------------------------------------- Inner classes + + /** + * The basic and internal utility for URI escape and character encoding and + * decoding. + * + * @deprecated use org.apache.commons.codec.net.URLCodec + */ + protected static class Coder extends URI { + + /** + * Escape and encode a given string with allowed characters not to be + * escaped. + * + * @param unescapedComponent an unescaped component + * @param allowed allowed characters not to be escaped + * @param charset the charset to encode + * @return the escaped and encoded string + * + * @throws URIException if the charset is not supported + * + * @deprecated use org.apache.commons.codec.net.URLCodec + */ + public static char[] encode(String unescapedComponent, BitSet allowed, String charset) + throws URIException { + + return URI.encode(unescapedComponent, allowed, charset); + } + + + /** + * Unescape and decode a given string. + * + * @param escapedComponent an being-unescaped component + * @param charset the charset to decode + * @return the escaped and encoded string + * + * @throws URIException if the charset is not supported + * + * @deprecated use org.apache.commons.codec.net.URLCodec + */ + public static String decode(char[] escapedComponent, String charset) + throws URIException { + + return URI.decode(escapedComponent, charset); + } + + + /** + * Verify whether a given string is escaped or not + * + * @param original given characters + * @return true if the given character array is 7 bit ASCII-compatible. + */ + public static boolean verifyEscaped(char[] original) { + for (int i = 0; i < original.length; i++) { + int c = original[i]; + if (c > 128) { + return false; + } else if (c == '%') { + if (Character.digit(original[++i], 16) == -1 + || Character.digit(original[++i], 16) == -1) { + return false; + } + } + } + return true; + } + + + /** + * Replace from a given character to given character in an array order + * for a given string. + * + * @param original a given string + * @param from a replacing character array + * @param to a replaced character array + * @return the replaced string + */ + public static String replace(String original, char[] from, char[] to) { + for (int i = from.length; i > 0; --i) { + original = replace(original, from[i], to[i]); + } + return original.toString(); + } + + + /** + * Replace from a given character to given character for a given string. + * + * @param original a given string + * @param from a replacing character array + * @param to a replaced character array + * @return the replaced string + */ + public static String replace(String original, char from, char to) { + StringBuffer result = new StringBuffer(original.length()); + int at, saved = 0; + do { + at = original.indexOf(from); + if (at >= 0) { + result.append(original.substring(0, at)); + result.append(to); + } else { + result.append(original.substring(saved)); + } + saved = at; + } while (at >= 0); + return result.toString(); + } + } + +} + Index: 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/package.html =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/package.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-httpclient/org/apache/commons/httpclient/util/package.html 22 Aug 2012 17:30:38 -0000 1.1 @@ -0,0 +1,11 @@ + + + + Package Documentation for org.apache.commons.httpclient.util + + + Provides some utility classes for use by HttpClient. + + @since 2.0 + + Index: lams_build/3rdParty.userlibraries =================================================================== RCS file: /usr/local/cvsroot/lams_build/3rdParty.userlibraries,v diff -u -r1.55 -r1.56 --- lams_build/3rdParty.userlibraries 17 Aug 2012 14:13:06 -0000 1.55 +++ lams_build/3rdParty.userlibraries 22 Aug 2012 17:28:46 -0000 1.56 @@ -116,6 +116,6 @@ - +