summaryrefslogtreecommitdiffstats
path: root/java/client/src/org/apache/commons
diff options
context:
space:
mode:
Diffstat (limited to 'java/client/src/org/apache/commons')
-rw-r--r--java/client/src/org/apache/commons/codec/BinaryDecoder.java38
-rw-r--r--java/client/src/org/apache/commons/codec/BinaryEncoder.java38
-rw-r--r--java/client/src/org/apache/commons/codec/CharEncoding.java113
-rw-r--r--java/client/src/org/apache/commons/codec/Charsets.java144
-rw-r--r--java/client/src/org/apache/commons/codec/Decoder.java47
-rw-r--r--java/client/src/org/apache/commons/codec/DecoderException.java86
-rw-r--r--java/client/src/org/apache/commons/codec/Encoder.java44
-rw-r--r--java/client/src/org/apache/commons/codec/EncoderException.java89
-rw-r--r--java/client/src/org/apache/commons/codec/binary/Base64.java775
-rw-r--r--java/client/src/org/apache/commons/codec/binary/BaseNCodec.java500
-rw-r--r--java/client/src/org/apache/commons/codec/binary/StringUtils.java343
11 files changed, 2217 insertions, 0 deletions
diff --git a/java/client/src/org/apache/commons/codec/BinaryDecoder.java b/java/client/src/org/apache/commons/codec/BinaryDecoder.java
new file mode 100644
index 0000000..546ff76
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/BinaryDecoder.java
@@ -0,0 +1,38 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec;
19
20/**
21 * Defines common decoding methods for byte array decoders.
22 *
23 * @version $Id$
24 */
25public interface BinaryDecoder extends Decoder {
26
27 /**
28 * Decodes a byte array and returns the results as a byte array.
29 *
30 * @param source
31 * A byte array which has been encoded with the appropriate encoder
32 * @return a byte array that contains decoded content
33 * @throws DecoderException
34 * A decoder exception is thrown if a Decoder encounters a failure condition during the decode process.
35 */
36 byte[] decode(byte[] source) throws DecoderException;
37}
38
diff --git a/java/client/src/org/apache/commons/codec/BinaryEncoder.java b/java/client/src/org/apache/commons/codec/BinaryEncoder.java
new file mode 100644
index 0000000..65f92cc
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/BinaryEncoder.java
@@ -0,0 +1,38 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec;
19
20/**
21 * Defines common encoding methods for byte array encoders.
22 *
23 * @version $Id$
24 */
25public interface BinaryEncoder extends Encoder {
26
27 /**
28 * Encodes a byte array and return the encoded data as a byte array.
29 *
30 * @param source
31 * Data to be encoded
32 * @return A byte array containing the encoded data
33 * @throws EncoderException
34 * thrown if the Encoder encounters a failure condition during the encoding process.
35 */
36 byte[] encode(byte[] source) throws EncoderException;
37}
38
diff --git a/java/client/src/org/apache/commons/codec/CharEncoding.java b/java/client/src/org/apache/commons/codec/CharEncoding.java
new file mode 100644
index 0000000..2cfafa6
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/CharEncoding.java
@@ -0,0 +1,113 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec;
19
20/**
21 * Character encoding names required of every implementation of the Java platform.
22 *
23 * From the Java documentation <a
24 * href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>:
25 * <p>
26 * <cite>Every implementation of the Java platform is required to support the following character encodings. Consult the
27 * release documentation for your implementation to see if any other encodings are supported. Consult the release
28 * documentation for your implementation to see if any other encodings are supported.</cite>
29 * </p>
30 *
31 * <ul>
32 * <li><code>US-ASCII</code><br/>
33 * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.</li>
34 * <li><code>ISO-8859-1</code><br/>
35 * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.</li>
36 * <li><code>UTF-8</code><br/>
37 * Eight-bit Unicode Transformation Format.</li>
38 * <li><code>UTF-16BE</code><br/>
39 * Sixteen-bit Unicode Transformation Format, big-endian byte order.</li>
40 * <li><code>UTF-16LE</code><br/>
41 * Sixteen-bit Unicode Transformation Format, little-endian byte order.</li>
42 * <li><code>UTF-16</code><br/>
43 * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order
44 * accepted on input, big-endian used on output.)</li>
45 * </ul>
46 *
47 * This perhaps would best belong in the [lang] project. Even if a similar interface is defined in [lang], it is not
48 * foreseen that [codec] would be made to depend on [lang].
49 *
50 * <p>
51 * This class is immutable and thread-safe.
52 * </p>
53 *
54 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
55 * @since 1.4
56 * @version $Id$
57 */
58public class CharEncoding {
59 /**
60 * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
61 * <p>
62 * Every implementation of the Java platform is required to support this character encoding.
63 *
64 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
65 */
66 public static final String ISO_8859_1 = "ISO-8859-1";
67
68 /**
69 * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set.
70 * <p>
71 * Every implementation of the Java platform is required to support this character encoding.
72 *
73 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
74 */
75 public static final String US_ASCII = "US-ASCII";
76
77 /**
78 * Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory initial byte-order mark
79 * (either order accepted on input, big-endian used on output)
80 * <p>
81 * Every implementation of the Java platform is required to support this character encoding.
82 *
83 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
84 */
85 public static final String UTF_16 = "UTF-16";
86
87 /**
88 * Sixteen-bit Unicode Transformation Format, big-endian byte order.
89 * <p>
90 * Every implementation of the Java platform is required to support this character encoding.
91 *
92 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
93 */
94 public static final String UTF_16BE = "UTF-16BE";
95
96 /**
97 * Sixteen-bit Unicode Transformation Format, little-endian byte order.
98 * <p>
99 * Every implementation of the Java platform is required to support this character encoding.
100 *
101 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
102 */
103 public static final String UTF_16LE = "UTF-16LE";
104
105 /**
106 * Eight-bit Unicode Transformation Format.
107 * <p>
108 * Every implementation of the Java platform is required to support this character encoding.
109 *
110 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
111 */
112 public static final String UTF_8 = "UTF-8";
113}
diff --git a/java/client/src/org/apache/commons/codec/Charsets.java b/java/client/src/org/apache/commons/codec/Charsets.java
new file mode 100644
index 0000000..73fbc79
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/Charsets.java
@@ -0,0 +1,144 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package org.apache.commons.codec;
18
19import java.nio.charset.Charset;
20
21/**
22 * Charsets required of every implementation of the Java platform.
23 *
24 * From the Java documentation <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard
25 * charsets</a>:
26 * <p>
27 * <cite>Every implementation of the Java platform is required to support the following character encodings. Consult the
28 * release documentation for your implementation to see if any other encodings are supported. Consult the release
29 * documentation for your implementation to see if any other encodings are supported. </cite>
30 * </p>
31 *
32 * <ul>
33 * <li><code>US-ASCII</code><br/>
34 * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.</li>
35 * <li><code>ISO-8859-1</code><br/>
36 * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.</li>
37 * <li><code>UTF-8</code><br/>
38 * Eight-bit Unicode Transformation Format.</li>
39 * <li><code>UTF-16BE</code><br/>
40 * Sixteen-bit Unicode Transformation Format, big-endian byte order.</li>
41 * <li><code>UTF-16LE</code><br/>
42 * Sixteen-bit Unicode Transformation Format, little-endian byte order.</li>
43 * <li><code>UTF-16</code><br/>
44 * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order
45 * accepted on input, big-endian used on output.)</li>
46 * </ul>
47 *
48 * This perhaps would best belong in the Commons Lang project. Even if a similar class is defined in Commons Lang, it is
49 * not foreseen that Commons Codec would be made to depend on Commons Lang.
50 *
51 * <p>
52 * This class is immutable and thread-safe.
53 * </p>
54 *
55 * @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
56 * @since 1.7
57 * @version $Id: CharEncoding.java 1173287 2011-09-20 18:16:19Z ggregory $
58 */
59public class Charsets {
60
61 //
62 // This class should only contain Charset instances for required encodings. This guarantees that it will load
63 // correctly and without delay on all Java platforms.
64 //
65
66 /**
67 * Returns the given Charset or the default Charset if the given Charset is null.
68 *
69 * @param charset
70 * A charset or null.
71 * @return the given Charset or the default Charset if the given Charset is null
72 */
73 public static Charset toCharset(final Charset charset) {
74 return charset == null ? Charset.defaultCharset() : charset;
75 }
76
77 /**
78 * Returns a Charset for the named charset. If the name is null, return the default Charset.
79 *
80 * @param charset
81 * The name of the requested charset, may be null.
82 * @return a Charset for the named charset
83 * @throws java.nio.charset.UnsupportedCharsetException
84 * If the named charset is unavailable
85 */
86 public static Charset toCharset(final String charset) {
87 return charset == null ? Charset.defaultCharset() : Charset.forName(charset);
88 }
89
90 /**
91 * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
92 * <p>
93 * Every implementation of the Java platform is required to support this character encoding.
94 *
95 * @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
96 */
97 public static final Charset ISO_8859_1 = Charset.forName(CharEncoding.ISO_8859_1);
98
99 /**
100 * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set.
101 * <p>
102 * Every implementation of the Java platform is required to support this character encoding.
103 *
104 * @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
105 */
106 public static final Charset US_ASCII = Charset.forName(CharEncoding.US_ASCII);
107
108 /**
109 * Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory initial byte-order mark
110 * (either order accepted on input, big-endian used on output)
111 * <p>
112 * Every implementation of the Java platform is required to support this character encoding.
113 *
114 * @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
115 */
116 public static final Charset UTF_16 = Charset.forName(CharEncoding.UTF_16);
117
118 /**
119 * Sixteen-bit Unicode Transformation Format, big-endian byte order.
120 * <p>
121 * Every implementation of the Java platform is required to support this character encoding.
122 *
123 * @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
124 */
125 public static final Charset UTF_16BE = Charset.forName(CharEncoding.UTF_16BE);
126
127 /**
128 * Sixteen-bit Unicode Transformation Format, little-endian byte order.
129 * <p>
130 * Every implementation of the Java platform is required to support this character encoding.
131 *
132 * @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
133 */
134 public static final Charset UTF_16LE = Charset.forName(CharEncoding.UTF_16LE);
135
136 /**
137 * Eight-bit Unicode Transformation Format.
138 * <p>
139 * Every implementation of the Java platform is required to support this character encoding.
140 *
141 * @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
142 */
143 public static final Charset UTF_8 = Charset.forName(CharEncoding.UTF_8);
144}
diff --git a/java/client/src/org/apache/commons/codec/Decoder.java b/java/client/src/org/apache/commons/codec/Decoder.java
new file mode 100644
index 0000000..9f3ba60
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/Decoder.java
@@ -0,0 +1,47 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec;
19
20/**
21 * Provides the highest level of abstraction for Decoders.
22 * <p>
23 * This is the sister interface of {@link Encoder}. All Decoders implement this common generic interface.
24 * Allows a user to pass a generic Object to any Decoder implementation in the codec package.
25 * <p>
26 * One of the two interfaces at the center of the codec package.
27 *
28 * @version $Id$
29 */
30public interface Decoder {
31
32 /**
33 * Decodes an "encoded" Object and returns a "decoded" Object. Note that the implementation of this interface will
34 * try to cast the Object parameter to the specific type expected by a particular Decoder implementation. If a
35 * {@link ClassCastException} occurs this decode method will throw a DecoderException.
36 *
37 * @param source
38 * the object to decode
39 * @return a 'decoded" object
40 * @throws DecoderException
41 * a decoder exception can be thrown for any number of reasons. Some good candidates are that the
42 * parameter passed to this method is null, a param cannot be cast to the appropriate type for a
43 * specific encoder.
44 */
45 Object decode(Object source) throws DecoderException;
46}
47
diff --git a/java/client/src/org/apache/commons/codec/DecoderException.java b/java/client/src/org/apache/commons/codec/DecoderException.java
new file mode 100644
index 0000000..52846a5
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/DecoderException.java
@@ -0,0 +1,86 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec;
19
20/**
21 * Thrown when there is a failure condition during the decoding process. This exception is thrown when a {@link Decoder}
22 * encounters a decoding specific exception such as invalid data, or characters outside of the expected range.
23 *
24 * @version $Id$
25 */
26public class DecoderException extends Exception {
27
28 /**
29 * Declares the Serial Version Uid.
30 *
31 * @see <a href="http://c2.com/cgi/wiki?AlwaysDeclareSerialVersionUid">Always Declare Serial Version Uid</a>
32 */
33 private static final long serialVersionUID = 1L;
34
35 /**
36 * Constructs a new exception with {@code null} as its detail message. The cause is not initialized, and may
37 * subsequently be initialized by a call to {@link #initCause}.
38 *
39 * @since 1.4
40 */
41 public DecoderException() {
42 super();
43 }
44
45 /**
46 * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
47 * be initialized by a call to {@link #initCause}.
48 *
49 * @param message
50 * The detail message which is saved for later retrieval by the {@link #getMessage()} method.
51 */
52 public DecoderException(final String message) {
53 super(message);
54 }
55
56 /**
57 * Constructs a new exception with the specified detail message and cause.
58 * <p>
59 * Note that the detail message associated with <code>cause</code> is not automatically incorporated into this
60 * exception's detail message.
61 *
62 * @param message
63 * The detail message which is saved for later retrieval by the {@link #getMessage()} method.
64 * @param cause
65 * The cause which is saved for later retrieval by the {@link #getCause()} method. A {@code null}
66 * value is permitted, and indicates that the cause is nonexistent or unknown.
67 * @since 1.4
68 */
69 public DecoderException(final String message, final Throwable cause) {
70 super(message, cause);
71 }
72
73 /**
74 * Constructs a new exception with the specified cause and a detail message of <code>(cause==null ?
75 * null : cause.toString())</code> (which typically contains the class and detail message of <code>cause</code>).
76 * This constructor is useful for exceptions that are little more than wrappers for other throwables.
77 *
78 * @param cause
79 * The cause which is saved for later retrieval by the {@link #getCause()} method. A {@code null}
80 * value is permitted, and indicates that the cause is nonexistent or unknown.
81 * @since 1.4
82 */
83 public DecoderException(final Throwable cause) {
84 super(cause);
85 }
86}
diff --git a/java/client/src/org/apache/commons/codec/Encoder.java b/java/client/src/org/apache/commons/codec/Encoder.java
new file mode 100644
index 0000000..c7e99eb
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/Encoder.java
@@ -0,0 +1,44 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec;
19
20/**
21 * Provides the highest level of abstraction for Encoders.
22 * <p>
23 * This is the sister interface of {@link Decoder}. Every implementation of Encoder provides this
24 * common generic interface which allows a user to pass a generic Object to any Encoder implementation
25 * in the codec package.
26 *
27 * @version $Id$
28 */
29public interface Encoder {
30
31 /**
32 * Encodes an "Object" and returns the encoded content as an Object. The Objects here may just be
33 * <code>byte[]</code> or <code>String</code>s depending on the implementation used.
34 *
35 * @param source
36 * An object to encode
37 * @return An "encoded" Object
38 * @throws EncoderException
39 * An encoder exception is thrown if the encoder experiences a failure condition during the encoding
40 * process.
41 */
42 Object encode(Object source) throws EncoderException;
43}
44
diff --git a/java/client/src/org/apache/commons/codec/EncoderException.java b/java/client/src/org/apache/commons/codec/EncoderException.java
new file mode 100644
index 0000000..dfc88f7
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/EncoderException.java
@@ -0,0 +1,89 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec;
19
20/**
21 * Thrown when there is a failure condition during the encoding process. This exception is thrown when an
22 * {@link Encoder} encounters a encoding specific exception such as invalid data, inability to calculate a checksum,
23 * characters outside of the expected range.
24 *
25 * @version $Id$
26 */
27public class EncoderException extends Exception {
28
29 /**
30 * Declares the Serial Version Uid.
31 *
32 * @see <a href="http://c2.com/cgi/wiki?AlwaysDeclareSerialVersionUid">Always Declare Serial Version Uid</a>
33 */
34 private static final long serialVersionUID = 1L;
35
36 /**
37 * Constructs a new exception with {@code null} as its detail message. The cause is not initialized, and may
38 * subsequently be initialized by a call to {@link #initCause}.
39 *
40 * @since 1.4
41 */
42 public EncoderException() {
43 super();
44 }
45
46 /**
47 * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
48 * be initialized by a call to {@link #initCause}.
49 *
50 * @param message
51 * a useful message relating to the encoder specific error.
52 */
53 public EncoderException(final String message) {
54 super(message);
55 }
56
57 /**
58 * Constructs a new exception with the specified detail message and cause.
59 *
60 * <p>
61 * Note that the detail message associated with <code>cause</code> is not automatically incorporated into this
62 * exception's detail message.
63 * </p>
64 *
65 * @param message
66 * The detail message which is saved for later retrieval by the {@link #getMessage()} method.
67 * @param cause
68 * The cause which is saved for later retrieval by the {@link #getCause()} method. A {@code null}
69 * value is permitted, and indicates that the cause is nonexistent or unknown.
70 * @since 1.4
71 */
72 public EncoderException(final String message, final Throwable cause) {
73 super(message, cause);
74 }
75
76 /**
77 * Constructs a new exception with the specified cause and a detail message of <code>(cause==null ?
78 * null : cause.toString())</code> (which typically contains the class and detail message of <code>cause</code>).
79 * This constructor is useful for exceptions that are little more than wrappers for other throwables.
80 *
81 * @param cause
82 * The cause which is saved for later retrieval by the {@link #getCause()} method. A {@code null}
83 * value is permitted, and indicates that the cause is nonexistent or unknown.
84 * @since 1.4
85 */
86 public EncoderException(final Throwable cause) {
87 super(cause);
88 }
89}
diff --git a/java/client/src/org/apache/commons/codec/binary/Base64.java b/java/client/src/org/apache/commons/codec/binary/Base64.java
new file mode 100644
index 0000000..3e01916
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/binary/Base64.java
@@ -0,0 +1,775 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec.binary;
19
20import java.math.BigInteger;
21
22/**
23 * Provides Base64 encoding and decoding as defined by <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
24 *
25 * <p>
26 * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
27 * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
28 * </p>
29 * <p>
30 * The class can be parameterized in the following manner with various constructors:
31 * <ul>
32 * <li>URL-safe mode: Default off.</li>
33 * <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of
34 * 4 in the encoded data.
35 * <li>Line separator: Default is CRLF ("\r\n")</li>
36 * </ul>
37 * </p>
38 * <p>
39 * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only
40 * encode/decode character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252,
41 * UTF-8, etc).
42 * </p>
43 * <p>
44 * This class is thread-safe.
45 * </p>
46 *
47 * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
48 * @since 1.0
49 * @version $Id$
50 */
51public class Base64 extends BaseNCodec {
52
53 /**
54 * BASE32 characters are 6 bits in length.
55 * They are formed by taking a block of 3 octets to form a 24-bit string,
56 * which is converted into 4 BASE64 characters.
57 */
58 private static final int BITS_PER_ENCODED_BYTE = 6;
59 private static final int BYTES_PER_UNENCODED_BLOCK = 3;
60 private static final int BYTES_PER_ENCODED_BLOCK = 4;
61
62 /**
63 * Chunk separator per RFC 2045 section 2.1.
64 *
65 * <p>
66 * N.B. The next major release may break compatibility and make this field private.
67 * </p>
68 *
69 * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
70 */
71 static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
72
73 /**
74 * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
75 * equivalents as specified in Table 1 of RFC 2045.
76 *
77 * Thanks to "commons" project in ws.apache.org for this code.
78 * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
79 */
80 private static final byte[] STANDARD_ENCODE_TABLE = {
81 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
82 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
83 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
84 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
85 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
86 };
87
88 /**
89 * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
90 * changed to - and _ to make the encoded Base64 results more URL-SAFE.
91 * This table is only used when the Base64's mode is set to URL-SAFE.
92 */
93 private static final byte[] URL_SAFE_ENCODE_TABLE = {
94 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
95 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
96 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
97 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
98 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
99 };
100
101 /**
102 * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified
103 * in Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
104 * alphabet but fall within the bounds of the array are translated to -1.
105 *
106 * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
107 * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
108 *
109 * Thanks to "commons" project in ws.apache.org for this code.
110 * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
111 */
112 private static final byte[] DECODE_TABLE = {
113 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
114 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
115 -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
116 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
117 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
118 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
119 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
120 };
121
122 /**
123 * Base64 uses 6-bit fields.
124 */
125 /** Mask used to extract 6 bits, used when encoding */
126 private static final int MASK_6BITS = 0x3f;
127
128 // The static final fields above are used for the original static byte[] methods on Base64.
129 // The private member fields below are used with the new streaming approach, which requires
130 // some state be preserved between calls of encode() and decode().
131
132 /**
133 * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
134 * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
135 * between the two modes.
136 */
137 private final byte[] encodeTable;
138
139 // Only one decode table currently; keep for consistency with Base32 code
140 private final byte[] decodeTable = DECODE_TABLE;
141
142 /**
143 * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
144 */
145 private final byte[] lineSeparator;
146
147 /**
148 * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
149 * <code>decodeSize = 3 + lineSeparator.length;</code>
150 */
151 private final int decodeSize;
152
153 /**
154 * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
155 * <code>encodeSize = 4 + lineSeparator.length;</code>
156 */
157 private final int encodeSize;
158
159 /**
160 * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
161 * <p>
162 * When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE.
163 * </p>
164 *
165 * <p>
166 * When decoding all variants are supported.
167 * </p>
168 */
169 public Base64() {
170 this(0);
171 }
172
173 /**
174 * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
175 * <p>
176 * When encoding the line length is 76, the line separator is CRLF, and the encoding table is
177 * STANDARD_ENCODE_TABLE.
178 * </p>
179 *
180 * <p>
181 * When decoding all variants are supported.
182 * </p>
183 *
184 * @param urlSafe
185 * if {@code true}, URL-safe encoding is used. In most cases this should be set to {@code false}.
186 * @since 1.4
187 */
188 public Base64(final boolean urlSafe) {
189 this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
190 }
191
192 /**
193 * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
194 * <p>
195 * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is
196 * STANDARD_ENCODE_TABLE.
197 * </p>
198 * <p>
199 * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
200 * </p>
201 * <p>
202 * When decoding all variants are supported.
203 * </p>
204 *
205 * @param lineLength
206 * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
207 * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
208 * decoding.
209 * @since 1.4
210 */
211 public Base64(final int lineLength) {
212 this(lineLength, CHUNK_SEPARATOR);
213 }
214
215 /**
216 * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
217 * <p>
218 * When encoding the line length and line separator are given in the constructor, and the encoding table is
219 * STANDARD_ENCODE_TABLE.
220 * </p>
221 * <p>
222 * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
223 * </p>
224 * <p>
225 * When decoding all variants are supported.
226 * </p>
227 *
228 * @param lineLength
229 * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
230 * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
231 * decoding.
232 * @param lineSeparator
233 * Each line of encoded data will end with this sequence of bytes.
234 * @throws IllegalArgumentException
235 * Thrown when the provided lineSeparator included some base64 characters.
236 * @since 1.4
237 */
238 public Base64(final int lineLength, final byte[] lineSeparator) {
239 this(lineLength, lineSeparator, false);
240 }
241
242 /**
243 * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
244 * <p>
245 * When encoding the line length and line separator are given in the constructor, and the encoding table is
246 * STANDARD_ENCODE_TABLE.
247 * </p>
248 * <p>
249 * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
250 * </p>
251 * <p>
252 * When decoding all variants are supported.
253 * </p>
254 *
255 * @param lineLength
256 * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
257 * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
258 * decoding.
259 * @param lineSeparator
260 * Each line of encoded data will end with this sequence of bytes.
261 * @param urlSafe
262 * Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
263 * operations. Decoding seamlessly handles both modes.
264 * <b>Note: no padding is added when using the URL-safe alphabet.</b>
265 * @throws IllegalArgumentException
266 * The provided lineSeparator included some base64 characters. That's not going to work!
267 * @since 1.4
268 */
269 public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe) {
270 super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
271 lineLength,
272 lineSeparator == null ? 0 : lineSeparator.length);
273 // TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
274 // @see test case Base64Test.testConstructors()
275 if (lineSeparator != null) {
276 if (containsAlphabetOrPad(lineSeparator)) {
277 final String sep = StringUtils.newStringUtf8(lineSeparator);
278 throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
279 }
280 if (lineLength > 0){ // null line-sep forces no chunking rather than throwing IAE
281 this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
282 this.lineSeparator = new byte[lineSeparator.length];
283 System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
284 } else {
285 this.encodeSize = BYTES_PER_ENCODED_BLOCK;
286 this.lineSeparator = null;
287 }
288 } else {
289 this.encodeSize = BYTES_PER_ENCODED_BLOCK;
290 this.lineSeparator = null;
291 }
292 this.decodeSize = this.encodeSize - 1;
293 this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
294 }
295
296 /**
297 * Returns our current encode mode. True if we're URL-SAFE, false otherwise.
298 *
299 * @return true if we're in URL-SAFE mode, false otherwise.
300 * @since 1.4
301 */
302 public boolean isUrlSafe() {
303 return this.encodeTable == URL_SAFE_ENCODE_TABLE;
304 }
305
306 /**
307 * <p>
308 * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
309 * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, to flush last
310 * remaining bytes (if not multiple of 3).
311 * </p>
312 * <p><b>Note: no padding is added when encoding using the URL-safe alphabet.</b></p>
313 * <p>
314 * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
315 * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
316 * </p>
317 *
318 * @param in
319 * byte[] array of binary data to base64 encode.
320 * @param inPos
321 * Position to start reading data from.
322 * @param inAvail
323 * Amount of bytes available from input for encoding.
324 * @param context
325 * the context to be used
326 */
327 @Override
328 void encode(final byte[] in, int inPos, final int inAvail, final Context context) {
329 if (context.eof) {
330 return;
331 }
332 // inAvail < 0 is how we're informed of EOF in the underlying data we're
333 // encoding.
334 if (inAvail < 0) {
335 context.eof = true;
336 if (0 == context.modulus && lineLength == 0) {
337 return; // no leftovers to process and not using chunking
338 }
339 final byte[] buffer = ensureBufferSize(encodeSize, context);
340 final int savedPos = context.pos;
341 switch (context.modulus) { // 0-2
342 case 0 : // nothing to do here
343 break;
344 case 1 : // 8 bits = 6 + 2
345 // top 6 bits:
346 buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 2) & MASK_6BITS];
347 // remaining 2:
348 buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 4) & MASK_6BITS];
349 // URL-SAFE skips the padding to further reduce size.
350 if (encodeTable == STANDARD_ENCODE_TABLE) {
351 buffer[context.pos++] = PAD;
352 buffer[context.pos++] = PAD;
353 }
354 break;
355
356 case 2 : // 16 bits = 6 + 6 + 4
357 buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 10) & MASK_6BITS];
358 buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 4) & MASK_6BITS];
359 buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 2) & MASK_6BITS];
360 // URL-SAFE skips the padding to further reduce size.
361 if (encodeTable == STANDARD_ENCODE_TABLE) {
362 buffer[context.pos++] = PAD;
363 }
364 break;
365 default:
366 throw new IllegalStateException("Impossible modulus "+context.modulus);
367 }
368 context.currentLinePos += context.pos - savedPos; // keep track of current line position
369 // if currentPos == 0 we are at the start of a line, so don't add CRLF
370 if (lineLength > 0 && context.currentLinePos > 0) {
371 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
372 context.pos += lineSeparator.length;
373 }
374 } else {
375 for (int i = 0; i < inAvail; i++) {
376 final byte[] buffer = ensureBufferSize(encodeSize, context);
377 context.modulus = (context.modulus+1) % BYTES_PER_UNENCODED_BLOCK;
378 int b = in[inPos++];
379 if (b < 0) {
380 b += 256;
381 }
382 context.ibitWorkArea = (context.ibitWorkArea << 8) + b; // BITS_PER_BYTE
383 if (0 == context.modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract
384 buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 18) & MASK_6BITS];
385 buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 12) & MASK_6BITS];
386 buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 6) & MASK_6BITS];
387 buffer[context.pos++] = encodeTable[context.ibitWorkArea & MASK_6BITS];
388 context.currentLinePos += BYTES_PER_ENCODED_BLOCK;
389 if (lineLength > 0 && lineLength <= context.currentLinePos) {
390 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
391 context.pos += lineSeparator.length;
392 context.currentLinePos = 0;
393 }
394 }
395 }
396 }
397 }
398
399 /**
400 * <p>
401 * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
402 * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
403 * call is not necessary when decoding, but it doesn't hurt, either.
404 * </p>
405 * <p>
406 * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
407 * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
408 * garbage-out philosophy: it will not check the provided data for validity.
409 * </p>
410 * <p>
411 * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
412 * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
413 * </p>
414 *
415 * @param in
416 * byte[] array of ascii data to base64 decode.
417 * @param inPos
418 * Position to start reading data from.
419 * @param inAvail
420 * Amount of bytes available from input for encoding.
421 * @param context
422 * the context to be used
423 */
424 @Override
425 void decode(final byte[] in, int inPos, final int inAvail, final Context context) {
426 if (context.eof) {
427 return;
428 }
429 if (inAvail < 0) {
430 context.eof = true;
431 }
432 for (int i = 0; i < inAvail; i++) {
433 final byte[] buffer = ensureBufferSize(decodeSize, context);
434 final byte b = in[inPos++];
435 if (b == PAD) {
436 // We're done.
437 context.eof = true;
438 break;
439 } else {
440 if (b >= 0 && b < DECODE_TABLE.length) {
441 final int result = DECODE_TABLE[b];
442 if (result >= 0) {
443 context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK;
444 context.ibitWorkArea = (context.ibitWorkArea << BITS_PER_ENCODED_BYTE) + result;
445 if (context.modulus == 0) {
446 buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 16) & MASK_8BITS);
447 buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS);
448 buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS);
449 }
450 }
451 }
452 }
453 }
454
455 // Two forms of EOF as far as base64 decoder is concerned: actual
456 // EOF (-1) and first time '=' character is encountered in stream.
457 // This approach makes the '=' padding characters completely optional.
458 if (context.eof && context.modulus != 0) {
459 final byte[] buffer = ensureBufferSize(decodeSize, context);
460
461 // We have some spare bits remaining
462 // Output all whole multiples of 8 bits and ignore the rest
463 switch (context.modulus) {
464// case 0 : // impossible, as excluded above
465 case 1 : // 6 bits - ignore entirely
466 // TODO not currently tested; perhaps it is impossible?
467 break;
468 case 2 : // 12 bits = 8 + 4
469 context.ibitWorkArea = context.ibitWorkArea >> 4; // dump the extra 4 bits
470 buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS);
471 break;
472 case 3 : // 18 bits = 8 + 8 + 2
473 context.ibitWorkArea = context.ibitWorkArea >> 2; // dump 2 bits
474 buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS);
475 buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS);
476 break;
477 default:
478 throw new IllegalStateException("Impossible modulus "+context.modulus);
479 }
480 }
481 }
482
483 /**
484 * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
485 * method treats whitespace as valid.
486 *
487 * @param arrayOctet
488 * byte array to test
489 * @return {@code true} if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
490 * {@code false}, otherwise
491 * @deprecated 1.5 Use {@link #isBase64(byte[])}, will be removed in 2.0.
492 */
493 @Deprecated
494 public static boolean isArrayByteBase64(final byte[] arrayOctet) {
495 return isBase64(arrayOctet);
496 }
497
498 /**
499 * Returns whether or not the <code>octet</code> is in the base 64 alphabet.
500 *
501 * @param octet
502 * The value to test
503 * @return {@code true} if the value is defined in the the base 64 alphabet, {@code false} otherwise.
504 * @since 1.4
505 */
506 public static boolean isBase64(final byte octet) {
507 return octet == PAD_DEFAULT || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1);
508 }
509
510 /**
511 * Tests a given String to see if it contains only valid characters within the Base64 alphabet. Currently the
512 * method treats whitespace as valid.
513 *
514 * @param base64
515 * String to test
516 * @return {@code true} if all characters in the String are valid characters in the Base64 alphabet or if
517 * the String is empty; {@code false}, otherwise
518 * @since 1.5
519 */
520 public static boolean isBase64(final String base64) {
521 return isBase64(StringUtils.getBytesUtf8(base64));
522 }
523
524 /**
525 * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
526 * method treats whitespace as valid.
527 *
528 * @param arrayOctet
529 * byte array to test
530 * @return {@code true} if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
531 * {@code false}, otherwise
532 * @since 1.5
533 */
534 public static boolean isBase64(final byte[] arrayOctet) {
535 for (int i = 0; i < arrayOctet.length; i++) {
536 if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
537 return false;
538 }
539 }
540 return true;
541 }
542
543 /**
544 * Encodes binary data using the base64 algorithm but does not chunk the output.
545 *
546 * @param binaryData
547 * binary data to encode
548 * @return byte[] containing Base64 characters in their UTF-8 representation.
549 */
550 public static byte[] encodeBase64(final byte[] binaryData) {
551 return encodeBase64(binaryData, false);
552 }
553
554 /**
555 * Encodes binary data using the base64 algorithm but does not chunk the output.
556 *
557 * NOTE: We changed the behaviour of this method from multi-line chunking (commons-codec-1.4) to
558 * single-line non-chunking (commons-codec-1.5).
559 *
560 * @param binaryData
561 * binary data to encode
562 * @return String containing Base64 characters.
563 * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not).
564 */
565 public static String encodeBase64String(final byte[] binaryData) {
566 return StringUtils.newStringUtf8(encodeBase64(binaryData, false));
567 }
568
569 /**
570 * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
571 * url-safe variation emits - and _ instead of + and / characters.
572 * <b>Note: no padding is added.</b>
573 * @param binaryData
574 * binary data to encode
575 * @return byte[] containing Base64 characters in their UTF-8 representation.
576 * @since 1.4
577 */
578 public static byte[] encodeBase64URLSafe(final byte[] binaryData) {
579 return encodeBase64(binaryData, false, true);
580 }
581
582 /**
583 * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
584 * url-safe variation emits - and _ instead of + and / characters.
585 * <b>Note: no padding is added.</b>
586 * @param binaryData
587 * binary data to encode
588 * @return String containing Base64 characters
589 * @since 1.4
590 */
591 public static String encodeBase64URLSafeString(final byte[] binaryData) {
592 return StringUtils.newStringUtf8(encodeBase64(binaryData, false, true));
593 }
594
595 /**
596 * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
597 *
598 * @param binaryData
599 * binary data to encode
600 * @return Base64 characters chunked in 76 character blocks
601 */
602 public static byte[] encodeBase64Chunked(final byte[] binaryData) {
603 return encodeBase64(binaryData, true);
604 }
605
606 /**
607 * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
608 *
609 * @param binaryData
610 * Array containing binary data to encode.
611 * @param isChunked
612 * if {@code true} this encoder will chunk the base64 output into 76 character blocks
613 * @return Base64-encoded data.
614 * @throws IllegalArgumentException
615 * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
616 */
617 public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked) {
618 return encodeBase64(binaryData, isChunked, false);
619 }
620
621 /**
622 * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
623 *
624 * @param binaryData
625 * Array containing binary data to encode.
626 * @param isChunked
627 * if {@code true} this encoder will chunk the base64 output into 76 character blocks
628 * @param urlSafe
629 * if {@code true} this encoder will emit - and _ instead of the usual + and / characters.
630 * <b>Note: no padding is added when encoding using the URL-safe alphabet.</b>
631 * @return Base64-encoded data.
632 * @throws IllegalArgumentException
633 * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
634 * @since 1.4
635 */
636 public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe) {
637 return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
638 }
639
640 /**
641 * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
642 *
643 * @param binaryData
644 * Array containing binary data to encode.
645 * @param isChunked
646 * if {@code true} this encoder will chunk the base64 output into 76 character blocks
647 * @param urlSafe
648 * if {@code true} this encoder will emit - and _ instead of the usual + and / characters.
649 * <b>Note: no padding is added when encoding using the URL-safe alphabet.</b>
650 * @param maxResultSize
651 * The maximum result size to accept.
652 * @return Base64-encoded data.
653 * @throws IllegalArgumentException
654 * Thrown when the input array needs an output array bigger than maxResultSize
655 * @since 1.4
656 */
657 public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked,
658 final boolean urlSafe, final int maxResultSize) {
659 if (binaryData == null || binaryData.length == 0) {
660 return binaryData;
661 }
662
663 // Create this so can use the super-class method
664 // Also ensures that the same roundings are performed by the ctor and the code
665 final Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
666 final long len = b64.getEncodedLength(binaryData);
667 if (len > maxResultSize) {
668 throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
669 len +
670 ") than the specified maximum size of " +
671 maxResultSize);
672 }
673
674 return b64.encode(binaryData);
675 }
676
677 /**
678 * Decodes a Base64 String into octets
679 *
680 * @param base64String
681 * String containing Base64 data
682 * @return Array containing decoded data.
683 * @since 1.4
684 */
685 public static byte[] decodeBase64(final String base64String) {
686 return new Base64().decode(base64String);
687 }
688
689 /**
690 * Decodes Base64 data into octets
691 *
692 * @param base64Data
693 * Byte array containing Base64 data
694 * @return Array containing decoded data.
695 */
696 public static byte[] decodeBase64(final byte[] base64Data) {
697 return new Base64().decode(base64Data);
698 }
699
700 // Implementation of the Encoder Interface
701
702 // Implementation of integer encoding used for crypto
703 /**
704 * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
705 *
706 * @param pArray
707 * a byte array containing base64 character data
708 * @return A BigInteger
709 * @since 1.4
710 */
711 public static BigInteger decodeInteger(final byte[] pArray) {
712 return new BigInteger(1, decodeBase64(pArray));
713 }
714
715 /**
716 * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
717 *
718 * @param bigInt
719 * a BigInteger
720 * @return A byte array containing base64 character data
721 * @throws NullPointerException
722 * if null is passed in
723 * @since 1.4
724 */
725 public static byte[] encodeInteger(final BigInteger bigInt) {
726 if (bigInt == null) {
727 throw new NullPointerException("encodeInteger called with null parameter");
728 }
729 return encodeBase64(toIntegerBytes(bigInt), false);
730 }
731
732 /**
733 * Returns a byte-array representation of a <code>BigInteger</code> without sign bit.
734 *
735 * @param bigInt
736 * <code>BigInteger</code> to be converted
737 * @return a byte array representation of the BigInteger parameter
738 */
739 static byte[] toIntegerBytes(final BigInteger bigInt) {
740 int bitlen = bigInt.bitLength();
741 // round bitlen
742 bitlen = ((bitlen + 7) >> 3) << 3;
743 final byte[] bigBytes = bigInt.toByteArray();
744
745 if (((bigInt.bitLength() % 8) != 0) && (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) {
746 return bigBytes;
747 }
748 // set up params for copying everything but sign bit
749 int startSrc = 0;
750 int len = bigBytes.length;
751
752 // if bigInt is exactly byte-aligned, just skip signbit in copy
753 if ((bigInt.bitLength() % 8) == 0) {
754 startSrc = 1;
755 len--;
756 }
757 final int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec
758 final byte[] resizedBytes = new byte[bitlen / 8];
759 System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len);
760 return resizedBytes;
761 }
762
763 /**
764 * Returns whether or not the <code>octet</code> is in the Base64 alphabet.
765 *
766 * @param octet
767 * The value to test
768 * @return {@code true} if the value is defined in the the Base64 alphabet {@code false} otherwise.
769 */
770 @Override
771 protected boolean isInAlphabet(final byte octet) {
772 return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
773 }
774
775}
diff --git a/java/client/src/org/apache/commons/codec/binary/BaseNCodec.java b/java/client/src/org/apache/commons/codec/binary/BaseNCodec.java
new file mode 100644
index 0000000..2edd754
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/binary/BaseNCodec.java
@@ -0,0 +1,500 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec.binary;
19
20import org.apache.commons.codec.BinaryDecoder;
21import org.apache.commons.codec.BinaryEncoder;
22import org.apache.commons.codec.DecoderException;
23import org.apache.commons.codec.EncoderException;
24
25/**
26 * Abstract superclass for Base-N encoders and decoders.
27 *
28 * <p>
29 * This class is thread-safe.
30 * </p>
31 *
32 * @version $Id$
33 */
34public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
35
36 /**
37 * Holds thread context so classes can be thread-safe.
38 *
39 * This class is not itself thread-safe; each thread must allocate its own copy.
40 *
41 * @since 1.7
42 */
43 static class Context {
44
45 /**
46 * Place holder for the bytes we're dealing with for our based logic.
47 * Bitwise operations store and extract the encoding or decoding from this variable.
48 */
49 int ibitWorkArea;
50
51 /**
52 * Place holder for the bytes we're dealing with for our based logic.
53 * Bitwise operations store and extract the encoding or decoding from this variable.
54 */
55 long lbitWorkArea;
56
57 /**
58 * Buffer for streaming.
59 */
60 byte[] buffer;
61
62 /**
63 * Position where next character should be written in the buffer.
64 */
65 int pos;
66
67 /**
68 * Position where next character should be read from the buffer.
69 */
70 int readPos;
71
72 /**
73 * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless,
74 * and must be thrown away.
75 */
76 boolean eof;
77
78 /**
79 * Variable tracks how many characters have been written to the current line. Only used when encoding. We use
80 * it to make sure each encoded line never goes beyond lineLength (if lineLength > 0).
81 */
82 int currentLinePos;
83
84 /**
85 * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This
86 * variable helps track that.
87 */
88 int modulus;
89
90 Context() {
91 }
92
93 /**
94 * Returns a String useful for debugging (especially within a debugger.)
95 *
96 * @return a String useful for debugging.
97 */
98 @SuppressWarnings("boxing") // OK to ignore boxing here
99 @Override
100 public String toString() {
101 return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, " +
102 "modulus=%s, pos=%s, readPos=%s]", this.getClass().getSimpleName(), buffer, currentLinePos, eof,
103 ibitWorkArea, lbitWorkArea, modulus, pos, readPos);
104 }
105 }
106
107 /**
108 * EOF
109 *
110 * @since 1.7
111 */
112 static final int EOF = -1;
113
114 /**
115 * MIME chunk size per RFC 2045 section 6.8.
116 *
117 * <p>
118 * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
119 * equal signs.
120 * </p>
121 *
122 * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
123 */
124 public static final int MIME_CHUNK_SIZE = 76;
125
126 /**
127 * PEM chunk size per RFC 1421 section 4.3.2.4.
128 *
129 * <p>
130 * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
131 * equal signs.
132 * </p>
133 *
134 * @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421 section 4.3.2.4</a>
135 */
136 public static final int PEM_CHUNK_SIZE = 64;
137
138 private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
139
140 /**
141 * Defines the default buffer size - currently {@value}
142 * - must be large enough for at least one encoded block+separator
143 */
144 private static final int DEFAULT_BUFFER_SIZE = 8192;
145
146 /** Mask used to extract 8 bits, used in decoding bytes */
147 protected static final int MASK_8BITS = 0xff;
148
149 /**
150 * Byte used to pad output.
151 */
152 protected static final byte PAD_DEFAULT = '='; // Allow static access to default
153
154 protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later
155
156 /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
157 private final int unencodedBlockSize;
158
159 /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */
160 private final int encodedBlockSize;
161
162 /**
163 * Chunksize for encoding. Not used when decoding.
164 * A value of zero or less implies no chunking of the encoded data.
165 * Rounded down to nearest multiple of encodedBlockSize.
166 */
167 protected final int lineLength;
168
169 /**
170 * Size of chunk separator. Not used unless {@link #lineLength} > 0.
171 */
172 private final int chunkSeparatorLength;
173
174 /**
175 * Note <code>lineLength</code> is rounded down to the nearest multiple of {@link #encodedBlockSize}
176 * If <code>chunkSeparatorLength</code> is zero, then chunking is disabled.
177 * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
178 * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
179 * @param lineLength if &gt; 0, use chunking with a length <code>lineLength</code>
180 * @param chunkSeparatorLength the chunk separator length, if relevant
181 */
182 protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
183 final int lineLength, final int chunkSeparatorLength) {
184 this.unencodedBlockSize = unencodedBlockSize;
185 this.encodedBlockSize = encodedBlockSize;
186 final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0;
187 this.lineLength = useChunking ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;
188 this.chunkSeparatorLength = chunkSeparatorLength;
189 }
190
191 /**
192 * Returns true if this object has buffered data for reading.
193 *
194 * @param context the context to be used
195 * @return true if there is data still available for reading.
196 */
197 boolean hasData(final Context context) { // package protected for access from I/O streams
198 return context.buffer != null;
199 }
200
201 /**
202 * Returns the amount of buffered data available for reading.
203 *
204 * @param context the context to be used
205 * @return The amount of buffered data available for reading.
206 */
207 int available(final Context context) { // package protected for access from I/O streams
208 return context.buffer != null ? context.pos - context.readPos : 0;
209 }
210
211 /**
212 * Get the default buffer size. Can be overridden.
213 *
214 * @return {@link #DEFAULT_BUFFER_SIZE}
215 */
216 protected int getDefaultBufferSize() {
217 return DEFAULT_BUFFER_SIZE;
218 }
219
220 /**
221 * Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}.
222 * @param context the context to be used
223 */
224 private byte[] resizeBuffer(final Context context) {
225 if (context.buffer == null) {
226 context.buffer = new byte[getDefaultBufferSize()];
227 context.pos = 0;
228 context.readPos = 0;
229 } else {
230 final byte[] b = new byte[context.buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
231 System.arraycopy(context.buffer, 0, b, 0, context.buffer.length);
232 context.buffer = b;
233 }
234 return context.buffer;
235 }
236
237 /**
238 * Ensure that the buffer has room for <code>size</code> bytes
239 *
240 * @param size minimum spare space required
241 * @param context the context to be used
242 */
243 protected byte[] ensureBufferSize(final int size, final Context context){
244 if ((context.buffer == null) || (context.buffer.length < context.pos + size)){
245 return resizeBuffer(context);
246 }
247 return context.buffer;
248 }
249
250 /**
251 * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail
252 * bytes. Returns how many bytes were actually extracted.
253 * <p>
254 * Package protected for access from I/O streams.
255 *
256 * @param b
257 * byte[] array to extract the buffered data into.
258 * @param bPos
259 * position in byte[] array to start extraction at.
260 * @param bAvail
261 * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
262 * @param context
263 * the context to be used
264 * @return The number of bytes successfully extracted into the provided byte[] array.
265 */
266 int readResults(final byte[] b, final int bPos, final int bAvail, final Context context) {
267 if (context.buffer != null) {
268 final int len = Math.min(available(context), bAvail);
269 System.arraycopy(context.buffer, context.readPos, b, bPos, len);
270 context.readPos += len;
271 if (context.readPos >= context.pos) {
272 context.buffer = null; // so hasData() will return false, and this method can return -1
273 }
274 return len;
275 }
276 return context.eof ? EOF : 0;
277 }
278
279 /**
280 * Checks if a byte value is whitespace or not.
281 * Whitespace is taken to mean: space, tab, CR, LF
282 * @param byteToCheck
283 * the byte to check
284 * @return true if byte is whitespace, false otherwise
285 */
286 protected static boolean isWhiteSpace(final byte byteToCheck) {
287 switch (byteToCheck) {
288 case ' ' :
289 case '\n' :
290 case '\r' :
291 case '\t' :
292 return true;
293 default :
294 return false;
295 }
296 }
297
298 /**
299 * Encodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of
300 * the Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[].
301 *
302 * @param obj
303 * Object to encode
304 * @return An object (of type byte[]) containing the Base-N encoded data which corresponds to the byte[] supplied.
305 * @throws EncoderException
306 * if the parameter supplied is not of type byte[]
307 */
308 @Override
309 public Object encode(final Object obj) throws EncoderException {
310 if (!(obj instanceof byte[])) {
311 throw new EncoderException("Parameter supplied to Base-N encode is not a byte[]");
312 }
313 return encode((byte[]) obj);
314 }
315
316 /**
317 * Encodes a byte[] containing binary data, into a String containing characters in the Base-N alphabet.
318 * Uses UTF8 encoding.
319 *
320 * @param pArray
321 * a byte array containing binary data
322 * @return A String containing only Base-N character data
323 */
324 public String encodeToString(final byte[] pArray) {
325 return StringUtils.newStringUtf8(encode(pArray));
326 }
327
328 /**
329 * Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet.
330 * Uses UTF8 encoding.
331 *
332 * @param pArray a byte array containing binary data
333 * @return String containing only character data in the appropriate alphabet.
334 */
335 public String encodeAsString(final byte[] pArray){
336 return StringUtils.newStringUtf8(encode(pArray));
337 }
338
339 /**
340 * Decodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of
341 * the Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String.
342 *
343 * @param obj
344 * Object to decode
345 * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String
346 * supplied.
347 * @throws DecoderException
348 * if the parameter supplied is not of type byte[]
349 */
350 @Override
351 public Object decode(final Object obj) throws DecoderException {
352 if (obj instanceof byte[]) {
353 return decode((byte[]) obj);
354 } else if (obj instanceof String) {
355 return decode((String) obj);
356 } else {
357 throw new DecoderException("Parameter supplied to Base-N decode is not a byte[] or a String");
358 }
359 }
360
361 /**
362 * Decodes a String containing characters in the Base-N alphabet.
363 *
364 * @param pArray
365 * A String containing Base-N character data
366 * @return a byte array containing binary data
367 */
368 public byte[] decode(final String pArray) {
369 return decode(StringUtils.getBytesUtf8(pArray));
370 }
371
372 /**
373 * Decodes a byte[] containing characters in the Base-N alphabet.
374 *
375 * @param pArray
376 * A byte array containing Base-N character data
377 * @return a byte array containing binary data
378 */
379 @Override
380 public byte[] decode(final byte[] pArray) {
381 if (pArray == null || pArray.length == 0) {
382 return pArray;
383 }
384 final Context context = new Context();
385 decode(pArray, 0, pArray.length, context);
386 decode(pArray, 0, EOF, context); // Notify decoder of EOF.
387 final byte[] result = new byte[context.pos];
388 readResults(result, 0, result.length, context);
389 return result;
390 }
391
392 /**
393 * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
394 *
395 * @param pArray
396 * a byte array containing binary data
397 * @return A byte array containing only the basen alphabetic character data
398 */
399 @Override
400 public byte[] encode(final byte[] pArray) {
401 if (pArray == null || pArray.length == 0) {
402 return pArray;
403 }
404 final Context context = new Context();
405 encode(pArray, 0, pArray.length, context);
406 encode(pArray, 0, EOF, context); // Notify encoder of EOF.
407 final byte[] buf = new byte[context.pos - context.readPos];
408 readResults(buf, 0, buf.length, context);
409 return buf;
410 }
411
412 // package protected for access from I/O streams
413 abstract void encode(byte[] pArray, int i, int length, Context context);
414
415 // package protected for access from I/O streams
416 abstract void decode(byte[] pArray, int i, int length, Context context);
417
418 /**
419 * Returns whether or not the <code>octet</code> is in the current alphabet.
420 * Does not allow whitespace or pad.
421 *
422 * @param value The value to test
423 *
424 * @return {@code true} if the value is defined in the current alphabet, {@code false} otherwise.
425 */
426 protected abstract boolean isInAlphabet(byte value);
427
428 /**
429 * Tests a given byte array to see if it contains only valid characters within the alphabet.
430 * The method optionally treats whitespace and pad as valid.
431 *
432 * @param arrayOctet byte array to test
433 * @param allowWSPad if {@code true}, then whitespace and PAD are also allowed
434 *
435 * @return {@code true} if all bytes are valid characters in the alphabet or if the byte array is empty;
436 * {@code false}, otherwise
437 */
438 public boolean isInAlphabet(final byte[] arrayOctet, final boolean allowWSPad) {
439 for (int i = 0; i < arrayOctet.length; i++) {
440 if (!isInAlphabet(arrayOctet[i]) &&
441 (!allowWSPad || (arrayOctet[i] != PAD) && !isWhiteSpace(arrayOctet[i]))) {
442 return false;
443 }
444 }
445 return true;
446 }
447
448 /**
449 * Tests a given String to see if it contains only valid characters within the alphabet.
450 * The method treats whitespace and PAD as valid.
451 *
452 * @param basen String to test
453 * @return {@code true} if all characters in the String are valid characters in the alphabet or if
454 * the String is empty; {@code false}, otherwise
455 * @see #isInAlphabet(byte[], boolean)
456 */
457 public boolean isInAlphabet(final String basen) {
458 return isInAlphabet(StringUtils.getBytesUtf8(basen), true);
459 }
460
461 /**
462 * Tests a given byte array to see if it contains any characters within the alphabet or PAD.
463 *
464 * Intended for use in checking line-ending arrays
465 *
466 * @param arrayOctet
467 * byte array to test
468 * @return {@code true} if any byte is a valid character in the alphabet or PAD; {@code false} otherwise
469 */
470 protected boolean containsAlphabetOrPad(final byte[] arrayOctet) {
471 if (arrayOctet == null) {
472 return false;
473 }
474 for (final byte element : arrayOctet) {
475 if (PAD == element || isInAlphabet(element)) {
476 return true;
477 }
478 }
479 return false;
480 }
481
482 /**
483 * Calculates the amount of space needed to encode the supplied array.
484 *
485 * @param pArray byte[] array which will later be encoded
486 *
487 * @return amount of space needed to encoded the supplied array.
488 * Returns a long since a max-len array will require > Integer.MAX_VALUE
489 */
490 public long getEncodedLength(final byte[] pArray) {
491 // Calculate non-chunked size - rounded up to allow for padding
492 // cast to long is needed to avoid possibility of overflow
493 long len = ((pArray.length + unencodedBlockSize-1) / unencodedBlockSize) * (long) encodedBlockSize;
494 if (lineLength > 0) { // We're using chunking
495 // Round up to nearest multiple
496 len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength;
497 }
498 return len;
499 }
500}
diff --git a/java/client/src/org/apache/commons/codec/binary/StringUtils.java b/java/client/src/org/apache/commons/codec/binary/StringUtils.java
new file mode 100644
index 0000000..14a362f
--- /dev/null
+++ b/java/client/src/org/apache/commons/codec/binary/StringUtils.java
@@ -0,0 +1,343 @@
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.codec.binary;
19
20import java.io.UnsupportedEncodingException;
21import java.nio.charset.Charset;
22
23import org.apache.commons.codec.CharEncoding;
24import org.apache.commons.codec.Charsets;
25
26/**
27 * Converts String to and from bytes using the encodings required by the Java specification. These encodings are
28 * specified in <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">
29 * Standard charsets</a>.
30 *
31 * <p>This class is immutable and thread-safe.</p>
32 *
33 * @see CharEncoding
34 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
35 * @version $Id$
36 * @since 1.4
37 */
38public class StringUtils {
39
40 /**
41 * Calls {@link String#getBytes(Charset)}
42 *
43 * @param string
44 * The string to encode (if null, return null).
45 * @param charset
46 * The {@link Charset} to encode the {@code String}
47 * @return the encoded bytes
48 */
49 private static byte[] getBytes(final String string, final Charset charset) {
50 if (string == null) {
51 return null;
52 }
53 return string.getBytes(charset);
54 }
55
56 /**
57 * Encodes the given string into a sequence of bytes using the ISO-8859-1 charset, storing the result into a new
58 * byte array.
59 *
60 * @param string
61 * the String to encode, may be {@code null}
62 * @return encoded bytes, or {@code null} if the input string was {@code null}
63 * @throws NullPointerException
64 * Thrown if {@link Charsets#ISO_8859_1} is not initialized, which should never happen since it is
65 * required by the Java platform specification.
66 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
67 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
68 * @see #getBytesUnchecked(String, String)
69 */
70 public static byte[] getBytesIso8859_1(final String string) {
71 return getBytes(string, Charsets.ISO_8859_1);
72 }
73
74
75 /**
76 * Encodes the given string into a sequence of bytes using the named charset, storing the result into a new byte
77 * array.
78 * <p>
79 * This method catches {@link UnsupportedEncodingException} and rethrows it as {@link IllegalStateException}, which
80 * should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
81 * </p>
82 *
83 * @param string
84 * the String to encode, may be {@code null}
85 * @param charsetName
86 * The name of a required {@link java.nio.charset.Charset}
87 * @return encoded bytes, or {@code null} if the input string was {@code null}
88 * @throws IllegalStateException
89 * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
90 * required charset name.
91 * @see CharEncoding
92 * @see String#getBytes(String)
93 */
94 public static byte[] getBytesUnchecked(final String string, final String charsetName) {
95 if (string == null) {
96 return null;
97 }
98 try {
99 return string.getBytes(charsetName);
100 } catch (final UnsupportedEncodingException e) {
101 throw StringUtils.newIllegalStateException(charsetName, e);
102 }
103 }
104
105 /**
106 * Encodes the given string into a sequence of bytes using the US-ASCII charset, storing the result into a new byte
107 * array.
108 *
109 * @param string
110 * the String to encode, may be {@code null}
111 * @return encoded bytes, or {@code null} if the input string was {@code null}
112 * @throws NullPointerException
113 * Thrown if {@link Charsets#US_ASCII} is not initialized, which should never happen since it is
114 * required by the Java platform specification.
115 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
116 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
117 * @see #getBytesUnchecked(String, String)
118 */
119 public static byte[] getBytesUsAscii(final String string) {
120 return getBytes(string, Charsets.US_ASCII);
121 }
122
123 /**
124 * Encodes the given string into a sequence of bytes using the UTF-16 charset, storing the result into a new byte
125 * array.
126 *
127 * @param string
128 * the String to encode, may be {@code null}
129 * @return encoded bytes, or {@code null} if the input string was {@code null}
130 * @throws NullPointerException
131 * Thrown if {@link Charsets#UTF_16} is not initialized, which should never happen since it is
132 * required by the Java platform specification.
133 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
134 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
135 * @see #getBytesUnchecked(String, String)
136 */
137 public static byte[] getBytesUtf16(final String string) {
138 return getBytes(string, Charsets.UTF_16);
139 }
140
141 /**
142 * Encodes the given string into a sequence of bytes using the UTF-16BE charset, storing the result into a new byte
143 * array.
144 *
145 * @param string
146 * the String to encode, may be {@code null}
147 * @return encoded bytes, or {@code null} if the input string was {@code null}
148 * @throws NullPointerException
149 * Thrown if {@link Charsets#UTF_16BE} is not initialized, which should never happen since it is
150 * required by the Java platform specification.
151 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
152 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
153 * @see #getBytesUnchecked(String, String)
154 */
155 public static byte[] getBytesUtf16Be(final String string) {
156 return getBytes(string, Charsets.UTF_16BE);
157 }
158
159 /**
160 * Encodes the given string into a sequence of bytes using the UTF-16LE charset, storing the result into a new byte
161 * array.
162 *
163 * @param string
164 * the String to encode, may be {@code null}
165 * @return encoded bytes, or {@code null} if the input string was {@code null}
166 * @throws NullPointerException
167 * Thrown if {@link Charsets#UTF_16LE} is not initialized, which should never happen since it is
168 * required by the Java platform specification.
169 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
170 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
171 * @see #getBytesUnchecked(String, String)
172 */
173 public static byte[] getBytesUtf16Le(final String string) {
174 return getBytes(string, Charsets.UTF_16LE);
175 }
176
177 /**
178 * Encodes the given string into a sequence of bytes using the UTF-8 charset, storing the result into a new byte
179 * array.
180 *
181 * @param string
182 * the String to encode, may be {@code null}
183 * @return encoded bytes, or {@code null} if the input string was {@code null}
184 * @throws NullPointerException
185 * Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is
186 * required by the Java platform specification.
187 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
188 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
189 * @see #getBytesUnchecked(String, String)
190 */
191 public static byte[] getBytesUtf8(final String string) {
192 return getBytes(string, Charsets.UTF_8);
193 }
194
195 private static IllegalStateException newIllegalStateException(final String charsetName,
196 final UnsupportedEncodingException e) {
197 return new IllegalStateException(charsetName + ": " + e);
198 }
199
200 /**
201 * Constructs a new <code>String</code> by decoding the specified array of bytes using the given charset.
202 *
203 * @param bytes
204 * The bytes to be decoded into characters
205 * @param charset
206 * The {@link Charset} to encode the {@code String}
207 * @return A new <code>String</code> decoded from the specified array of bytes using the given charset,
208 * or {@code null} if the input byte array was {@code null}.
209 * @throws NullPointerException
210 * Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is
211 * required by the Java platform specification.
212 */
213 private static String newString(final byte[] bytes, final Charset charset) {
214 return bytes == null ? null : new String(bytes, charset);
215 }
216
217 /**
218 * Constructs a new <code>String</code> by decoding the specified array of bytes using the given charset.
219 * <p>
220 * This method catches {@link UnsupportedEncodingException} and re-throws it as {@link IllegalStateException}, which
221 * should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
222 * </p>
223 *
224 * @param bytes
225 * The bytes to be decoded into characters, may be {@code null}
226 * @param charsetName
227 * The name of a required {@link java.nio.charset.Charset}
228 * @return A new <code>String</code> decoded from the specified array of bytes using the given charset,
229 * or {@code null} if the input byte array was {@code null}.
230 * @throws IllegalStateException
231 * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
232 * required charset name.
233 * @see CharEncoding
234 * @see String#String(byte[], String)
235 */
236 public static String newString(final byte[] bytes, final String charsetName) {
237 if (bytes == null) {
238 return null;
239 }
240 try {
241 return new String(bytes, charsetName);
242 } catch (final UnsupportedEncodingException e) {
243 throw StringUtils.newIllegalStateException(charsetName, e);
244 }
245 }
246
247 /**
248 * Constructs a new <code>String</code> by decoding the specified array of bytes using the ISO-8859-1 charset.
249 *
250 * @param bytes
251 * The bytes to be decoded into characters, may be {@code null}
252 * @return A new <code>String</code> decoded from the specified array of bytes using the ISO-8859-1 charset, or
253 * {@code null} if the input byte array was {@code null}.
254 * @throws NullPointerException
255 * Thrown if {@link Charsets#ISO_8859_1} is not initialized, which should never happen since it is
256 * required by the Java platform specification.
257 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
258 */
259 public static String newStringIso8859_1(final byte[] bytes) {
260 return new String(bytes, Charsets.ISO_8859_1);
261 }
262
263 /**
264 * Constructs a new <code>String</code> by decoding the specified array of bytes using the US-ASCII charset.
265 *
266 * @param bytes
267 * The bytes to be decoded into characters
268 * @return A new <code>String</code> decoded from the specified array of bytes using the US-ASCII charset,
269 * or {@code null} if the input byte array was {@code null}.
270 * @throws NullPointerException
271 * Thrown if {@link Charsets#US_ASCII} is not initialized, which should never happen since it is
272 * required by the Java platform specification.
273 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
274 */
275 public static String newStringUsAscii(final byte[] bytes) {
276 return new String(bytes, Charsets.US_ASCII);
277 }
278
279 /**
280 * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16 charset.
281 *
282 * @param bytes
283 * The bytes to be decoded into characters
284 * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16 charset
285 * or {@code null} if the input byte array was {@code null}.
286 * @throws NullPointerException
287 * Thrown if {@link Charsets#UTF_16} is not initialized, which should never happen since it is
288 * required by the Java platform specification.
289 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
290 */
291 public static String newStringUtf16(final byte[] bytes) {
292 return new String(bytes, Charsets.UTF_16);
293 }
294
295 /**
296 * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16BE charset.
297 *
298 * @param bytes
299 * The bytes to be decoded into characters
300 * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16BE charset,
301 * or {@code null} if the input byte array was {@code null}.
302 * @throws NullPointerException
303 * Thrown if {@link Charsets#UTF_16BE} is not initialized, which should never happen since it is
304 * required by the Java platform specification.
305 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
306 */
307 public static String newStringUtf16Be(final byte[] bytes) {
308 return new String(bytes, Charsets.UTF_16BE);
309 }
310
311 /**
312 * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16LE charset.
313 *
314 * @param bytes
315 * The bytes to be decoded into characters
316 * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16LE charset,
317 * or {@code null} if the input byte array was {@code null}.
318 * @throws NullPointerException
319 * Thrown if {@link Charsets#UTF_16LE} is not initialized, which should never happen since it is
320 * required by the Java platform specification.
321 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
322 */
323 public static String newStringUtf16Le(final byte[] bytes) {
324 return new String(bytes, Charsets.UTF_16LE);
325 }
326
327 /**
328 * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-8 charset.
329 *
330 * @param bytes
331 * The bytes to be decoded into characters
332 * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-8 charset,
333 * or {@code null} if the input byte array was {@code null}.
334 * @throws NullPointerException
335 * Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is
336 * required by the Java platform specification.
337 * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
338 */
339 public static String newStringUtf8(final byte[] bytes) {
340 return newString(bytes, Charsets.UTF_8);
341 }
342
343}