Author: cbrisson
Date: Thu Apr 18 13:46:25 2019
New Revision: 1857748
URL: http://svn.apache.org/viewvc?rev=1857748&view=rev
Log:
[tools/model] Initial import: utility classes, and shading of commons-codec
Base64
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/AESCryptograph.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/ChainedMap.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/Cryptograph.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/GlobToRegex.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/HashMultiMap.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/LogOutputStream.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/MultiMap.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotHashMap.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotMap.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotTreeMap.java
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/TypeUtils.java
Modified:
velocity/tools/branches/model/velocity-tools-model/pom.xml
Modified: velocity/tools/branches/model/velocity-tools-model/pom.xml
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/pom.xml?rev=1857748&r1=1857747&r2=1857748&view=diff
==============================================================================
--- velocity/tools/branches/model/velocity-tools-model/pom.xml (original)
+++ velocity/tools/branches/model/velocity-tools-model/pom.xml Thu Apr 18
13:46:25 2019
@@ -40,6 +40,48 @@
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>3.2.1</version>
+ <executions>
+ <execution>
+ <id>shade</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <artifactSet>
+ <includes>
+
<include>commons-codec:commons-codec</include>
+ </includes>
+ </artifactSet>
+ <filters>
+ <filter>
+
<artifact>commons-codec:commons-codec</artifact>
+ <includes>
+
<include>org/apache/commons/codec/Encoder.class</include>
+
<include>org/apache/commons/codec/Decoder.class</include>
+
<include>org/apache/commons/codec/BinaryEncoder.class</include>
+
<include>org/apache/commons/codec/BinaryDecoder.class</include>
+
<include>org/apache/commons/codec/binary/BaseNCodec.class</include>
+
<include>org/apache/commons/codec/binary/Base64.class</include>
+ </includes>
+ </filter>
+ </filters>
+ <relocations>
+ <relocation>
+ <pattern>org.apache.commons.codec</pattern>
+
<shadedPattern>org.apache.velocity.tools.model.util.shaded.commons.codec</shadedPattern>
+ </relocation>
+ </relocations>
+
<keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
+ <minimizeJar>true</minimizeJar>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
@@ -64,6 +106,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.12</version>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/AESCryptograph.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/AESCryptograph.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/AESCryptograph.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/AESCryptograph.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,97 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.velocity.tools.config.ConfigurationException;
+
+/**
+ * TODO - document secure random requirement
+ */
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.Charset;
+
+import static javax.crypto.Cipher.DECRYPT_MODE;
+import static javax.crypto.Cipher.ENCRYPT_MODE;
+
+/**
+ * Basic AES encryption. Please note that it uses the ECB block mode, which
has the advantage
+ * to not require random bytes, thus providing some *persistence* for the
encrypted data, but
+ * at the expense of some security weaknesses. The purpose here is just to
discourage editing
+ * id values in URLs, not to protect state secrets.
+ */
+
+public class AESCryptograph implements Cryptograph
+{
+ @Override
+ public void init(String key)
+ {
+ byte[] bytes = key.getBytes(Charset.defaultCharset());
+ if (bytes.length < 16)
+ {
+ throw new ConfigurationException("not enough secret bytes");
+ }
+ SecretKey secret = new SecretKeySpec(bytes, 0, 16, ALGORITHM);
+ try
+ {
+ encrypt = Cipher.getInstance(CIPHER);
+ encrypt.init(ENCRYPT_MODE, secret);
+ decrypt = Cipher.getInstance(CIPHER);
+ decrypt.init(DECRYPT_MODE, secret);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("cyptograph initialization failed", e);
+ }
+ }
+
+ @Override
+ public byte[] encrypt(String str)
+ {
+ try
+ {
+ return encrypt.doFinal(str.getBytes(Charset.defaultCharset()));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("encryption failed failed", e);
+ }
+ }
+
+ @Override
+ public String decrypt(byte[] bytes)
+ {
+ try
+ {
+ return new String(decrypt.doFinal(bytes),
Charset.defaultCharset());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("encryption failed failed", e);
+ }
+ }
+
+ private final String CIPHER = "AES/ECB/PKCS5Padding";
+ private final String ALGORITHM = "AES";
+ private Cipher encrypt, decrypt;
+
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/ChainedMap.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/ChainedMap.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/ChainedMap.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/ChainedMap.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,135 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+public class ChainedMap implements Map
+{
+ protected static Logger logger = LoggerFactory.getLogger(ChainedMap.class);
+
+ private Map source;
+ private Map parameters;
+
+ public ChainedMap(Map source, Map parameters)
+ {
+ this.source = source;
+ this.parameters = parameters;
+ }
+
+ public Map getSource()
+ {
+ return source;
+ }
+
+ public Map getParameters()
+ {
+ return parameters;
+ }
+
+ public void clear()
+ {
+ logger.error("trying to modify a read-only ChainedMap");
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return source.containsKey(key) || parameters.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return source.containsValue(value) || parameters.containsValue(value);
+ }
+
+ public Set<Map.Entry> entrySet()
+ {
+ Set<Map.Entry> ret = source.entrySet();
+ ret.addAll(parameters.entrySet());
+ return ret;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o == null || !(o instanceof ChainedMap)) return false;
+ ChainedMap other = (ChainedMap)o;
+ return source.equals(other.getSource()) &&
parameters.equals(other.getParameters());
+ }
+
+ public Object get(Object key)
+ {
+ Object ret = parameters.get(key);
+ return ret == null ? source.get(key) : ret;
+ }
+
+ public int hashCode()
+ {
+ return source.hashCode() ^ parameters.hashCode();
+ }
+
+ public boolean isEmpty()
+ {
+ return source.isEmpty() && parameters.isEmpty();
+ }
+
+ public Set keySet()
+ {
+ Set ret = source.keySet();
+ ret.addAll(parameters.keySet());
+ return ret;
+ }
+
+ public Object put(Object key, Object value)
+ {
+ logger.error("trying to modify a read-only ChainedMap");
+ return null;
+ }
+
+ public void putAll(Map m)
+ {
+ logger.error("trying to modify a read-only ChainedMap");
+ }
+
+ public Serializable remove(Object key)
+ {
+ logger.error("trying to modify a read-only ChainedMap");
+ return null;
+ }
+
+ public int size()
+ {
+ return source.size() + parameters.size();
+ }
+
+ public Collection values()
+ {
+ ArrayList ret = new ArrayList();
+ ret.addAll(source.values());
+ ret.addAll(parameters.values());
+ return ret;
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/Cryptograph.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/Cryptograph.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/Cryptograph.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/Cryptograph.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,51 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ * Cryptograph - used to encrypt and decrypt strings.
+ *
+ * @author <a href=mailto:[email protected]>Claude Brisson</a>
+ */
+
+public interface Cryptograph extends Serializable
+{
+ /**
+ * init.
+ * @param random random string
+ */
+ void init(String random);
+
+ /**
+ * encrypt.
+ * @param str string to encrypt
+ * @return encrypted string
+ */
+ byte[] encrypt(String str);
+
+ /**
+ * decrypt.
+ * @param bytes to decrypt
+ * @return decrypted string
+ */
+ String decrypt(byte[] bytes);
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/GlobToRegex.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/GlobToRegex.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/GlobToRegex.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/GlobToRegex.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,558 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * 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.
+ */
+
+import org.apache.velocity.tools.config.ConfigurationException;
+
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * Translates globs to regex patterns.
+ * Borrowed from com.google.common.jimfs.
+ *
+ * @author Colin Decker
+ */
+
+public final class GlobToRegex
+{
+
+ /**
+ * Converts the given glob to a regular expression pattern. The given
separators determine what
+ * characters the resulting expression breaks on for glob expressions such
as * which should not
+ * cross directory boundaries.
+ * <p>
+ * <p>Basic conversions (assuming / as only separator):
+ * <p>
+ * <pre>{@code
+ * ? = [^/]
+ * * = [^/]*
+ * ** = .*
+ * [a-z] = [[^/]&&[a-z]]
+ * [!a-z] = [[^/]&&[^a-z]]
+ * {a,b,c} = (a|b|c)
+ * }</pre>
+ */
+ public static String toRegex(String glob, String separators)
+ {
+ return new GlobToRegex(glob, separators).convert();
+ }
+
+ /**
+ * Char matcher
+ *
+ * @author Colin Decker
+ */
+ final static class InternalCharMatcher
+ {
+
+ private final char[] chars;
+
+ public InternalCharMatcher(String chars)
+ {
+ this.chars = chars.toCharArray();
+ Arrays.sort(this.chars);
+ }
+
+ public boolean matches(char c)
+ {
+ return Arrays.binarySearch(chars, c) >= 0;
+ }
+ }
+
+ public static InternalCharMatcher anyOf(String chars)
+ {
+ return new InternalCharMatcher(chars);
+ }
+
+ private static final InternalCharMatcher REGEX_RESERVED =
anyOf("^$.?+*\\[]{}()");
+
+ private final String glob;
+ private final String separators;
+ private final InternalCharMatcher separatorMatcher;
+
+ private final StringBuilder builder = new StringBuilder();
+ private final Deque<State> states = new ArrayDeque<>();
+ private int index;
+
+ private GlobToRegex(String glob, String separators)
+ {
+ if (glob == null)
+ {
+ throw new ConfigurationException("null glob pattern");
+ }
+ this.glob = glob;
+ this.separators = separators;
+ this.separatorMatcher = anyOf(separators);
+ }
+
+ /**
+ * Converts the glob to a regex one character at a time. A state stack
(states) is maintained,
+ * with the state at the top of the stack being the current state at any
given time. The current
+ * state is always used to process the next character. When a state
processes a character, it may
+ * pop the current state or push a new state as the current state. The
resulting regex is written
+ * to {@code builder}.
+ */
+ private String convert()
+ {
+ pushState(NORMAL);
+ for (index = 0; index < glob.length(); index++)
+ {
+ currentState().process(this, glob.charAt(index));
+ }
+ currentState().finish(this);
+ return builder.toString();
+ }
+
+ /**
+ * Enters the given state. The current state becomes the previous state.
+ */
+ private void pushState(State state)
+ {
+ states.push(state);
+ }
+
+ /**
+ * Returns to the previous state.
+ */
+ private void popState()
+ {
+ states.pop();
+ }
+
+ /**
+ * Returns the current state.
+ */
+ private State currentState()
+ {
+ return states.peek();
+ }
+
+ /**
+ * Throws a {@link PatternSyntaxException}.
+ */
+ private PatternSyntaxException syntaxError(String desc)
+ {
+ throw new PatternSyntaxException(desc, glob, index);
+ }
+
+ /**
+ * Appends the given character as-is to the regex.
+ */
+ private void appendExact(char c)
+ {
+ builder.append(c);
+ }
+
+ /**
+ * Appends the regex form of the given normal character or separator from
the glob.
+ */
+ private void append(char c)
+ {
+ if (separatorMatcher.matches(c))
+ {
+ appendSeparator();
+ }
+ else
+ {
+ appendNormal(c);
+ }
+ }
+
+ /**
+ * Appends the regex form of the given normal character from the glob.
+ */
+ private void appendNormal(char c)
+ {
+ if (REGEX_RESERVED.matches(c))
+ {
+ builder.append('\\');
+ }
+ builder.append(c);
+ }
+
+ /**
+ * Appends the regex form matching the separators for the path type.
+ */
+ private void appendSeparator()
+ {
+ if (separators.length() == 1)
+ {
+ appendNormal(separators.charAt(0));
+ }
+ else
+ {
+ builder.append('[');
+ for (int i = 0; i < separators.length(); i++)
+ {
+ appendInBracket(separators.charAt(i));
+ }
+ builder.append("]");
+ }
+ }
+
+ /**
+ * Appends the regex form that matches anything except the separators for
the path type.
+ */
+ private void appendNonSeparator()
+ {
+ builder.append("[^");
+ for (int i = 0; i < separators.length(); i++)
+ {
+ appendInBracket(separators.charAt(i));
+ }
+ builder.append(']');
+ }
+
+ /**
+ * Appends the regex form of the glob ? character.
+ */
+ private void appendQuestionMark()
+ {
+ appendNonSeparator();
+ }
+
+ /**
+ * Appends the regex form of the glob * character.
+ */
+ private void appendStar()
+ {
+ appendNonSeparator();
+ builder.append('*');
+ }
+
+ /**
+ * Appends the regex form of the glob ** pattern.
+ */
+ private void appendStarStar()
+ {
+ builder.append(".*");
+ }
+
+ /**
+ * Appends the regex form of the start of a glob [] section.
+ */
+ private void appendBracketStart()
+ {
+ builder.append('[');
+ appendNonSeparator();
+ builder.append("&&[");
+ }
+
+ /**
+ * Appends the regex form of the end of a glob [] section.
+ */
+ private void appendBracketEnd()
+ {
+ builder.append("]]");
+ }
+
+ /**
+ * Appends the regex form of the given character within a glob [] section.
+ */
+ private void appendInBracket(char c)
+ {
+ // escape \ in regex character class
+ if (c == '\\')
+ {
+ builder.append('\\');
+ }
+
+ builder.append(c);
+ }
+
+ /**
+ * Appends the regex form of the start of a glob {} section.
+ */
+ private void appendCurlyBraceStart()
+ {
+ builder.append('(');
+ }
+
+ /**
+ * Appends the regex form of the separator (,) within a glob {} section.
+ */
+ private void appendSubpatternSeparator()
+ {
+ builder.append('|');
+ }
+
+ /**
+ * Appends the regex form of the end of a glob {} section.
+ */
+ private void appendCurlyBraceEnd()
+ {
+ builder.append(')');
+ }
+
+ /**
+ * Converter state.
+ */
+ private abstract static class State
+ {
+ /**
+ * Process the next character with the current state, transitioning
the converter to a new
+ * state if necessary.
+ */
+ abstract void process(GlobToRegex converter, char c);
+
+ /**
+ * Called after all characters have been read.
+ */
+ void finish(GlobToRegex converter)
+ {
+ }
+ }
+
+ /**
+ * Normal state.
+ */
+ private static final State NORMAL =
+ new State()
+ {
+ @Override
+ void process(GlobToRegex converter, char c)
+ {
+ switch (c)
+ {
+ case '?':
+ converter.appendQuestionMark();
+ return;
+ case '[':
+ converter.appendBracketStart();
+ converter.pushState(BRACKET_FIRST_CHAR);
+ return;
+ case '{':
+ converter.appendCurlyBraceStart();
+ converter.pushState(CURLY_BRACE);
+ return;
+ case '*':
+ converter.pushState(STAR);
+ return;
+ case '\\':
+ converter.pushState(ESCAPE);
+ return;
+ default:
+ converter.append(c);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "NORMAL";
+ }
+ };
+
+ /**
+ * State following the reading of a single \.
+ */
+ private static final State ESCAPE =
+ new State()
+ {
+ @Override
+ void process(GlobToRegex converter, char c)
+ {
+ converter.append(c);
+ converter.popState();
+ }
+
+ @Override
+ void finish(GlobToRegex converter)
+ {
+ throw converter.syntaxError("Hanging escape (\\) at end of
pattern");
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ESCAPE";
+ }
+ };
+
+ /**
+ * State following the reading of a single *.
+ */
+ private static final State STAR =
+ new State()
+ {
+ @Override
+ void process(GlobToRegex converter, char c)
+ {
+ if (c == '*')
+ {
+ converter.appendStarStar();
+ converter.popState();
+ }
+ else
+ {
+ converter.appendStar();
+ converter.popState();
+ converter.currentState().process(converter, c);
+ }
+ }
+
+ @Override
+ void finish(GlobToRegex converter)
+ {
+ converter.appendStar();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "STAR";
+ }
+ };
+
+ /**
+ * State immediately following the reading of a [.
+ */
+ private static final State BRACKET_FIRST_CHAR =
+ new State()
+ {
+ @Override
+ void process(GlobToRegex converter, char c)
+ {
+ if (c == ']')
+ {
+ // A glob like "[]]" or "[]q]" is apparently fine in Unix
(when used with ls for example)
+ // but doesn't work for the default java.nio.file
implementations. In the cases of "[]]" it
+ // produces:
+ // java.util.regex.PatternSyntaxException: Unclosed
character class near index 13
+ // ^[[^/]&&[]]\]$
+ // ^
+ // The error here is slightly different, but trying to
make this work would require some
+ // kind of lookahead and break the simplicity of
char-by-char conversion here. Also, if
+ // someone wants to include a ']' inside a character
class, they should escape it.
+ throw converter.syntaxError("Empty []");
+ }
+ if (c == '!')
+ {
+ converter.appendExact('^');
+ }
+ else if (c == '-')
+ {
+ converter.appendExact(c);
+ }
+ else
+ {
+ converter.appendInBracket(c);
+ }
+ converter.popState();
+ converter.pushState(BRACKET);
+ }
+
+ @Override
+ void finish(GlobToRegex converter)
+ {
+ throw converter.syntaxError("Unclosed [");
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BRACKET_FIRST_CHAR";
+ }
+ };
+
+ /**
+ * State inside [brackets], but not at the first character inside the
brackets.
+ */
+ private static final State BRACKET =
+ new State()
+ {
+ @Override
+ void process(GlobToRegex converter, char c)
+ {
+ if (c == ']')
+ {
+ converter.appendBracketEnd();
+ converter.popState();
+ }
+ else
+ {
+ converter.appendInBracket(c);
+ }
+ }
+
+ @Override
+ void finish(GlobToRegex converter)
+ {
+ throw converter.syntaxError("Unclosed [");
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BRACKET";
+ }
+ };
+
+ /**
+ * State inside {curly braces}.
+ */
+ private static final State CURLY_BRACE =
+ new State()
+ {
+ @Override
+ void process(GlobToRegex converter, char c)
+ {
+ switch (c)
+ {
+ case '?':
+ converter.appendQuestionMark();
+ break;
+ case '[':
+ converter.appendBracketStart();
+ converter.pushState(BRACKET_FIRST_CHAR);
+ break;
+ case '{':
+ throw converter.syntaxError("{ not allowed in
subpattern group");
+ case '*':
+ converter.pushState(STAR);
+ break;
+ case '\\':
+ converter.pushState(ESCAPE);
+ break;
+ case '}':
+ converter.appendCurlyBraceEnd();
+ converter.popState();
+ break;
+ case ',':
+ converter.appendSubpatternSeparator();
+ break;
+ default:
+ converter.append(c);
+ }
+ }
+
+ @Override
+ void finish(GlobToRegex converter)
+ {
+ throw converter.syntaxError("Unclosed {");
+ }
+
+ @Override
+ public String toString()
+ {
+ return "CURLY_BRACE";
+ }
+ };
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/HashMultiMap.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/HashMultiMap.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/HashMultiMap.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/HashMultiMap.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,270 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A MultiMap is a Map allowing multiple occurrences of keys.
+ *
+ * @author Mark Richters
+ * @see java.util.Map
+ */
+public class HashMultiMap implements MultiMap, Serializable
+{
+ /**
+ * inner map.
+ */
+ private Map map; // (Object key -> List values)
+
+ /**
+ * total number of values.
+ */
+ private transient int sizeAll;
+
+ /**
+ * build a new HashMultiMap.
+ */
+ public HashMultiMap()
+ {
+ map = new HashMap();
+ }
+
+ // Query Operations
+
+ /**
+ * Returns the number of values in this multimap.
+ *
+ * @return totla number of values
+ */
+ public int size()
+ {
+ return sizeAll;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this multimap contains no mappings.
+ *
+ * @return empty status
+ */
+ public boolean isEmpty()
+ {
+ return sizeAll == 0;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this multimap contains a mapping for
+ * the specified key.
+ *
+ * @param key
+ */
+ public boolean containsKey(Object key)
+ {
+ return map.containsKey(key);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this multimap maps one or more keys to
+ * the specified value.
+ */
+ public boolean containsValue(Object value)
+ {
+ Iterator it = map.values().iterator();
+
+ while(it.hasNext())
+ {
+ List l = (List)it.next();
+
+ if(l.contains(value))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a list of values to which this multimap maps the specified
+ * key.
+ *
+ * @return the list of values to which this map maps the specified key, the
+ * list may be empty if the multimap contains no mapping for this key.
+ */
+ public List get(Object key)
+ {
+ List l = (List)map.get(key);
+
+ if(l == null)
+ {
+ l = new ArrayList();
+ }
+ return l;
+ }
+
+ // Modification Operations
+
+ /**
+ * Adds the specified value with the specified key to this multimap.
+ * @param key
+ * @param value
+ */
+ public void put(Object key, Object value)
+ {
+ List l = (List)map.get(key);
+
+ if(l == null)
+ {
+ l = new ArrayList();
+ map.put(key, l);
+ }
+ l.add(value);
+ sizeAll++;
+ }
+
+ /**
+ * Copies all entries from the specified multimap to this
+ * multimap.
+ * @param t source multimap
+ */
+ public void putAll(MultiMap t)
+ {
+ Iterator it = t.keySet().iterator();
+
+ while(it.hasNext())
+ {
+ Object key = it.next();
+ List tl = t.get(key);
+ List l = (List)map.get(key);
+
+ if(l == null)
+ {
+ l = new ArrayList();
+ map.put(key, l);
+ }
+ l.addAll(tl);
+ sizeAll += tl.size();
+ }
+ }
+
+ /**
+ * Removes all mappings for this key from this multimap if present.
+ * @param key
+ */
+ public void remove(Object key)
+ {
+ List l = (List)map.get(key);
+
+ if(l != null)
+ {
+ sizeAll -= l.size();
+ }
+ map.remove(key);
+ }
+
+ /**
+ * Removes the specified key/value mapping from this multimap if present.
+ * @param key
+ * @param value
+ */
+ public void remove(Object key, Object value)
+ {
+ List l = (List)map.get(key);
+
+ if(l != null)
+ {
+ if(l.remove(value))
+ {
+ sizeAll--;
+ }
+ }
+ }
+
+ // Bulk Operations
+
+ /**
+ * Removes all mappings from this map (optional operation).
+ */
+ public void clear()
+ {
+ map.clear();
+ sizeAll = 0;
+ }
+
+ // Views
+
+ /**
+ * Returns a set view of the keys contained in this multimap.
+ */
+ public Set keySet()
+ {
+ return map.keySet();
+ }
+
+ // Comparison and hashing
+
+ /**
+ * Compares the specified object with this multimap for equality.
+ * @param o
+ */
+ public boolean equals(Object o)
+ {
+ if(o == this)
+ {
+ return true;
+ }
+
+ // FIXME: use MultiMap interface only
+ if(!(o instanceof HashMultiMap))
+ {
+ return false;
+ }
+
+ HashMultiMap c = (HashMultiMap)o;
+
+ if(c.size() != size())
+ {
+ return false;
+ }
+ return map.equals(c.map);
+ }
+
+ /**
+ * Returns the hash code value for this multimap.
+ */
+ public int hashCode()
+ {
+ int h = 0;
+ Iterator it = map.entrySet().iterator();
+
+ while(it.hasNext())
+ {
+ Object obj = it.next();
+
+ h += obj.hashCode();
+ }
+ return h;
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/LogOutputStream.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/LogOutputStream.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/LogOutputStream.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/LogOutputStream.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,101 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.slf4j.Logger;
+import org.slf4j.spi.LocationAwareLogger;
+
+import java.io.OutputStream;
+import java.util.function.Consumer;
+
+public class LogOutputStream extends OutputStream
+{
+ private Logger logger;
+
+ private StringBuffer buffer;
+
+ /** slf4j levels */
+ public static final int TRACE = LocationAwareLogger.TRACE_INT;
+ public static final int DEBUG = LocationAwareLogger.DEBUG_INT;
+ public static final int INFO = LocationAwareLogger.INFO_INT;
+ public static final int WARN = LocationAwareLogger.WARN_INT;
+ public static final int ERROR = LocationAwareLogger.ERROR_INT;
+
+ public LogOutputStream(Logger logger, int level)
+ {
+ this.logger = logger;
+ switch (level)
+ {
+ case TRACE: log = this::trace; break;
+ case DEBUG: log = this::debug; break;
+ case INFO : log = this::info; break;
+ case WARN: log = this::warn; break;
+ case ERROR: log = this::error; break;
+ }
+ }
+
+ private Consumer<String> log;
+
+ private final void trace(String log)
+ {
+ logger.trace(log);
+ }
+
+ private final void debug(String log)
+ {
+ logger.debug(log);
+ }
+
+ private final void info(String log)
+ {
+ logger.info(log);
+ }
+
+ private final void warn(String log)
+ {
+ logger.warn(log);
+ }
+
+ private final void error(String log)
+ {
+ logger.error(log);
+ }
+
+ @Override
+ public void write (int c)
+ {
+ char ch = (char)(c & 0xFF);
+ if (ch == '\n')
+ {
+ log.accept(buffer.toString());
+ buffer = new StringBuffer();
+ }
+ else
+ {
+ buffer.append(ch);
+ }
+ }
+
+ @Override
+ public void flush()
+ {
+ // I prefer just waiting for \n
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/MultiMap.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/MultiMap.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/MultiMap.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/MultiMap.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,134 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A MultiMap is a Map allowing multiple occurrences of keys.
+ *
+ * @author Mark Richters
+ * @see java.util.Map
+ */
+public interface MultiMap
+{
+ // Query Operations
+
+ /**
+ * Returns the number of values in this multimap.
+ */
+ int size();
+
+ /**
+ * Returns <tt>true</tt> if this multimap contains no mappings.
+ */
+ boolean isEmpty();
+
+ /**
+ * Returns <tt>true</tt> if this multimap contains a mapping for
+ * the specified key.
+ * @param key
+ * @return a boolean
+ */
+ boolean containsKey(Object key);
+
+ /**
+ * Returns <tt>true</tt> if this multimap maps one or more keys to
+ * the specified value.
+ * @param value
+ * @return a boolean
+ */
+ boolean containsValue(Object value);
+
+ /**
+ * Returns a list of values to which this multimap maps the specified
+ * key.
+ * @param key
+ * @return the list of values to which this map maps the specified
+ * key, the list may be empty if the multimap contains no
+ * mapping for this key.
+ */
+ List get(Object key);
+
+ // Modification Operations
+
+ /**
+ * Adds the specified value with the specified key to this multimap.
+ *
+ * @param key
+ * @param value
+ */
+ void put(Object key, Object value);
+
+ /**
+ * Copies all entries from the specified multimap to this
+ * multimap.
+ * @param t multimap
+ */
+ void putAll(MultiMap t);
+
+ /**
+ * Removes all mappings for this key from this multimap if present.
+ * @param key
+ */
+ void remove(Object key);
+
+ /**
+ * Removes the specified key/value mapping from this multimap if present.
+ * @param key
+ * @param value
+ */
+ void remove(Object key, Object value);
+
+ // Bulk Operations
+
+ /**
+ * Removes all mappings from this map (optional operation).
+ */
+ void clear();
+
+ // Views
+
+ /**
+ * Returns a set view of the keys contained in this multimap.
+ * @return key set
+ */
+ Set keySet();
+
+ /*
+ * Returns a collection view of the values contained in this map.
+ */
+
+ // Collection values();
+ // Comparison and hashing
+
+ /**
+ * Compares the specified object with this multimap for equality.
+ * @param o other object
+ * @return a boolean
+ */
+ boolean equals(Object o);
+
+ /**
+ * Returns the hash code value for this map.
+ */
+ int hashCode();
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotHashMap.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotHashMap.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotHashMap.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotHashMap.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,34 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SlotHashMap extends HashMap<String,Serializable> implements
SlotMap
+{
+ public SlotHashMap() {}
+
+ public SlotHashMap(Map<? extends String, ? extends Serializable> m)
+ {
+ super(m);
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotMap.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotMap.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotMap.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotMap.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,27 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Map;
+
+public interface SlotMap extends Map<String,Serializable>, Serializable
+{
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotTreeMap.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotTreeMap.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotTreeMap.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/SlotTreeMap.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,39 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class SlotTreeMap extends TreeMap<String,Serializable> implements
SlotMap
+{
+ public SlotTreeMap() {}
+
+ public SlotTreeMap(java.util.Comparator<java.lang.String> comparator)
+ {
+ super(comparator);
+ }
+
+ public SlotTreeMap(Map<? extends String, ? extends Serializable> m)
+ {
+ super(m);
+ }
+}
Added:
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/TypeUtils.java
URL:
http://svn.apache.org/viewvc/velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/TypeUtils.java?rev=1857748&view=auto
==============================================================================
---
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/TypeUtils.java
(added)
+++
velocity/tools/branches/model/velocity-tools-model/src/main/java/org/apache/velocity/tools/model/util/TypeUtils.java
Thu Apr 18 13:46:25 2019
@@ -0,0 +1,249 @@
+package org.apache.velocity.tools.model.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.commons.codec.binary.Base64;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+public class TypeUtils
+{
+ public static String toString(Object value)
+ {
+ return value == null ? null : value.toString();
+ }
+
+ public static Boolean toBoolean(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ if (value instanceof Boolean)
+ {
+ return (Boolean)value;
+ }
+ if (value instanceof String)
+ {
+ String str = (String)value;
+ if ("true".equals(str))
+ {
+ return true;
+ }
+ if ("false".equals(str))
+ {
+ return false;
+ }
+ try
+ {
+ value = Long.valueOf(str);
+ }
+ catch (NumberFormatException nfe)
+ {
+ return false;
+ }
+ }
+ if (value instanceof Number)
+ {
+ return ((Number)value).longValue() != 0l;
+ }
+ return false;
+ }
+
+ public static Short toShort(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number)value).shortValue();
+ }
+ if (value instanceof String)
+ {
+ try
+ {
+ return Short.valueOf((String)value);
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ return null;
+ }
+
+ public static Integer toInteger(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number)value).intValue();
+ }
+ if (value instanceof String)
+ {
+ try
+ {
+ return Integer.valueOf((String)value);
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ return null;
+ }
+
+ public static Long toLong(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number)value).longValue();
+ }
+ if (value instanceof String)
+ {
+ try
+ {
+ return Long.valueOf((String)value);
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ return null;
+ }
+
+ public static Float toFloat(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number)value).floatValue();
+ }
+ if (value instanceof String)
+ {
+ try
+ {
+ return Float.valueOf((String)value);
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ return null;
+ }
+
+ public static Double toDouble(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number)value).doubleValue();
+ }
+ if (value instanceof String)
+ {
+ try
+ {
+ return Double.valueOf((String)value);
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ return null;
+ }
+
+ public static Date toDate(Object value)
+ {
+ if (value == null || value instanceof Date)
+ {
+ return (Date)value;
+ }
+ if (value instanceof Calendar)
+ {
+ return ((Calendar)value).getTime();
+ }
+ return null;
+ }
+
+ public static Calendar toCalendar(Object value)
+ {
+ if (value == null || value instanceof Calendar)
+ {
+ return (Calendar)value;
+ }
+ if (value instanceof Date)
+ {
+ // CB TODO - use model locale
+ Calendar calendar = GregorianCalendar.getInstance();
+ calendar.setTime((Date)value);
+ return calendar;
+ }
+ return null;
+ }
+
+ public static byte[] toBytes(Object value)
+ {
+ if (value == null || value instanceof byte[])
+ {
+ return (byte[])value;
+ }
+ return String.valueOf(value).getBytes(StandardCharsets.UTF_8);
+ }
+
+ public static String base64Encode(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ byte[] decoded = toBytes(value);
+ byte[] encoded = Base64.encodeBase64URLSafe(decoded);
+ return new String(encoded, StandardCharsets.UTF_8);
+ }
+
+ public static byte[] base64Decode(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ String encoded = toString(value);
+ return Base64.decodeBase64(encoded);
+
+ }
+}