package file updates

removed unused / old code
This commit is contained in:
Keith Donald
2008-04-13 02:02:50 +00:00
parent 3bd270729e
commit cef084c02f
44 changed files with 154 additions and 1439 deletions

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.util;
package org.springframework.webflow.action;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -32,7 +32,7 @@ import org.springframework.util.CachingMapDecorator;
* @author Keith Donald
* @author Ben Hale
*/
public class DispatchMethodInvoker {
class DispatchMethodInvoker {
/**
* The target object to dispatch to.

View File

@@ -33,7 +33,6 @@ import org.springframework.web.bind.WebDataBinder;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.ScopeType;
import org.springframework.webflow.util.DispatchMethodInvoker;
/**
* Multi-action that implements common logic dealing with input forms. This class leverages the Spring Web data binding

View File

@@ -18,7 +18,6 @@ package org.springframework.webflow.action;
import org.springframework.util.Assert;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.util.DispatchMethodInvoker;
/**
* Action implementation that bundles two or more action execution methods into a single class. Action execution methods

View File

@@ -8,8 +8,5 @@ When implementing custom actions, consider subclassing {@link org.springframewor
Alternatively, you could also subclass {@link org.springframework.webflow.action.MultiAction} to bundle several action
execution methods in a single class.
</p>
<p>
The {@link org.springframework.webflow.action.FormAction} provides powerful input form handling functionality.
</p>
</body>
</html>

View File

@@ -8,8 +8,7 @@ This is the highest-layer package in the framework, responsible for providing
a clean interface for configuring Spring Web Flow.
</p>
<p>
This package also defines a Spring 2.0 custom XML namespace for configuring
the Spring Web Flow engine in a Spring 2.0 environment.
This package also defines a Spring custom XML namespace for configuring the Spring Web Flow engine.
</p>
</body>
</html>

View File

@@ -1,5 +1,5 @@
<html>
<body>
Support code to allow access to the Spring Web Flow scopes (request, flash, flow conversation) from a Spring ApplicationContext.
Web Flow custom bean scopes allowing access to scoped-beans from a Spring ApplicationContext.
</body>
</html>

View File

@@ -0,0 +1,5 @@
<html>
<body>
Contains the PortletExternalContext implementation for calling into Web Flow from a Portlet.
</body>
</html>

View File

@@ -1,5 +1,5 @@
<html>
<body>
The representation of a client request into Spring Web Flow from an HTTP Servlet environment.
Contains the ServletExternalContext implementation for calling into Web Flow from a Servlet environment.
</body>
</html>

View File

@@ -0,0 +1,5 @@
<html>
<body>
Shared classes used by the Servlet and Portlet ExternalContext implementations.
</body>
</html>

View File

@@ -9,11 +9,8 @@ The central concept defined by this package is the
a service interface for managing conversations.
</p>
<p>
This package serves as a portable conversation management abstraction and does not depend on
the Spring Web Flow engine. It is used by the flow execution repository subsystem to store conversation related
state. It is important to realize that this subsystem does not define a conceptual <i>conversation</i>,
it just servers as a technical layer to manage state associated with conversations, as implemented by the
SWF engine.
This package serves as a portable conversation management abstraction and does not depend on the Spring Web Flow engine.
It is used by the flow execution repository subsystem to store conversation related state.
</p>
</body>
</html>

View File

@@ -5,37 +5,12 @@ Core, stable abstractions for representing flow definitions.
</p>
<p>
Each flow has an indentifier and is composed of one or more states, one of which is the start state.
States may be transitionable, and if so define one or more transitions that lead to other states.
States may be transitionable, if so they define one or more transitions that lead to other states.
</p>
<p>
With these types a client can introspect a flow definition to reason on its attributes and traverse
its structure, perhaps to display a visual diagram. Note that the types defined in this package
do not capture the behavioral characteristics of a flow.
</p>
<p>
The following code shows the beginnings of a basic flow definition traversal algorithm:
</p>
<pre class="code">
FlowDefinition flow = ...
// lookup start state
StateDefinition state = flow.getStartState();
// traverse to state transitions
traverse(state);
public void traverse(StateDefinition state) {
logger.info("State: " + state.getId());
while (state instanceof TransitionableStateDefinition) {
TransitionableStateDefinition transitionable = (TransitionableStateDefinition)state;
TransitionDefinition[] transitions = transitionable.getTransitions();
for (int i = 0; i &lt; transitions.length; i++) {
Transition t = transitions[i];
logger.info("Transition " + t.getId());
traverse(state.getOwner().getState(t.getTargetStateId());
}
}
}
</pre>
</body>
</html>

View File

@@ -1,25 +1,7 @@
<html>
<body>
<p>
The flow definition registry subsystem for managing containers of flow definitions.
The flow definition registry subsystem for managing collections of executable flow definitions.
</p>
<p>
You can construct a generic, initially empty FlowDefinitionRegistry, populate it
with flow definitions using a FlowDefinitionRegistrar, then lookup flow definitions by id.
For example:
</p>
<pre class="code">
// create registry
FlowDefinitionRegistry registry = new FlowDefinitionRegistryImpl();
// populate registry
FlowDefinitionRegistrar registrar = ..
registrar.addLocation(...);
registrar.addLocation(...);
registrar.registerFlowDefinitions(registry);
// use registry
FlowDefinition flow = registry.getFlow("myFlow");
</pre>
</body>
</html>

View File

@@ -0,0 +1,13 @@
<html>
<body>
<p>
Contains a FlowBuilder that builds {@link org.springframework.webflow.engine.Flow} instances from a
{@link org.springframework.webflow.engine.model.FlowModel}.
</p>
<p>
A FLowModel is a generic Java-based configuration model of a Flow, independent of any
external representation such as an XML file. Therefore, the FlowBuilder in this package may
engineer Flows from models produced from different representations.
</p>
</body>
</html>

View File

@@ -1,34 +1,12 @@
<html>
<body>
<p>
The flow builder subsystem for building and assembling executable flow definitions.
The FlowBuilder subsystem for building and assembling executable flow definitions.
</p>
<p>
You construct a Flow using a {@link org.springframework.webflow.engine.builder.FlowBuilder}.
This package defines the following flow builder implementations:
<ul>
<li>
{@link org.springframework.webflow.engine.builder.AbstractFlowBuilder} - A
convenience superclass to use when you want to assemble the web flow
in Java code.
</li>
<li>
{@link org.springframework.webflow.engine.builder.xml.XmlFlowBuilder} - A flow
builder that reads an XML file containing a web flow definition and
constructs the flow accordingly.
</li>
</ul>
<p>
During flow construction, a flow builder may need to access externally
managed <i>flow artifacts</i> referenced by the flow definition.
The {@link org.springframework.webflow.engine.builder.FlowServiceLocator} fulfills
this need, acting as a facade or gateway to an external registry of
flow artifacts (such as a Spring Bean Factory).
</p>
<p>
To direct flow construction, use the
{@link org.springframework.webflow.engine.builder.FlowAssembler}.
You construct a Flow using a {@link org.springframework.webflow.engine.builder.FlowBuilder} implementation.
This is done generally by using a {@link org.springframework.webflow.engine.builder.FlowAssembler}.
This package is based on the classic GoF Builder design pattern.
</p>
</body>
</body>
</html>

View File

@@ -0,0 +1,7 @@
<html>
<body>
<p>
Support classes for implementing FlowBuilders.
</p>
</body>
</html>

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.webflow.engine.impl;
import java.io.Serializable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
@@ -26,7 +24,6 @@ import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.execution.FlowExecutionFactory;
import org.springframework.webflow.execution.FlowExecutionKey;
import org.springframework.webflow.execution.FlowExecutionKeyFactory;
import org.springframework.webflow.util.RandomGuidUidGenerator;
/**
* A factory for instances of the {@link FlowExecutionImpl default flow execution} implementation.
@@ -39,7 +36,7 @@ public class FlowExecutionImplFactory extends FlowExecutionImplServicesConfigure
/**
* The factory used to assign keys to flow executions that need to be persisted.
*/
private FlowExecutionKeyFactory executionKeyFactory = new RandomFlowExecutionKeyFactory();
private FlowExecutionKeyFactory executionKeyFactory = new SimpleFlowExecutionKeyFactory();
/**
* Sets the strategy for generating flow execution keys for persistent flow executions.
@@ -60,13 +57,19 @@ public class FlowExecutionImplFactory extends FlowExecutionImplServicesConfigure
}
/**
* Generates random flow execution keys.
* Simple key factory suitable for standalone usage and testing. Not expected to be used in a web environment.
*/
private static class RandomFlowExecutionKeyFactory implements FlowExecutionKeyFactory {
private RandomGuidUidGenerator idGenerator = new RandomGuidUidGenerator();
private static class SimpleFlowExecutionKeyFactory implements FlowExecutionKeyFactory {
private int sequence;
public FlowExecutionKey getKey(FlowExecution execution) {
return new SimpleFlowExecutionKey(idGenerator.generateUid());
if (execution.getKey() == null) {
return new SimpleFlowExecutionKey(nextSequence());
} else {
// keep the same key
return execution.getKey();
}
}
public void removeAllFlowExecutionSnapshots(FlowExecution execution) {
@@ -78,27 +81,32 @@ public class FlowExecutionImplFactory extends FlowExecutionImplServicesConfigure
public void updateFlowExecutionSnapshot(FlowExecution execution) {
}
private static class SimpleFlowExecutionKey extends FlowExecutionKey {
private Serializable value;
private synchronized int nextSequence() {
return ++sequence;
}
public SimpleFlowExecutionKey(Serializable value) {
private static class SimpleFlowExecutionKey extends FlowExecutionKey {
private int value;
public SimpleFlowExecutionKey(int value) {
this.value = value;
}
public boolean equals(Object o) {
if (!(o instanceof SimpleFlowExecutionKey)) {
SimpleFlowExecutionKey key = (SimpleFlowExecutionKey) o;
return this.value.equals(key.value);
return value == key.value;
}
return false;
}
public int hashCode() {
return this.value.hashCode();
return value * 29;
}
public String toString() {
return value.toString();
return String.valueOf(value);
}
}
}

View File

@@ -1,7 +1,7 @@
<html>
<body>
<p>
The implementation of Spring Web Flow's flow execution machine.
The implementation of Spring Web Flow's flow execution engine, based on finite-state machine.
</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<html>
<body>
<p>
The FlowModelBuilder subsystem for building FlowModels, a configuration model for a Flow instance.
</p>
<p>
You construct a FlowModel using a {@link org.springframework.webflow.engine.model.builder.FlowModelBuilder}.
Implementations typically engineer a FlowModel from some external resource such as a file or database.
This package is based on the classic GoF Builder design pattern.
</p>
</body>
</html>

View File

@@ -0,0 +1,11 @@
<html>
<body>
<p>
Defines the XmlFlowModelBuilder, for building FlowModels from XML-based resources.
</p>
<p>
This package also contains the definition of the XML-based flow definition language,
defined within spring-webflow-2.0.xsd. See this schema for a detailed description of language elements.
</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<html>
<body>
<p>
Defines a configuration model for Flow instances.
</p>
<p>
A FlowModel is a generic Java-based configuration model of a Flow, independent of any
external flow representation such as an XML file. Flow Models can be merged together to
facilitate reuse between flows that share a common structure.
</p>
</body>
</html>

View File

@@ -0,0 +1,7 @@
<html>
<body>
<p>
The registry subsystem for managing collections of flow models.
</p>
</body>
</html>

View File

@@ -1,7 +1,7 @@
<html>
<body>
<p>
The implementation of the core flow definition artifacts that serve the basis of the flow execution engine.
The implementation of the web flow execution engine.
</p>
<p>
The engine implementation itself is located within the {@link org.springframework.webflow.engine.impl impl} package.

View File

@@ -1,7 +1,7 @@
<html>
<body>
<p>
Support implementations for internal engine-specific types.
Support implementations the engine uses internally.
</p>
</body>
</html>

View File

@@ -31,10 +31,22 @@ public interface FlowExecutionKeyFactory {
*/
public FlowExecutionKey getKey(FlowExecution execution);
/**
* Update the snapshot indexed by key of the provided execution to capture the execution's current state.
* @param execution the flow execution
*/
public void updateFlowExecutionSnapshot(FlowExecution execution);
/**
* Remove the snapshot indexed by the key of the provided flow execution from storage.
* @param execution the flow execution
*/
public void removeFlowExecutionSnapshot(FlowExecution execution);
/**
* Remove all snapshots associated with the flow execution from storage.
* @param execution the flow execution
*/
public void removeAllFlowExecutionSnapshots(FlowExecution execution);
}

View File

@@ -2,7 +2,7 @@
<body>
<p>
Supporting types often used by flow execution factory implementations. In particular, this
package provides a number of classes facillitating the registration of flow execution
package provides a number of classes allowing the registration of flow execution
listeners with a flow execution during its construction by a flow execution factory.
</p>
</body>

View File

@@ -27,18 +27,6 @@ lifecycle events.
</li>
</ul>
<p>
Package Usage example:
<pre class="code">
// create flow execution
FlowDefinition definition = ...
FlowExecutionFactory factory = ...
FlowExecution execution = factory.createFlowExecution(definition);
// start execution
ExternalContext context = ...
ViewSelection response = execution.start(null, context);
</pre>
<p>
This package depends on the definition package.
</p>
</body>

View File

@@ -1,7 +1,7 @@
<html>
<body>
<p>
Support for repositories that take flow execution continuation snapshots.
Support for repositories that take flow execution snapshots to support backtracking.
</p>
</body>
</html>

View File

@@ -1,7 +1,7 @@
<html>
<body>
<p>
The flow execution repository subsystem for saving, and restoring managed flow executions.
The flow execution repository subsystem for saving and restoring managed flow executions.
</p>
<p>
The central concept defined by this package is the

View File

@@ -1,7 +1,7 @@
<html>
<body>
<p>
Expression language integration. Contains Web Flow specific expression parsers.
Expression language integration. Contains Web Flow specific ExpressionParser implementations.
</p>
</body>
</html>

View File

@@ -0,0 +1,7 @@
<html>
<body>
<p>
The integration between Web Flow and Spring Portlet MVC, Spring's portlet application platform.
</p>
</body>
</html>

View File

@@ -0,0 +1,7 @@
<html>
<body>
<p>
Support for rendering Spring MVC-based Views within Web Flow.
</p>
</body>
</html>

View File

@@ -6,7 +6,7 @@ Support for testing flows and their associated artifacts.
<p>
When you want to unit test one of your flows the
{@link org.springframework.webflow.test.execution.AbstractFlowExecutionTests}
and associated subclasses provide a base you can extend.
and its associated subclasses provide a base you can extend.
</p>
<p>
When unit testing flow artifacts such as actions in isolation, the
@@ -21,4 +21,4 @@ Fowler's</a> reasoning. These classes are called <i>Mock</i>s to be consistent w
convention in the rest of the Spring framework (e.g. MockHttpServletRequest, ...).
</p>
</body>
</html>
</html>

View File

@@ -0,0 +1,7 @@
<html>
<body>
<p>
A migration tool to convert Web Flow version 1 flow definitions to the version 2 format.
</p>
</body>
</html>

View File

@@ -1,419 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* 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.
*/
package org.springframework.webflow.util;
/**
* Encodes and decodes to and from Base64 notation.
* <p>
* Based on Base64 encoder and decoder version 2.2.1 written by Robert Harder (<a
* href="http://iharder.net/base64">http://iharder.net/base64</a>). Modified by Erwin Vervaet to use the '.' character
* as padding character when using URL safe encoding, like in the Bouncy Castle URLBase64 encoder (<a
* href="http://www.bouncycastle.org/java.html">http://www.bouncycastle.org/java.html</a>).
*
* @author Robert Harder
* @author Erwin Vervaet
*/
public class Base64 {
/*
* static data used by the encoding and decoding algorithm
*/
/*
* The equals sign (=) as a byte.
*/
private static final byte EQUALS_SIGN = (byte) '=';
/* The dot (.) as a byte. */
private static final byte DOT = (byte) '.';
private static final byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
private static final byte PADDING_CHAR_ENC = -1; // Indicates padding char in encoding
/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
/** The 64 valid Base64 values. */
/* Host platform may be something funny like EBCDIC, so we hardcode these values. */
private static final byte[] STANDARD_ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E',
(byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N',
(byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W',
(byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
(byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x',
(byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
(byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/' };
/**
* Translates a Base64 value to either its 6-bit reconstruction value or a negative number indicating some other
* meaning.
*/
private static final byte[] STANDARD_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
-5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
62, // Plus sign at decimal 43
-9, -9, -9, // Decimal 44 - 46
63, // Slash at decimal 47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60
-1, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-9, -9, -9, -9, -9, -9, // Decimal 91 - 96
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
-9, -9, -9, -9 // Decimal 123 - 126
};
/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
/**
* Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: <a
* href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>. Notice that the last two
* bytes become "hyphen" and "underscore" instead of "plus" and "slash."
*/
private static final byte[] URL_SAFE_ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E',
(byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N',
(byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W',
(byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
(byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x',
(byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
(byte) '7', (byte) '8', (byte) '9', (byte) '-', (byte) '_' };
/**
* Used in decoding URL- and Filename-safe dialects of Base64.
*/
private static final byte[] URL_SAFE_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
-5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
-9, // Plus sign at decimal 43
-9, // Decimal 44
62, // Minus sign at decimal 45
-1, // Dot at decimal 46
-9, // Slash at decimal 47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60
-9, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-9, -9, -9, -9, // Decimal 91 - 94
63, // Underscore at decimal 95
-9, // Decimal 96
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
-9, -9, -9, -9 // Decimal 123 - 126
};
// instance members
/**
* Encode using Base64-like encoding that is URL- and Filename-safe as described in Section 4 of RFC3548: <a
* href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
*/
private boolean urlSafe;
private byte[] ALPHABET;
private byte[] DECODABET;
private byte PADDING_CHAR;
/**
* Create a new Base64 encoder and decoder using the standard Base64 alphabet. Note that the resulting encoded
* strings are not <i>URL-safe</i>: they will can contain characters that are subject to URL encoding.
*/
public Base64() {
this(false);
}
/**
* Create a new Base64 encoder and decoder.
* <p>
* Allows Base64-like encoding that is URL- and Filename-safe as described in Section 4 of RFC3548: <a
* href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>. When URL-safe encoding
* is used, the standard "=" Base64 padding character is replaced with the '.' character.
* <p>
* It is important to note that data encoded this way is <em>not</em> officially valid Base64, or at the very
* least should not be called Base64 without also specifying that is was encoded using the URL- and Filename-safe
* dialect
*
* @param urlSafe if true, URL safe encoding and decoding will be used
*/
public Base64(boolean urlSafe) {
this.urlSafe = urlSafe;
if (urlSafe) {
ALPHABET = URL_SAFE_ALPHABET;
DECODABET = URL_SAFE_DECODABET;
PADDING_CHAR = DOT;
} else {
ALPHABET = STANDARD_ALPHABET;
DECODABET = STANDARD_DECODABET;
PADDING_CHAR = EQUALS_SIGN;
}
}
/**
* Returns whether or not this coder is using Base64-like encoding that is URL- and Filename-safe as described in
* Section 4 of RFC3548: <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
* When URL-safe encoding is used, the standard "=" Base64 padding character is replaced with the '.' character.
* <p>
* It is important to note that data encoded this way is <em>not</em> officially valid Base64, or at the very
* least should not be called Base64 without also specifying that is was encoded using the URL- and Filename-safe
* dialect.
* @return true or false
*/
public boolean isUrlSafe() {
return urlSafe;
}
/* ******** E N C O D I N G M E T H O D S ******** */
/**
* Encodes up to three bytes of the array <var>source</var> and writes the resulting four Base64 bytes to
* <var>destination</var>. The source and destination arrays can be manipulated anywhere along their length by
* specifying <var>srcOffset</var> and <var>destOffset</var>. This method does not check to make sure your arrays
* are large enough to accomodate <var>srcOffset</var> + 3 for the <var>source</var> array or <var>destOffset</var> +
* 4 for the <var>destination</var> array. The actual number of significant bytes in your array is given by
* <var>numSigBytes</var>.
* </p>
* <p>
* This is the lowest level of the encoding methods with all possible parameters.
* </p>
* @param source the array to convert
* @param srcOffset the index where conversion begins
* @param numSigBytes the number of significant bytes in your array
* @param destination the array to hold the conversion
* @param destOffset the index where output will be put
* @return the <var>destination</var> array
*/
private byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset) {
// 1 2 3
// 01234567890123456789012345678901 Bit position
// --------000000001111111122222222 Array position from threeBytes
// --------| || || || | Six bit groups to index ALPHABET
// >>18 >>12 >> 6 >> 0 Right shift necessary
// 0x3f 0x3f 0x3f Additional AND
// Create buffer with zero-padding if there are only one or two
// significant bytes passed in the array.
// We have to shift left 24 in order to flush out the 1's that appear
// when Java treats a value as negative that is cast from a byte to an int.
int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
| (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
| (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
switch (numSigBytes) {
case 3:
destination[destOffset] = ALPHABET[(inBuff >>> 18)];
destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
return destination;
case 2:
destination[destOffset] = ALPHABET[(inBuff >>> 18)];
destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
destination[destOffset + 3] = PADDING_CHAR;
return destination;
case 1:
destination[destOffset] = ALPHABET[(inBuff >>> 18)];
destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
destination[destOffset + 2] = PADDING_CHAR;
destination[destOffset + 3] = PADDING_CHAR;
return destination;
default:
return destination;
}
}
/**
* Encodes a byte array into Base64 notation.
* @param source the data to convert
* @param off offset in array where conversion should begin
* @param len length of data to convert
* @return the encoded data
*/
public final byte[] encode(byte[] source, int off, int len) {
int len43 = len * 4 / 3;
byte[] outBuff = new byte[(len43) // main 4:3
+ ((len % 3) > 0 ? 4 : 0)]; // account for padding
int d = 0;
int e = 0;
int len2 = len - 2;
int lineLength = 0;
for (; d < len2; d += 3, e += 4) {
encode3to4(source, d + off, 3, outBuff, e);
lineLength += 4;
} // end for: each piece of array
if (d < len) {
encode3to4(source, d + off, len - d, outBuff, e);
e += 4;
} // end if: some padding needed
byte[] out = new byte[e];
System.arraycopy(outBuff, 0, out, 0, e);
return out;
}
/**
* Encodes a byte array into Base64 notation.
* @param source the data to encode
* @return the encoded data
*/
public final byte[] encode(byte[] source) {
return encode(source, 0, source.length);
}
/**
* Encodes a byte array into Base64 notation. The resulting string will be created using the platform default
* encoding.
* @param source the source data to encode
* @return the encoded data
*/
public final String encodeToString(byte[] source) {
return new String(encode(source));
}
/* ******** D E C O D I N G M E T H O D S ******** */
/**
* Decodes four bytes from array <var>source</var> and writes the resulting bytes (up to three of them) to
* <var>destination</var>. The source and destination arrays can be manipulated anywhere along their length by
* specifying <var>srcOffset</var> and <var>destOffset</var>. This method does not check to make sure your arrays
* are large enough to accomodate <var>srcOffset</var> + 4 for the <var>source</var> array or <var>destOffset</var> +
* 3 for the <var>destination</var> array. This method returns the actual number of bytes that were converted from
* the Base64 encoding.
* <p>
* This is the lowest level of the decoding methods with all possible parameters.
* </p>
* @param source the array to convert
* @param srcOffset the index where conversion begins
* @param destination the array to hold the conversion
* @param destOffset the index where output will be put
* @return the number of decoded bytes converted
*/
private final int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset) {
// Example: Dk== or Dk..
if (source[srcOffset + 2] == PADDING_CHAR) {
int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);
destination[destOffset] = (byte) (outBuff >>> 16);
return 1;
}
// Example: DkL= or DkL.
else if (source[srcOffset + 3] == PADDING_CHAR) {
int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
| ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6);
destination[destOffset] = (byte) (outBuff >>> 16);
destination[destOffset + 1] = (byte) (outBuff >>> 8);
return 2;
}
// Example: DkLE
else {
int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
| ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) | ((DECODABET[source[srcOffset + 3]] & 0xFF));
destination[destOffset] = (byte) (outBuff >> 16);
destination[destOffset + 1] = (byte) (outBuff >> 8);
destination[destOffset + 2] = (byte) (outBuff);
return 3;
}
}
/**
* Very low-level access to decoding ASCII characters in the form of a byte array.
* @param source the Base64 encoded data
* @param off the offset of where to begin decoding
* @param len the length of characters to decode
* @return decoded data
*/
public final byte[] decode(byte[] source, int off, int len) {
int len34 = len * 3 / 4;
byte[] outBuff = new byte[len34]; // upper limit on size of output
int outBuffPosn = 0;
byte[] b4 = new byte[4];
int b4Posn = 0;
int i = 0;
byte sbiCrop = 0;
byte sbiDecode = 0;
for (i = off; i < off + len; i++) {
sbiCrop = (byte) (source[i] & 0x7f); // only the low seven bits
sbiDecode = DECODABET[sbiCrop];
if (sbiDecode >= WHITE_SPACE_ENC) { // white space, equals sign or better
if (sbiDecode >= PADDING_CHAR_ENC) {
b4[b4Posn++] = sbiCrop;
if (b4Posn > 3) {
outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
b4Posn = 0;
// if that was the padding char, break out of 'for' loop
if (sbiCrop == PADDING_CHAR) {
break;
}
} // end if: quartet built
} // end if: equals sign or better
} // end if: white space, equals sign or better
else {
// discard
}
} // each input character
byte[] out = new byte[outBuffPosn];
System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
return out;
}
/**
* Decodes data from Base64 notation.
* @param source the source data
* @return the decoded data
*/
public final byte[] decode(byte[] source) {
return decode(source, 0, source.length);
}
/**
* Decodes data from Base64 notation. Uses the platform default character set to obtain bytes from given string.
* @param s the string to decode
* @return the decoded data
*/
public final byte[] decodeFromString(String s) {
return decode(s.getBytes());
}
}

View File

@@ -1,195 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* 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.
*/
package org.springframework.webflow.util;
/*
* RandomGUID from http://www.javaexchange.com/aboutRandomGUID.html
* @version 1.2.1 11/05/02 @author Marc A. Mnich
*
* From www.JavaExchange.com, Open Software licensing
*
* 11/05/02 -- Performance enhancement from Mike Dubman. Moved InetAddr.getLocal to static block. Mike has measured a 10
* fold improvement in run time. 01/29/02 -- Bug fix: Improper seeding of nonsecure Random object caused duplicate GUIDs
* to be produced. Random object is now only created once per JVM. 01/19/02 -- Modified random seeding and added new
* constructor to allow secure random feature. 01/14/02 -- Added random function seeding with JVM run time
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
/**
* Globally unique identifier generator.
* <p>
* In the multitude of java GUID generators, I found none that guaranteed randomness. GUIDs are guaranteed to be
* globally unique by using ethernet MACs, IP addresses, time elements, and sequential numbers. GUIDs are not expected
* to be random and most often are easy/possible to guess given a sample from a given generator. SQL Server, for example
* generates GUID that are unique but sequencial within a given instance.
* <p>
* GUIDs can be used as security devices to hide things such as files within a filesystem where listings are unavailable
* (e.g. files that are served up from a Web server with indexing turned off). This may be desireable in cases where
* standard authentication is not appropriate. In this scenario, the RandomGuids are used as directories. Another
* example is the use of GUIDs for primary keys in a database where you want to ensure that the keys are secret. Random
* GUIDs can then be used in a URL to prevent hackers (or users) from accessing records by guessing or simply by
* incrementing sequential numbers.
* <p>
* There are many other possiblities of using GUIDs in the realm of security and encryption where the element of
* randomness is important. This class was written for these purposes but can also be used as a general purpose GUID
* generator as well.
* <p>
* RandomGuid generates truly random GUIDs by using the system's IP address (name/IP), system time in milliseconds (as
* an integer), and a very large random number joined together in a single String that is passed through an MD5 hash.
* The IP address and system time make the MD5 seed globally unique and the random number guarantees that the generated
* GUIDs will have no discernable pattern and cannot be guessed given any number of previously generated GUIDs. It is
* generally not possible to access the seed information (IP, time, random number) from the resulting GUIDs as the MD5
* hash algorithm provides one way encryption.
* <p>
* <b>Security of RandomGuid</b>: RandomGuid can be called one of two ways -- with the basic java Random number
* generator or a cryptographically strong random generator (SecureRandom). The choice is offered because the secure
* random generator takes about 3.5 times longer to generate its random numbers and this performance hit may not be
* worth the added security especially considering the basic generator is seeded with a cryptographically strong random
* seed.
* <p>
* Seeding the basic generator in this way effectively decouples the random numbers from the time component making it
* virtually impossible to predict the random number component even if one had absolute knowledge of the System time.
* Thanks to Ashutosh Narhari for the suggestion of using the static method to prime the basic random generator.
* <p>
* Using the secure random option, this class complies with the statistical random number generator tests specified in
* FIPS 140-2, Security Requirements for Cryptographic Modules, secition 4.9.1.
* <p>
* I converted all the pieces of the seed to a String before handing it over to the MD5 hash so that you could print it
* out to make sure it contains the data you expect to see and to give a nice warm fuzzy. If you need better
* performance, you may want to stick to byte[] arrays.
* <p>
* I believe that it is important that the algorithm for generating random GUIDs be open for inspection and
* modification. This class is free for all uses.
*
* @version 1.2.1 11/05/02
* @author Marc A. Mnich
*/
public class RandomGuid {
private static Random random;
private static SecureRandom secureRandom;
private static String id;
private String guid;
/*
* Static block to take care of one time secureRandom seed. It takes a few seconds to initialize SecureRandom. You
* might want to consider removing this static block or replacing it with a "time since first loaded" seed to reduce
* this time. This block will run only once per JVM instance.
*/
static {
secureRandom = new SecureRandom();
long secureInitializer = secureRandom.nextLong();
random = new Random(secureInitializer);
try {
id = InetAddress.getLocalHost().toString();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
/**
* Default constructor. With no specification of security option, this constructor defaults to lower security, high
* performance.
*/
public RandomGuid() {
getRandomGuid(false);
}
/**
* Constructor with security option. Setting secure true enables each random number generated to be
* cryptographically strong. Secure false defaults to the standard Random function seeded with a single
* cryptographically strong random number.
*/
public RandomGuid(boolean secure) {
getRandomGuid(secure);
}
/**
* Method to generate the random GUID.
*/
private void getRandomGuid(boolean secure) {
MessageDigest md5 = null;
StringBuffer sbValueBeforeMD5 = new StringBuffer();
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
long time = System.currentTimeMillis();
long rand = 0;
if (secure) {
rand = secureRandom.nextLong();
} else {
rand = random.nextLong();
}
// This StringBuffer can be a long as you need; the MD5
// hash will always return 128 bits. You can change
// the seed to include anything you want here.
// You could even stream a file through the MD5 making
// the odds of guessing it at least as great as that
// of guessing the contents of the file!
sbValueBeforeMD5.append(id);
sbValueBeforeMD5.append(":");
sbValueBeforeMD5.append(Long.toString(time));
sbValueBeforeMD5.append(":");
sbValueBeforeMD5.append(Long.toString(rand));
String valueBeforeMD5 = sbValueBeforeMD5.toString();
md5.update(valueBeforeMD5.getBytes());
byte[] array = md5.digest();
StringBuffer sb = new StringBuffer();
for (int j = 0; j < array.length; ++j) {
int b = array[j] & 0xFF;
if (b < 0x10)
sb.append('0');
sb.append(Integer.toHexString(b));
}
guid = sb.toString();
}
/**
* Convert to the standard format for GUID (Useful for SQL Server UniqueIdentifiers, etc). Example:
* "C2FEEEAC-CFCD-11D1-8B05-00600806D9B6".
*/
public String toString() {
String raw = guid.toUpperCase();
StringBuffer sb = new StringBuffer();
sb.append(raw.substring(0, 8));
sb.append("-");
sb.append(raw.substring(8, 12));
sb.append("-");
sb.append(raw.substring(12, 16));
sb.append("-");
sb.append(raw.substring(16, 20));
sb.append("-");
sb.append(raw.substring(20));
return sb.toString();
}
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* 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.
*/
package org.springframework.webflow.util;
import java.io.Serializable;
/**
* A key generator that uses the RandomGuid support class. The default implementation used by the webflow system.
*
* @author Keith Donald
*/
public class RandomGuidUidGenerator implements UidGenerator, Serializable {
/**
* Should the random GUID generated be secure?
*/
private boolean secure;
/**
* Returns whether or not the generated random numbers are <i>secure</i>, meaning cryptographically strong.
*/
public boolean isSecure() {
return secure;
}
/**
* Sets whether or not the generated random numbers should be <i>secure</i>. If set to true, generated GUIDs are
* cryptographically strong.
*/
public void setSecure(boolean secure) {
this.secure = secure;
}
public Serializable generateUid() {
return new RandomGuid(secure).toString();
}
public Serializable parseUid(String encodedUid) {
return encodedUid;
}
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* 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.
*/
package org.springframework.webflow.util;
import org.springframework.core.io.Resource;
/**
* Simple interface for all objects (typically flow builders) that hold on to a resource defining a flow (e.g. an XML
* file). Provides a way to access information about the underlying resource like the last modified date.
*
* @see org.springframework.webflow.engine.builder.FlowBuilder
*
* @author Erwin Vervaet
* @author Keith Donald
*/
public interface ResourceHolder {
/**
* Returns the flow definition resource held by this holder.
*/
public Resource getResource();
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* 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.
*/
package org.springframework.webflow.util;
import java.io.Serializable;
/**
* A strategy for generating ids for uniquely identifying execution artifacts such as FlowExecutions and any other
* uniquely identified flow artifact.
*
* @author Keith Donald
*/
public interface UidGenerator {
/**
* Generate a new unique id.
* @return a serializable id, guaranteed to be unique in some context
*/
public Serializable generateUid();
/**
* Convert the string-encoded uid into its original object form.
* @param encodedUid the string encoded uid
* @return the converted uid
*/
public Serializable parseUid(String encodedUid);
}

View File

@@ -1,5 +0,0 @@
<html>
<body>
General purpose utility classes used internally by the Spring Web Flow system.
</body>
</html>

View File

@@ -13,7 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.util;
package org.springframework.webflow.action;
import org.springframework.webflow.action.DispatchMethodInvoker;
import junit.framework.TestCase;

View File

@@ -17,6 +17,7 @@ package org.springframework.webflow.action;
import junit.framework.TestCase;
import org.springframework.webflow.action.DispatchMethodInvoker.MethodLookupException;
import org.springframework.webflow.action.MultiAction.MethodResolver;
import org.springframework.webflow.engine.AnnotatedAction;
import org.springframework.webflow.engine.StubViewFactory;
@@ -24,7 +25,6 @@ import org.springframework.webflow.engine.ViewState;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.test.MockFlowSession;
import org.springframework.webflow.test.MockRequestContext;
import org.springframework.webflow.util.DispatchMethodInvoker.MethodLookupException;
/**
* Unit tests for {@link MultiAction}.

View File

@@ -9,7 +9,6 @@ import org.springframework.webflow.engine.EndState;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.builder.support.AbstractFlowBuilder;
import org.springframework.webflow.test.MockFlowBuilderContext;
import org.springframework.webflow.util.ResourceHolder;
public class DefaultFlowHolderTests extends TestCase {
private DefaultFlowHolder holder;
@@ -47,7 +46,7 @@ public class DefaultFlowHolderTests extends TestCase {
}
public class ChangeDetectableFlowBuilder extends SimpleFlowBuilder implements ResourceHolder {
public class ChangeDetectableFlowBuilder extends SimpleFlowBuilder {
private FileSystemResource resource = new FileSystemResource("file.txt");
public Resource getResource() {

View File

@@ -2,14 +2,12 @@ package org.springframework.webflow.engine.model.registry;
import junit.framework.TestCase;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.webflow.engine.model.AbstractStateModel;
import org.springframework.webflow.engine.model.EndStateModel;
import org.springframework.webflow.engine.model.FlowModel;
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
import org.springframework.webflow.engine.model.builder.FlowModelBuilderException;
import org.springframework.webflow.util.ResourceHolder;
public class DefaultFlowModelHolderTests extends TestCase {
private DefaultFlowModelHolder holder;
@@ -67,13 +65,4 @@ public class DefaultFlowModelHolderTests extends TestCase {
}
}
public class ChangeDetectableFlowBuilder extends SimpleFlowBuilder implements ResourceHolder {
private FileSystemResource resource = new FileSystemResource("file.txt");
public Resource getResource() {
return resource;
}
}
}

View File

@@ -1,554 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* 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.
*/
package org.springframework.webflow.util;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Random;
import junit.framework.TestCase;
/**
* Test case for {@link Base64}. Based on Base64Test from Jakarta Commons Codec 1.3.
*
* @author Erwin Vervaet
*/
public class Base64Tests extends TestCase {
private Random random = new Random();
public Random getRandom() {
return this.random;
}
public void testBase64() {
assertEquals("SGVsbG8gV29ybGQ=", new Base64().encodeToString("Hello World".getBytes()));
assertEquals("SGVsbG8gV29ybGQ.", new Base64(true).encodeToString("Hello World".getBytes()));
}
public void testDecodePadMarkerIndex2() {
assertEquals("A", new String(new Base64().decodeFromString("QQ==")));
assertEquals("A", new String(new Base64(true).decodeFromString("QQ..")));
}
public void testDecodePadMarkerIndex3() {
assertEquals("AA", new String(new Base64().decodeFromString("QUE=")));
assertEquals("AAA", new String(new Base64().decodeFromString("QUFB")));
assertEquals("AA", new String(new Base64(true).decodeFromString("QUE.")));
assertEquals("AAA", new String(new Base64(true).decodeFromString("QUFB")));
}
public void testEncodeEmptyString() {
assertEquals("", new Base64().encodeToString("".getBytes()));
}
public void testDecodeEmptyString() {
assertEquals("", new String(new Base64().decodeFromString("")));
}
// encode/decode random arrays from size 0 to size 11
public void testEncodeDecodeSmall() {
for (int i = 0; i < 12; i++) {
byte[] data = new byte[i];
this.getRandom().nextBytes(data);
byte[] enc = new Base64().encode(data);
byte[] data2 = new Base64().decode(enc);
assertTrue(Arrays.equals(data, data2));
}
}
// encode/decode a large random array
public void testEncodeDecodeRandom() {
for (int i = 1; i < 5; i++) {
byte[] data = new byte[this.getRandom().nextInt(10000) + 1];
this.getRandom().nextBytes(data);
byte[] enc = new Base64().encode(data);
byte[] data2 = new Base64().decode(enc);
assertTrue(Arrays.equals(data, data2));
}
}
public void testSingletons() {
assertEquals("AA==", new String(new Base64().encode(new byte[] { (byte) 0 })));
assertEquals("AQ==", new String(new Base64().encode(new byte[] { (byte) 1 })));
assertEquals("Ag==", new String(new Base64().encode(new byte[] { (byte) 2 })));
assertEquals("Aw==", new String(new Base64().encode(new byte[] { (byte) 3 })));
assertEquals("BA==", new String(new Base64().encode(new byte[] { (byte) 4 })));
assertEquals("BQ==", new String(new Base64().encode(new byte[] { (byte) 5 })));
assertEquals("Bg==", new String(new Base64().encode(new byte[] { (byte) 6 })));
assertEquals("Bw==", new String(new Base64().encode(new byte[] { (byte) 7 })));
assertEquals("CA==", new String(new Base64().encode(new byte[] { (byte) 8 })));
assertEquals("CQ==", new String(new Base64().encode(new byte[] { (byte) 9 })));
assertEquals("Cg==", new String(new Base64().encode(new byte[] { (byte) 10 })));
assertEquals("Cw==", new String(new Base64().encode(new byte[] { (byte) 11 })));
assertEquals("DA==", new String(new Base64().encode(new byte[] { (byte) 12 })));
assertEquals("DQ==", new String(new Base64().encode(new byte[] { (byte) 13 })));
assertEquals("Dg==", new String(new Base64().encode(new byte[] { (byte) 14 })));
assertEquals("Dw==", new String(new Base64().encode(new byte[] { (byte) 15 })));
assertEquals("EA==", new String(new Base64().encode(new byte[] { (byte) 16 })));
assertEquals("EQ==", new String(new Base64().encode(new byte[] { (byte) 17 })));
assertEquals("Eg==", new String(new Base64().encode(new byte[] { (byte) 18 })));
assertEquals("Ew==", new String(new Base64().encode(new byte[] { (byte) 19 })));
assertEquals("FA==", new String(new Base64().encode(new byte[] { (byte) 20 })));
assertEquals("FQ==", new String(new Base64().encode(new byte[] { (byte) 21 })));
assertEquals("Fg==", new String(new Base64().encode(new byte[] { (byte) 22 })));
assertEquals("Fw==", new String(new Base64().encode(new byte[] { (byte) 23 })));
assertEquals("GA==", new String(new Base64().encode(new byte[] { (byte) 24 })));
assertEquals("GQ==", new String(new Base64().encode(new byte[] { (byte) 25 })));
assertEquals("Gg==", new String(new Base64().encode(new byte[] { (byte) 26 })));
assertEquals("Gw==", new String(new Base64().encode(new byte[] { (byte) 27 })));
assertEquals("HA==", new String(new Base64().encode(new byte[] { (byte) 28 })));
assertEquals("HQ==", new String(new Base64().encode(new byte[] { (byte) 29 })));
assertEquals("Hg==", new String(new Base64().encode(new byte[] { (byte) 30 })));
assertEquals("Hw==", new String(new Base64().encode(new byte[] { (byte) 31 })));
assertEquals("IA==", new String(new Base64().encode(new byte[] { (byte) 32 })));
assertEquals("IQ==", new String(new Base64().encode(new byte[] { (byte) 33 })));
assertEquals("Ig==", new String(new Base64().encode(new byte[] { (byte) 34 })));
assertEquals("Iw==", new String(new Base64().encode(new byte[] { (byte) 35 })));
assertEquals("JA==", new String(new Base64().encode(new byte[] { (byte) 36 })));
assertEquals("JQ==", new String(new Base64().encode(new byte[] { (byte) 37 })));
assertEquals("Jg==", new String(new Base64().encode(new byte[] { (byte) 38 })));
assertEquals("Jw==", new String(new Base64().encode(new byte[] { (byte) 39 })));
assertEquals("KA==", new String(new Base64().encode(new byte[] { (byte) 40 })));
assertEquals("KQ==", new String(new Base64().encode(new byte[] { (byte) 41 })));
assertEquals("Kg==", new String(new Base64().encode(new byte[] { (byte) 42 })));
assertEquals("Kw==", new String(new Base64().encode(new byte[] { (byte) 43 })));
assertEquals("LA==", new String(new Base64().encode(new byte[] { (byte) 44 })));
assertEquals("LQ==", new String(new Base64().encode(new byte[] { (byte) 45 })));
assertEquals("Lg==", new String(new Base64().encode(new byte[] { (byte) 46 })));
assertEquals("Lw==", new String(new Base64().encode(new byte[] { (byte) 47 })));
assertEquals("MA==", new String(new Base64().encode(new byte[] { (byte) 48 })));
assertEquals("MQ==", new String(new Base64().encode(new byte[] { (byte) 49 })));
assertEquals("Mg==", new String(new Base64().encode(new byte[] { (byte) 50 })));
assertEquals("Mw==", new String(new Base64().encode(new byte[] { (byte) 51 })));
assertEquals("NA==", new String(new Base64().encode(new byte[] { (byte) 52 })));
assertEquals("NQ==", new String(new Base64().encode(new byte[] { (byte) 53 })));
assertEquals("Ng==", new String(new Base64().encode(new byte[] { (byte) 54 })));
assertEquals("Nw==", new String(new Base64().encode(new byte[] { (byte) 55 })));
assertEquals("OA==", new String(new Base64().encode(new byte[] { (byte) 56 })));
assertEquals("OQ==", new String(new Base64().encode(new byte[] { (byte) 57 })));
assertEquals("Og==", new String(new Base64().encode(new byte[] { (byte) 58 })));
assertEquals("Ow==", new String(new Base64().encode(new byte[] { (byte) 59 })));
assertEquals("PA==", new String(new Base64().encode(new byte[] { (byte) 60 })));
assertEquals("PQ==", new String(new Base64().encode(new byte[] { (byte) 61 })));
assertEquals("Pg==", new String(new Base64().encode(new byte[] { (byte) 62 })));
assertEquals("Pw==", new String(new Base64().encode(new byte[] { (byte) 63 })));
assertEquals("QA==", new String(new Base64().encode(new byte[] { (byte) 64 })));
assertEquals("QQ==", new String(new Base64().encode(new byte[] { (byte) 65 })));
assertEquals("Qg==", new String(new Base64().encode(new byte[] { (byte) 66 })));
assertEquals("Qw==", new String(new Base64().encode(new byte[] { (byte) 67 })));
assertEquals("RA==", new String(new Base64().encode(new byte[] { (byte) 68 })));
assertEquals("RQ==", new String(new Base64().encode(new byte[] { (byte) 69 })));
assertEquals("Rg==", new String(new Base64().encode(new byte[] { (byte) 70 })));
assertEquals("Rw==", new String(new Base64().encode(new byte[] { (byte) 71 })));
assertEquals("SA==", new String(new Base64().encode(new byte[] { (byte) 72 })));
assertEquals("SQ==", new String(new Base64().encode(new byte[] { (byte) 73 })));
assertEquals("Sg==", new String(new Base64().encode(new byte[] { (byte) 74 })));
assertEquals("Sw==", new String(new Base64().encode(new byte[] { (byte) 75 })));
assertEquals("TA==", new String(new Base64().encode(new byte[] { (byte) 76 })));
assertEquals("TQ==", new String(new Base64().encode(new byte[] { (byte) 77 })));
assertEquals("Tg==", new String(new Base64().encode(new byte[] { (byte) 78 })));
assertEquals("Tw==", new String(new Base64().encode(new byte[] { (byte) 79 })));
assertEquals("UA==", new String(new Base64().encode(new byte[] { (byte) 80 })));
assertEquals("UQ==", new String(new Base64().encode(new byte[] { (byte) 81 })));
assertEquals("Ug==", new String(new Base64().encode(new byte[] { (byte) 82 })));
assertEquals("Uw==", new String(new Base64().encode(new byte[] { (byte) 83 })));
assertEquals("VA==", new String(new Base64().encode(new byte[] { (byte) 84 })));
assertEquals("VQ==", new String(new Base64().encode(new byte[] { (byte) 85 })));
assertEquals("Vg==", new String(new Base64().encode(new byte[] { (byte) 86 })));
assertEquals("Vw==", new String(new Base64().encode(new byte[] { (byte) 87 })));
assertEquals("WA==", new String(new Base64().encode(new byte[] { (byte) 88 })));
assertEquals("WQ==", new String(new Base64().encode(new byte[] { (byte) 89 })));
assertEquals("Wg==", new String(new Base64().encode(new byte[] { (byte) 90 })));
assertEquals("Ww==", new String(new Base64().encode(new byte[] { (byte) 91 })));
assertEquals("XA==", new String(new Base64().encode(new byte[] { (byte) 92 })));
assertEquals("XQ==", new String(new Base64().encode(new byte[] { (byte) 93 })));
assertEquals("Xg==", new String(new Base64().encode(new byte[] { (byte) 94 })));
assertEquals("Xw==", new String(new Base64().encode(new byte[] { (byte) 95 })));
assertEquals("YA==", new String(new Base64().encode(new byte[] { (byte) 96 })));
assertEquals("YQ==", new String(new Base64().encode(new byte[] { (byte) 97 })));
assertEquals("Yg==", new String(new Base64().encode(new byte[] { (byte) 98 })));
assertEquals("Yw==", new String(new Base64().encode(new byte[] { (byte) 99 })));
assertEquals("ZA==", new String(new Base64().encode(new byte[] { (byte) 100 })));
assertEquals("ZQ==", new String(new Base64().encode(new byte[] { (byte) 101 })));
assertEquals("Zg==", new String(new Base64().encode(new byte[] { (byte) 102 })));
assertEquals("Zw==", new String(new Base64().encode(new byte[] { (byte) 103 })));
assertEquals("aA==", new String(new Base64().encode(new byte[] { (byte) 104 })));
assertEquals("AA..", new String(new Base64(true).encode(new byte[] { (byte) 0 })));
assertEquals("AQ..", new String(new Base64(true).encode(new byte[] { (byte) 1 })));
assertEquals("Ag..", new String(new Base64(true).encode(new byte[] { (byte) 2 })));
assertEquals("Aw..", new String(new Base64(true).encode(new byte[] { (byte) 3 })));
assertEquals("BA..", new String(new Base64(true).encode(new byte[] { (byte) 4 })));
assertEquals("BQ..", new String(new Base64(true).encode(new byte[] { (byte) 5 })));
assertEquals("Bg..", new String(new Base64(true).encode(new byte[] { (byte) 6 })));
assertEquals("Bw..", new String(new Base64(true).encode(new byte[] { (byte) 7 })));
assertEquals("CA..", new String(new Base64(true).encode(new byte[] { (byte) 8 })));
assertEquals("CQ..", new String(new Base64(true).encode(new byte[] { (byte) 9 })));
assertEquals("Cg..", new String(new Base64(true).encode(new byte[] { (byte) 10 })));
assertEquals("Cw..", new String(new Base64(true).encode(new byte[] { (byte) 11 })));
assertEquals("DA..", new String(new Base64(true).encode(new byte[] { (byte) 12 })));
assertEquals("DQ..", new String(new Base64(true).encode(new byte[] { (byte) 13 })));
assertEquals("Dg..", new String(new Base64(true).encode(new byte[] { (byte) 14 })));
assertEquals("Dw..", new String(new Base64(true).encode(new byte[] { (byte) 15 })));
assertEquals("EA..", new String(new Base64(true).encode(new byte[] { (byte) 16 })));
assertEquals("EQ..", new String(new Base64(true).encode(new byte[] { (byte) 17 })));
assertEquals("Eg..", new String(new Base64(true).encode(new byte[] { (byte) 18 })));
assertEquals("Ew..", new String(new Base64(true).encode(new byte[] { (byte) 19 })));
assertEquals("FA..", new String(new Base64(true).encode(new byte[] { (byte) 20 })));
assertEquals("FQ..", new String(new Base64(true).encode(new byte[] { (byte) 21 })));
assertEquals("Fg..", new String(new Base64(true).encode(new byte[] { (byte) 22 })));
assertEquals("Fw..", new String(new Base64(true).encode(new byte[] { (byte) 23 })));
assertEquals("GA..", new String(new Base64(true).encode(new byte[] { (byte) 24 })));
assertEquals("GQ..", new String(new Base64(true).encode(new byte[] { (byte) 25 })));
assertEquals("Gg..", new String(new Base64(true).encode(new byte[] { (byte) 26 })));
assertEquals("Gw..", new String(new Base64(true).encode(new byte[] { (byte) 27 })));
assertEquals("HA..", new String(new Base64(true).encode(new byte[] { (byte) 28 })));
assertEquals("HQ..", new String(new Base64(true).encode(new byte[] { (byte) 29 })));
assertEquals("Hg..", new String(new Base64(true).encode(new byte[] { (byte) 30 })));
assertEquals("Hw..", new String(new Base64(true).encode(new byte[] { (byte) 31 })));
assertEquals("IA..", new String(new Base64(true).encode(new byte[] { (byte) 32 })));
assertEquals("IQ..", new String(new Base64(true).encode(new byte[] { (byte) 33 })));
assertEquals("Ig..", new String(new Base64(true).encode(new byte[] { (byte) 34 })));
assertEquals("Iw..", new String(new Base64(true).encode(new byte[] { (byte) 35 })));
assertEquals("JA..", new String(new Base64(true).encode(new byte[] { (byte) 36 })));
assertEquals("JQ..", new String(new Base64(true).encode(new byte[] { (byte) 37 })));
assertEquals("Jg..", new String(new Base64(true).encode(new byte[] { (byte) 38 })));
assertEquals("Jw..", new String(new Base64(true).encode(new byte[] { (byte) 39 })));
assertEquals("KA..", new String(new Base64(true).encode(new byte[] { (byte) 40 })));
assertEquals("KQ..", new String(new Base64(true).encode(new byte[] { (byte) 41 })));
assertEquals("Kg..", new String(new Base64(true).encode(new byte[] { (byte) 42 })));
assertEquals("Kw..", new String(new Base64(true).encode(new byte[] { (byte) 43 })));
assertEquals("LA..", new String(new Base64(true).encode(new byte[] { (byte) 44 })));
assertEquals("LQ..", new String(new Base64(true).encode(new byte[] { (byte) 45 })));
assertEquals("Lg..", new String(new Base64(true).encode(new byte[] { (byte) 46 })));
assertEquals("Lw..", new String(new Base64(true).encode(new byte[] { (byte) 47 })));
assertEquals("MA..", new String(new Base64(true).encode(new byte[] { (byte) 48 })));
assertEquals("MQ..", new String(new Base64(true).encode(new byte[] { (byte) 49 })));
assertEquals("Mg..", new String(new Base64(true).encode(new byte[] { (byte) 50 })));
assertEquals("Mw..", new String(new Base64(true).encode(new byte[] { (byte) 51 })));
assertEquals("NA..", new String(new Base64(true).encode(new byte[] { (byte) 52 })));
assertEquals("NQ..", new String(new Base64(true).encode(new byte[] { (byte) 53 })));
assertEquals("Ng..", new String(new Base64(true).encode(new byte[] { (byte) 54 })));
assertEquals("Nw..", new String(new Base64(true).encode(new byte[] { (byte) 55 })));
assertEquals("OA..", new String(new Base64(true).encode(new byte[] { (byte) 56 })));
assertEquals("OQ..", new String(new Base64(true).encode(new byte[] { (byte) 57 })));
assertEquals("Og..", new String(new Base64(true).encode(new byte[] { (byte) 58 })));
assertEquals("Ow..", new String(new Base64(true).encode(new byte[] { (byte) 59 })));
assertEquals("PA..", new String(new Base64(true).encode(new byte[] { (byte) 60 })));
assertEquals("PQ..", new String(new Base64(true).encode(new byte[] { (byte) 61 })));
assertEquals("Pg..", new String(new Base64(true).encode(new byte[] { (byte) 62 })));
assertEquals("Pw..", new String(new Base64(true).encode(new byte[] { (byte) 63 })));
assertEquals("QA..", new String(new Base64(true).encode(new byte[] { (byte) 64 })));
assertEquals("QQ..", new String(new Base64(true).encode(new byte[] { (byte) 65 })));
assertEquals("Qg..", new String(new Base64(true).encode(new byte[] { (byte) 66 })));
assertEquals("Qw..", new String(new Base64(true).encode(new byte[] { (byte) 67 })));
assertEquals("RA..", new String(new Base64(true).encode(new byte[] { (byte) 68 })));
assertEquals("RQ..", new String(new Base64(true).encode(new byte[] { (byte) 69 })));
assertEquals("Rg..", new String(new Base64(true).encode(new byte[] { (byte) 70 })));
assertEquals("Rw..", new String(new Base64(true).encode(new byte[] { (byte) 71 })));
assertEquals("SA..", new String(new Base64(true).encode(new byte[] { (byte) 72 })));
assertEquals("SQ..", new String(new Base64(true).encode(new byte[] { (byte) 73 })));
assertEquals("Sg..", new String(new Base64(true).encode(new byte[] { (byte) 74 })));
assertEquals("Sw..", new String(new Base64(true).encode(new byte[] { (byte) 75 })));
assertEquals("TA..", new String(new Base64(true).encode(new byte[] { (byte) 76 })));
assertEquals("TQ..", new String(new Base64(true).encode(new byte[] { (byte) 77 })));
assertEquals("Tg..", new String(new Base64(true).encode(new byte[] { (byte) 78 })));
assertEquals("Tw..", new String(new Base64(true).encode(new byte[] { (byte) 79 })));
assertEquals("UA..", new String(new Base64(true).encode(new byte[] { (byte) 80 })));
assertEquals("UQ..", new String(new Base64(true).encode(new byte[] { (byte) 81 })));
assertEquals("Ug..", new String(new Base64(true).encode(new byte[] { (byte) 82 })));
assertEquals("Uw..", new String(new Base64(true).encode(new byte[] { (byte) 83 })));
assertEquals("VA..", new String(new Base64(true).encode(new byte[] { (byte) 84 })));
assertEquals("VQ..", new String(new Base64(true).encode(new byte[] { (byte) 85 })));
assertEquals("Vg..", new String(new Base64(true).encode(new byte[] { (byte) 86 })));
assertEquals("Vw..", new String(new Base64(true).encode(new byte[] { (byte) 87 })));
assertEquals("WA..", new String(new Base64(true).encode(new byte[] { (byte) 88 })));
assertEquals("WQ..", new String(new Base64(true).encode(new byte[] { (byte) 89 })));
assertEquals("Wg..", new String(new Base64(true).encode(new byte[] { (byte) 90 })));
assertEquals("Ww..", new String(new Base64(true).encode(new byte[] { (byte) 91 })));
assertEquals("XA..", new String(new Base64(true).encode(new byte[] { (byte) 92 })));
assertEquals("XQ..", new String(new Base64(true).encode(new byte[] { (byte) 93 })));
assertEquals("Xg..", new String(new Base64(true).encode(new byte[] { (byte) 94 })));
assertEquals("Xw..", new String(new Base64(true).encode(new byte[] { (byte) 95 })));
assertEquals("YA..", new String(new Base64(true).encode(new byte[] { (byte) 96 })));
assertEquals("YQ..", new String(new Base64(true).encode(new byte[] { (byte) 97 })));
assertEquals("Yg..", new String(new Base64(true).encode(new byte[] { (byte) 98 })));
assertEquals("Yw..", new String(new Base64(true).encode(new byte[] { (byte) 99 })));
assertEquals("ZA..", new String(new Base64(true).encode(new byte[] { (byte) 100 })));
assertEquals("ZQ..", new String(new Base64(true).encode(new byte[] { (byte) 101 })));
assertEquals("Zg..", new String(new Base64(true).encode(new byte[] { (byte) 102 })));
assertEquals("Zw..", new String(new Base64(true).encode(new byte[] { (byte) 103 })));
assertEquals("aA..", new String(new Base64(true).encode(new byte[] { (byte) 104 })));
}
public void testTriplets() {
assertEquals("AAAA", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 0 })));
assertEquals("AAAB", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 1 })));
assertEquals("AAAC", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 2 })));
assertEquals("AAAD", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 3 })));
assertEquals("AAAE", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 4 })));
assertEquals("AAAF", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 5 })));
assertEquals("AAAG", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 6 })));
assertEquals("AAAH", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 7 })));
assertEquals("AAAI", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 8 })));
assertEquals("AAAJ", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 9 })));
assertEquals("AAAK", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 10 })));
assertEquals("AAAL", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 11 })));
assertEquals("AAAM", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 12 })));
assertEquals("AAAN", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 13 })));
assertEquals("AAAO", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 14 })));
assertEquals("AAAP", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 15 })));
assertEquals("AAAQ", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 16 })));
assertEquals("AAAR", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 17 })));
assertEquals("AAAS", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 18 })));
assertEquals("AAAT", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 19 })));
assertEquals("AAAU", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 20 })));
assertEquals("AAAV", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 21 })));
assertEquals("AAAW", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 22 })));
assertEquals("AAAX", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 23 })));
assertEquals("AAAY", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 24 })));
assertEquals("AAAZ", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 25 })));
assertEquals("AAAa", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 26 })));
assertEquals("AAAb", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 27 })));
assertEquals("AAAc", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 28 })));
assertEquals("AAAd", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 29 })));
assertEquals("AAAe", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 30 })));
assertEquals("AAAf", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 31 })));
assertEquals("AAAg", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 32 })));
assertEquals("AAAh", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 33 })));
assertEquals("AAAi", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 34 })));
assertEquals("AAAj", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 35 })));
assertEquals("AAAk", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 36 })));
assertEquals("AAAl", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 37 })));
assertEquals("AAAm", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 38 })));
assertEquals("AAAn", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 39 })));
assertEquals("AAAo", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 40 })));
assertEquals("AAAp", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 41 })));
assertEquals("AAAq", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 42 })));
assertEquals("AAAr", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 43 })));
assertEquals("AAAs", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 44 })));
assertEquals("AAAt", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 45 })));
assertEquals("AAAu", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 46 })));
assertEquals("AAAv", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 47 })));
assertEquals("AAAw", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 48 })));
assertEquals("AAAx", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 49 })));
assertEquals("AAAy", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 50 })));
assertEquals("AAAz", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 51 })));
assertEquals("AAA0", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 52 })));
assertEquals("AAA1", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 53 })));
assertEquals("AAA2", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 54 })));
assertEquals("AAA3", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 55 })));
assertEquals("AAA4", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 56 })));
assertEquals("AAA5", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 57 })));
assertEquals("AAA6", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 58 })));
assertEquals("AAA7", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 59 })));
assertEquals("AAA8", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 60 })));
assertEquals("AAA9", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 61 })));
assertEquals("AAA+", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 62 })));
assertEquals("AAA/", new String(new Base64().encode(new byte[] { (byte) 0, (byte) 0, (byte) 63 })));
assertEquals("AAAA", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 0 })));
assertEquals("AAAB", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 1 })));
assertEquals("AAAC", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 2 })));
assertEquals("AAAD", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 3 })));
assertEquals("AAAE", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 4 })));
assertEquals("AAAF", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 5 })));
assertEquals("AAAG", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 6 })));
assertEquals("AAAH", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 7 })));
assertEquals("AAAI", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 8 })));
assertEquals("AAAJ", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 9 })));
assertEquals("AAAK", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 10 })));
assertEquals("AAAL", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 11 })));
assertEquals("AAAM", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 12 })));
assertEquals("AAAN", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 13 })));
assertEquals("AAAO", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 14 })));
assertEquals("AAAP", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 15 })));
assertEquals("AAAQ", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 16 })));
assertEquals("AAAR", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 17 })));
assertEquals("AAAS", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 18 })));
assertEquals("AAAT", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 19 })));
assertEquals("AAAU", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 20 })));
assertEquals("AAAV", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 21 })));
assertEquals("AAAW", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 22 })));
assertEquals("AAAX", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 23 })));
assertEquals("AAAY", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 24 })));
assertEquals("AAAZ", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 25 })));
assertEquals("AAAa", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 26 })));
assertEquals("AAAb", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 27 })));
assertEquals("AAAc", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 28 })));
assertEquals("AAAd", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 29 })));
assertEquals("AAAe", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 30 })));
assertEquals("AAAf", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 31 })));
assertEquals("AAAg", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 32 })));
assertEquals("AAAh", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 33 })));
assertEquals("AAAi", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 34 })));
assertEquals("AAAj", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 35 })));
assertEquals("AAAk", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 36 })));
assertEquals("AAAl", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 37 })));
assertEquals("AAAm", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 38 })));
assertEquals("AAAn", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 39 })));
assertEquals("AAAo", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 40 })));
assertEquals("AAAp", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 41 })));
assertEquals("AAAq", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 42 })));
assertEquals("AAAr", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 43 })));
assertEquals("AAAs", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 44 })));
assertEquals("AAAt", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 45 })));
assertEquals("AAAu", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 46 })));
assertEquals("AAAv", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 47 })));
assertEquals("AAAw", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 48 })));
assertEquals("AAAx", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 49 })));
assertEquals("AAAy", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 50 })));
assertEquals("AAAz", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 51 })));
assertEquals("AAA0", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 52 })));
assertEquals("AAA1", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 53 })));
assertEquals("AAA2", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 54 })));
assertEquals("AAA3", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 55 })));
assertEquals("AAA4", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 56 })));
assertEquals("AAA5", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 57 })));
assertEquals("AAA6", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 58 })));
assertEquals("AAA7", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 59 })));
assertEquals("AAA8", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 60 })));
assertEquals("AAA9", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 61 })));
assertEquals("AAA-", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 62 })));
assertEquals("AAA_", new String(new Base64(true).encode(new byte[] { (byte) 0, (byte) 0, (byte) 63 })));
}
public void testKnownEncodings() {
assertEquals("VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg==", new Base64()
.encodeToString("The quick brown fox jumped over the lazy dogs.".getBytes()));
assertEquals("SXQgd2FzIHRoZSBiZXN0IG9mIHRpbWVzLCBpdCB3YXMgdGhlIHdvcnN0IG9mIHRpbWVzLg==", new Base64()
.encodeToString("It was the best of times, it was the worst of times.".getBytes()));
assertEquals("aHR0cDovL2pha2FydGEuYXBhY2hlLm9yZy9jb21tbW9ucw==", new Base64()
.encodeToString("http://jakarta.apache.org/commmons".getBytes()));
assertEquals("QWFCYkNjRGRFZUZmR2dIaElpSmpLa0xsTW1Obk9vUHBRcVJyU3NUdFV1VnZXd1h4WXlaeg==", new Base64()
.encodeToString("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".getBytes()));
assertEquals("eyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5IH0=", new Base64()
.encodeToString("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }".getBytes()));
assertEquals("eHl6enkh", new String(new Base64().encode("xyzzy!".getBytes())));
assertEquals("VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg..", new Base64(true)
.encodeToString("The quick brown fox jumped over the lazy dogs.".getBytes()));
assertEquals("SXQgd2FzIHRoZSBiZXN0IG9mIHRpbWVzLCBpdCB3YXMgdGhlIHdvcnN0IG9mIHRpbWVzLg..", new Base64(true)
.encodeToString("It was the best of times, it was the worst of times.".getBytes()));
assertEquals("aHR0cDovL2pha2FydGEuYXBhY2hlLm9yZy9jb21tbW9ucw..", new Base64(true)
.encodeToString("http://jakarta.apache.org/commmons".getBytes()));
assertEquals("QWFCYkNjRGRFZUZmR2dIaElpSmpLa0xsTW1Obk9vUHBRcVJyU3NUdFV1VnZXd1h4WXlaeg..", new Base64(true)
.encodeToString("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".getBytes()));
assertEquals("eyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5IH0.", new Base64(true)
.encodeToString("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }".getBytes()));
assertEquals("eHl6enkh", new String(new Base64(true).encode("xyzzy!".getBytes())));
}
public void testKnownDecodings() {
assertEquals("The quick brown fox jumped over the lazy dogs.", new String(new Base64()
.decodeFromString("VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg==")));
assertEquals("It was the best of times, it was the worst of times.", new String(new Base64()
.decodeFromString("SXQgd2FzIHRoZSBiZXN0IG9mIHRpbWVzLCBpdCB3YXMgdGhlIHdvcnN0IG9mIHRpbWVzLg==")));
assertEquals("http://jakarta.apache.org/commmons", new String(new Base64()
.decodeFromString("aHR0cDovL2pha2FydGEuYXBhY2hlLm9yZy9jb21tbW9ucw==")));
assertEquals("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz", new String(new Base64()
.decodeFromString("QWFCYkNjRGRFZUZmR2dIaElpSmpLa0xsTW1Obk9vUHBRcVJyU3NUdFV1VnZXd1h4WXlaeg==")));
assertEquals("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }", new String(new Base64()
.decodeFromString("eyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5IH0=")));
assertEquals("xyzzy!", new String(new Base64().decodeFromString("eHl6enkh")));
assertEquals("The quick brown fox jumped over the lazy dogs.", new String(new Base64(true)
.decodeFromString("VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg..")));
assertEquals("It was the best of times, it was the worst of times.", new String(new Base64(true)
.decodeFromString("SXQgd2FzIHRoZSBiZXN0IG9mIHRpbWVzLCBpdCB3YXMgdGhlIHdvcnN0IG9mIHRpbWVzLg..")));
assertEquals("http://jakarta.apache.org/commmons", new String(new Base64(true)
.decodeFromString("aHR0cDovL2pha2FydGEuYXBhY2hlLm9yZy9jb21tbW9ucw..")));
assertEquals("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz", new String(new Base64(true)
.decodeFromString("QWFCYkNjRGRFZUZmR2dIaElpSmpLa0xsTW1Obk9vUHBRcVJyU3NUdFV1VnZXd1h4WXlaeg..")));
assertEquals("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }", new String(new Base64(true)
.decodeFromString("eyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5IH0.")));
assertEquals("xyzzy!", new String(new Base64(true).decodeFromString("eHl6enkh")));
}
public void testNonBase64Test() throws Exception {
byte[] bArray = { '%' };
try {
byte[] result = new Base64().decode(bArray);
assertTrue("The result should be empty as the test encoded content did "
+ "not contain any valid base 64 characters", result.length == 0);
} catch (Exception e) {
fail("Exception was thrown when trying to decode "
+ "invalid base64 encoded data - RFC 2045 requires that all "
+ "non base64 character be discarded, an exception should not" + " have been thrown");
}
}
public void testIgnoringNonBase64InDecode() throws Exception {
assertEquals(
"The quick brown fox jumped over the lazy dogs.",
new String(
new Base64()
.decodeFromString("VGhlIH@$#$@%F1aWN@#@#@@rIGJyb3duIGZve\n\r\t%#%#%#%CBqd##$#$W1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg==")));
assertEquals(
"The quick brown fox jumped over the lazy dogs.",
new String(
new Base64(true)
.decodeFromString("VGhlIH@$#$@%F1aWN@#@#@@rIGJyb3duIGZve\n\r\t%#%#%#%CBqd##$#$W1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg..")));
}
public void testDecodeWithWhitespace() throws Exception {
String orig = "I am a late night coder.";
byte[] encodedArray = new Base64().encode(orig.getBytes());
StringBuffer intermediate = new StringBuffer(new String(encodedArray));
intermediate.insert(2, ' ');
intermediate.insert(5, '\t');
intermediate.insert(10, '\r');
intermediate.insert(15, '\n');
byte[] encodedWithWhitespace = intermediate.toString().getBytes();
byte[] decodedWithWhitespace = new Base64().decode(encodedWithWhitespace);
String dest = new String(decodedWithWhitespace);
assertEquals(orig, dest);
}
public void testEncodePaddingChar() {
assertEquals("=", new String(new Base64().decode(new Base64().encode("=".getBytes()))));
assertEquals(".", new String(new Base64().decode(new Base64().encode(".".getBytes()))));
assertEquals("=", new String(new Base64(true).decode(new Base64(true).encode("=".getBytes()))));
assertEquals(".", new String(new Base64(true).decode(new Base64(true).encode(".".getBytes()))));
}
public void testUrlSafety() throws Exception {
byte[] bytes = new byte[256];
for (int i = 0; i < 256; i++) {
bytes[i] = (byte) i;
}
byte[] encoded = new Base64(true).encode(bytes);
String encodedString = new String(encoded, "UTF-8");
String urlEncoded = URLEncoder.encode(encodedString, "UTF-8");
assertEquals(encodedString, urlEncoded);
String urlDecoded = URLDecoder.decode(urlEncoded, "UTF-8");
assertEquals(encodedString, urlDecoded);
byte[] decoded = new Base64(true).decode(urlDecoded.getBytes("UTF-8"));
assertEquals(bytes.length, decoded.length);
for (int i = 0; i < 256; i++) {
assertEquals(bytes[i], decoded[i]);
}
}
}