http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/pom.xml ---------------------------------------------------------------------- diff --git a/bval-jsr/pom.xml b/bval-jsr/pom.xml index f95f794..8913f7c 100644 --- a/bval-jsr/pom.xml +++ b/bval-jsr/pom.xml @@ -151,15 +151,6 @@ <dependencies> <dependency> - <groupId>org.apache.bval</groupId> - <artifactId>bval-core</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-lang3</artifactId> - </dependency> - <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils-core</artifactId> <optional>true</optional> @@ -176,6 +167,18 @@ <!-- don't pull into OSGi bundle --> <scope>provided</scope> <optional>true</optional> + <exclusions> + <exclusion> + <groupId>org.apache.bval</groupId> + <artifactId>bval-core</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <scope>provided</scope> + <optional>true</optional> </dependency> <dependency> <groupId>org.apache.geronimo.specs</groupId> @@ -270,11 +273,29 @@ </configuration> </plugin> + <!-- create mainClass attribute --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> + <id>default-jar</id> + <goals> + <goal>jar</goal> + </goals> + <configuration> + <archive> + <manifest> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + <mainClass>org.apache.bval.util.BValVersion</mainClass> + </manifest> + <manifestEntries> + <Implementation-Build>${buildNumber}</Implementation-Build> + </manifestEntries> + </archive> + </configuration> + </execution> + <execution> <id>test-jar</id> <phase>package</phase> <goals> @@ -298,6 +319,36 @@ <groupId>org.apache.commons</groupId> <artifactId>commons-weaver-maven-plugin</artifactId> </plugin> + <!-- + get the project version + and set it in a properties file for later retrieval + --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <id>set version info</id> + <phase>compile</phase> + <configuration> + <target> + <echo>Version: ${project.version}</echo> + <echo>Date: ${timestamp}</echo> + <mkdir dir="${project.build.outputDirectory}/META-INF" /> + <echo file="${project.build.outputDirectory}/META-INF/org.apache.bval.revision.properties"> +# Licensed under Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.0 +project.name=Apache BVal +project.version=${project.version} +build.timestamp=${timestamp} + </echo> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> </project>
http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java b/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java new file mode 100644 index 0000000..0835bae --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.bval.routines; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Description: holds the regexp to validate an email address<br> + * User: roman.stumm<br> + * Date: 17.06.2010<br> + * Time: 10:40:59<br> + */ +public class EMailValidationUtils { + private static String ATOM = "[^\\x00-\\x1F\\(\\)\\<\\>\\@\\,\\;\\:\\\\\\\"\\.\\[\\]\\s]"; + private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*"; + private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]"; + public static final Pattern DEFAULT_EMAIL_PATTERN; + + static { + DEFAULT_EMAIL_PATTERN = Pattern.compile("^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$", + Pattern.CASE_INSENSITIVE); + } + + /** + * Learn whether a given object is a valid email address. + * + * @param value + * to check + * @return <code>true</code> if the validation passes + */ + public static boolean isValid(Object value) { + return isValid(value, DEFAULT_EMAIL_PATTERN); + } + + /** + * Learn whether a particular value matches a given pattern per + * {@link Matcher#matches()}. + * + * @param value + * @param aPattern + * @return <code>true</code> if <code>value</code> was a <code>String</code> + * matching <code>aPattern</code> + */ + // TODO it would seem to make sense to move or reduce the visibility of this + // method as it is more general than email. + public static boolean isValid(Object value, Pattern aPattern) { + if (value == null) { + return true; + } + if (!(value instanceof CharSequence)) { + return false; + } + CharSequence seq = (CharSequence) value; + if (seq.length() == 0) { + return true; + } + return aPattern.matcher(seq).matches(); + } + +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java b/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java new file mode 100644 index 0000000..01b5c58 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java @@ -0,0 +1,195 @@ +/* + * 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. + */ +package org.apache.bval.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import java.util.StringTokenizer; + +import org.apache.bval.util.reflection.Reflection; +import org.apache.commons.weaver.privilizer.Privilizing; +import org.apache.commons.weaver.privilizer.Privilizing.CallTo; + +/** + * This class contains version information for BVal. + * It uses Ant's filter tokens to convert the template into a java + * file with current information. + */ +@Privilizing(@CallTo(Reflection.class)) +public class BValVersion { + + /** Project name */ + public static final String PROJECT_NAME = "Apache BVal"; + /** Unique id of the current project/version/revision */ + public static final String PROJECT_ID; + /** Version number */ + public static final String VERSION_NUMBER; + /** Major release number */ + public static final int MAJOR_RELEASE; + /** Minor release number */ + public static final int MINOR_RELEASE; + /** Patch/point release number */ + public static final int PATCH_RELEASE; + /** Release status */ + public static final String RELEASE_STATUS; + /** Version control revision number */ + public static final String REVISION_NUMBER; + + static { + Properties revisionProps = new Properties(); + try (InputStream in = BValVersion.class.getResourceAsStream("/META-INF/org.apache.bval.revision.properties")) { + if (in != null) { + revisionProps.load(in); + } + } catch (IOException ioe) { + } + + String vers = revisionProps.getProperty("project.version"); + if (StringUtils.isBlank(vers)) { + vers = "0.0.0"; + } + VERSION_NUMBER = vers; + + StringTokenizer tok = new StringTokenizer(VERSION_NUMBER, ".-"); + int major, minor, patch; + try { + major = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0; + } catch (Exception e) { + major = 0; + } + + try { + minor = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0; + } catch (Exception e) { + minor = 0; + } + + try { + patch = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0; + } catch (Exception e) { + patch = 0; + } + + String revision = revisionProps.getProperty("svn.revision"); + if (StringUtils.isBlank(revision)) { + revision = "unknown"; + } else { + tok = new StringTokenizer(revision, ":"); + String strTok = null; + while (tok.hasMoreTokens()) { + try { + strTok = tok.nextToken(); + } catch (Exception e) { + } + } + if (strTok != null) { + revision = strTok; + } + } + + MAJOR_RELEASE = major; + MINOR_RELEASE = minor; + PATCH_RELEASE = patch; + RELEASE_STATUS = tok.hasMoreTokens() ? tok.nextToken("!") : ""; + REVISION_NUMBER = revision; + PROJECT_ID = PROJECT_NAME + " " + VERSION_NUMBER + "-r" + REVISION_NUMBER; + } + + /** + * Get the project version number. + * @return String + */ + public static String getVersion() { + return VERSION_NUMBER; + } + + /** + * Get the version control revision number. + * @return String + */ + public static String getRevision() { + return REVISION_NUMBER; + } + + /** + * Get the project name. + * @return String + */ + public static String getName() { + return PROJECT_NAME; + } + + /** + * Get the fully-qualified project id. + * @return String + */ + public static String getID() { + return PROJECT_ID; + } + + /** + * Main method of this class that prints the {@link #toString()} to <code>System.out</code>. + * @param args ignored + */ + public static void main(String[] args) { + System.out.println(new BValVersion().toString()); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(80 * 40); + appendBanner(buf); + buf.append("\n"); + + appendProperty("os.name", buf).append("\n"); + appendProperty("os.version", buf).append("\n"); + appendProperty("os.arch", buf).append("\n\n"); + + appendProperty("java.version", buf).append("\n"); + appendProperty("java.vendor", buf).append("\n\n"); + + buf.append("java.class.path:\n"); + final StringTokenizer tok = new StringTokenizer(Reflection.getProperty("java.class.path")); + while (tok.hasMoreTokens()) { + buf.append("\t").append(tok.nextToken()); + buf.append("\n"); + } + buf.append("\n"); + + appendProperty("user.dir", buf).append("\n"); + return buf.toString(); + } + + private void appendBanner(StringBuilder buf) { + buf.append("Project").append(": ").append(getName()); + buf.append("\n"); + buf.append("Version").append(": ").append(getVersion()); + buf.append("\n"); + buf.append("Revision").append(": ").append(getRevision()); + buf.append("\n"); + } + + private StringBuilder appendProperty(String prop, StringBuilder buf) { + return buf.append(prop).append(": ").append(Reflection.getProperty(prop)); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/Exceptions.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/Exceptions.java b/bval-jsr/src/main/java/org/apache/bval/util/Exceptions.java new file mode 100644 index 0000000..9487cde --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/Exceptions.java @@ -0,0 +1,125 @@ +/* + * 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. + */ +package org.apache.bval.util; + +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; + +/** + * Utility class for the creation and throwing of Exceptions. + */ +public class Exceptions { + + public static <E extends Exception> E create(Function<? super String, ? extends E> fn, String format, + Object... args) { + return create(fn, () -> String.format(format, args)); + } + + public static <E extends Exception, C extends Throwable> E create( + BiFunction<? super String, ? super C, ? extends E> fn, C cause, String format, Object... args) { + return create(fn, cause, () -> String.format(format, args)); + } + + public static <E extends Exception> E create(Function<? super String, ? extends E> fn, Supplier<String> message) { + return elideStackTrace(fn.apply(message.get())); + } + + public static <E extends Exception, C extends Throwable> E create( + BiFunction<? super String, ? super C, ? extends E> fn, C cause, Supplier<String> message) { + return elideStackTrace(fn.apply(message.get(), cause)); + } + + public static <E extends Exception, R> R raise(Function<? super String, ? extends E> fn, String format, + Object... args) throws E { + throw create(fn, format, args); + } + + public static <E extends Exception> void raiseIf(boolean condition, Function<? super String, ? extends E> fn, + String format, Object... args) throws E { + if (condition) { + raise(fn, format, args); + } + } + + public static <E extends Exception> void raiseUnless(boolean condition, Function<? super String, ? extends E> fn, + String format, Object... args) throws E { + raiseIf(!condition, fn, format, args); + } + + public static <E extends Exception, R> R raise(Function<? super String, ? extends E> fn, Supplier<String> message) + throws E { + throw create(fn, message); + } + + public static <E extends Exception> void raiseIf(boolean condition, Function<? super String, ? extends E> fn, + Supplier<String> message) throws E { + if (condition) { + raise(fn, message); + } + } + + public static <E extends Exception> void raiseUnless(boolean condition, Function<? super String, ? extends E> fn, + Supplier<String> message) throws E { + raiseIf(!condition, fn, message); + } + + public static <E extends Exception, C extends Throwable, R> R raise( + BiFunction<? super String, ? super C, ? extends E> fn, C cause, String format, Object... args) throws E { + throw create(fn, cause, format, args); + } + + public static <E extends Exception, C extends Throwable> void raiseIf(boolean condition, + BiFunction<? super String, ? super C, ? extends E> fn, C cause, String format, Object... args) throws E { + if (condition) { + raise(fn, cause, format, args); + } + } + + public static <E extends Exception, C extends Throwable> void raiseUnless(boolean condition, + BiFunction<? super String, ? super C, ? extends E> fn, C cause, String format, Object... args) throws E { + raiseIf(!condition, fn, cause, format, args); + } + + public static <E extends Exception, C extends Throwable, R> R raise( + BiFunction<? super String, ? super C, ? extends E> fn, C cause, Supplier<String> message) throws E { + throw create(fn, cause, message); + } + + public static <E extends Exception, C extends Throwable> void raiseIf(boolean condition, + BiFunction<? super String, ? super C, ? extends E> fn, C cause, Supplier<String> message) throws E { + if (condition) { + raise(fn, cause, message); + } + } + + public static <E extends Exception, C extends Throwable> void raiseUnless(boolean condition, + BiFunction<? super String, ? super C, ? extends E> fn, C cause, Supplier<String> message) throws E { + raiseIf(!condition, fn, cause, message); + } + + private static <T extends Throwable> T elideStackTrace(T t) { + final StackTraceElement[] stackTrace = t.fillInStackTrace().getStackTrace(); + t.setStackTrace(Stream.of(stackTrace).filter(e -> !Exceptions.class.getName().equals(e.getClassName())) + .toArray(StackTraceElement[]::new)); + return t; + } + + private Exceptions() { + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java b/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java new file mode 100644 index 0000000..4796de3 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.bval.util; + +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * @since 2.0 + * + * @param <T> + */ +public class Lazy<T> implements Supplier<T> { + private T value; + private volatile Supplier<T> init; + + public Lazy(Supplier<T> init) { + reset(init); + } + + public Lazy<T> reset(Supplier<T> init) { + this.init = Validate.notNull(init); + return this; + } + + @Override + public T get() { + if (init != null) { + synchronized (this) { + if (init != null) { + value = init.get(); + init = null; + } + } + } + return value; + } + + public Optional<T> optional() { + return Optional.ofNullable(value); + } + + public <U> Consumer<U> consumer(BiConsumer<? super T, ? super U> delegate) { + return u -> delegate.accept(get(), u); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/LazyInt.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/LazyInt.java b/bval-jsr/src/main/java/org/apache/bval/util/LazyInt.java new file mode 100644 index 0000000..b866226 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/LazyInt.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.bval.util; + +import java.util.OptionalInt; +import java.util.function.IntSupplier; + +/** + * @since 2.0 + */ +public class LazyInt implements IntSupplier { + private int value; + private volatile IntSupplier init; + + public LazyInt(IntSupplier init) { + this.init = Validate.notNull(init); + } + + @Override + public int getAsInt() { + if (init != null) { + synchronized (this) { + if (init != null) { + value = init.getAsInt(); + init = null; + } + } + } + return value; + } + + public synchronized OptionalInt optional() { + return init == null ? OptionalInt.of(value) : OptionalInt.empty(); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/ObjectUtils.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/ObjectUtils.java b/bval-jsr/src/main/java/org/apache/bval/util/ObjectUtils.java new file mode 100644 index 0000000..1c5a728 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/ObjectUtils.java @@ -0,0 +1,98 @@ +/* + * 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. + */ +package org.apache.bval.util; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Stream; + +public final class ObjectUtils { + public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0]; + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + public static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; + + private ObjectUtils() { + } + + /** + * <p>Returns a default value if the object passed is {@code null}.</p> + * + * <pre> + * ObjectUtils.defaultIfNull(null, null) = null + * ObjectUtils.defaultIfNull(null, "") = "" + * ObjectUtils.defaultIfNull(null, "zz") = "zz" + * ObjectUtils.defaultIfNull("abc", *) = "abc" + * ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE + * </pre> + * + * @param <T> the type of the object + * @param object the {@code Object} to test, may be {@code null} + * @param defaultValue the default value to return, may be {@code null} + * @return {@code object} if it is not {@code null}, defaultValue otherwise + */ + public static <T> T defaultIfNull(final T object, final T defaultValue) { + return object == null ? defaultValue : object; + } + + public static <T> boolean isNotEmpty(final T[] array) { + return !isEmpty(array); + } + + public static boolean isEmpty(final Object[] array) { + return array == null || array.length == 0; + } + + /** + * <p>Checks if the object is in the given array. + * + * <p>The method returns {@code false} if a {@code null} array is passed in. + * + * @param array the array to search through + * @param objectToFind the object to find + * @return {@code true} if the array contains the object + */ + public static boolean arrayContains(final Object[] array, final Object objectToFind) { + if (array == null) { + return false; + } + return Stream.of(array).anyMatch(Predicate.isEqual(objectToFind)); + } + + public static int indexOf(final Object[] array, final Object objectToFind) { + for (int i = 0; i < array.length; i++) { + if (Objects.equals(array[i], objectToFind)) { + return i; + } + } + return -1; + } + + public static <T> T[] arrayAdd(T[] array, T objectToAdd) { + if (array == null && objectToAdd == null) { + throw new IllegalArgumentException("Arguments cannot both be null"); + } + final int arrayLength = Array.getLength(array); + @SuppressWarnings("unchecked") + T[] newArray = (T[]) Array.newInstance(array.getClass().getComponentType(), arrayLength + 1); + System.arraycopy(array, 0, newArray, 0, arrayLength); + newArray[newArray.length - 1] = objectToAdd; + + return newArray; + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/ObjectWrapper.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/ObjectWrapper.java b/bval-jsr/src/main/java/org/apache/bval/util/ObjectWrapper.java new file mode 100644 index 0000000..8483745 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/ObjectWrapper.java @@ -0,0 +1,50 @@ +/* + * 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. + */ +package org.apache.bval.util; + +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ObjectWrapper<T> implements Consumer<T>, Supplier<T> { + private T value; + + public ObjectWrapper() { + this(null); + } + + public ObjectWrapper(T value) { + super(); + this.value = value; + } + + @Override + public void accept(T value) { + this.value = value; + } + + @Override + public T get() { + return value; + } + + public Optional<T> optional() { + return Optional.ofNullable(value); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/StringUtils.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/StringUtils.java b/bval-jsr/src/main/java/org/apache/bval/util/StringUtils.java new file mode 100644 index 0000000..6b9c25d --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/StringUtils.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.bval.util; + +import java.util.ArrayList; +import java.util.List; + +public final class StringUtils { + private StringUtils() { + } + + /** + * Taken from commons-lang3. + * <p> + * <p>Capitalizes a String changing the first character to title case as + * per {@link Character#toTitleCase(char)}. No other characters are changed.</p> + * <p> + * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}. + * A {@code null} input String returns {@code null}.</p> + * <p> + * <pre> + * StringUtils.capitalize(null) = null + * StringUtils.capitalize("") = "" + * StringUtils.capitalize("cat") = "Cat" + * StringUtils.capitalize("cAt") = "CAt" + * StringUtils.capitalize("'cat'") = "'cat'" + * </pre> + * + * @param str the String to capitalize, may be null + * @return the capitalized String, {@code null} if null String input + * @see org.apache.commons.lang3.text.WordUtils#capitalize(String) + */ + public static String capitalize(final String str) { + int strLen; + if (str == null || (strLen = str.length()) == 0) { + return str; + } + + final char firstChar = str.charAt(0); + final char newChar = Character.toTitleCase(firstChar); + if (firstChar == newChar) { + // already capitalized + return str; + } + + char[] newChars = new char[strLen]; + newChars[0] = newChar; + str.getChars(1, strLen, newChars, 1); + return String.valueOf(newChars); + } + + /** + * Taken from commons-lang3. + * <p>Checks if a CharSequence is whitespace, empty ("") or null.</p> + * <p> + * <pre> + * StringUtils.isBlank(null) = true + * StringUtils.isBlank("") = true + * StringUtils.isBlank(" ") = true + * StringUtils.isBlank("bob") = false + * StringUtils.isBlank(" bob ") = false + * </pre> + * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is null, empty or whitespace + */ + public static boolean isBlank(final CharSequence cs) { + int strLen; + if (cs == null || (strLen = cs.length()) == 0) { + return true; + } + for (int i = 0; i < strLen; i++) { + if (Character.isWhitespace(cs.charAt(i)) == false) { + return false; + } + } + return true; + } + + /** + * Taken from commons-lang3. + * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p> + * + * <pre> + * StringUtils.isNotBlank(null) = false + * StringUtils.isNotBlank("") = false + * StringUtils.isNotBlank(" ") = false + * StringUtils.isNotBlank("bob") = true + * StringUtils.isNotBlank(" bob ") = true + * </pre> + * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is + * not empty and not null and not whitespace + */ + public static boolean isNotBlank(final CharSequence cs) { + return !isBlank(cs); + } + + /** + * <p>Splits the provided text into an array, separator is whitespace. + */ + public static String[] split(String str) { + return split(str, null); + } + + /** + * <p>Splits the provided text into an array, separator is whitespace. + */ + public static String[] split(String str, Character token) { + if (str == null || str.isEmpty()) { + return ObjectUtils.EMPTY_STRING_ARRAY; + } + + // split on token + List<String> ret = new ArrayList<>(); + StringBuilder sb = new StringBuilder(str.length()); + for (int pos = 0; pos < str.length(); pos++) { + char c = str.charAt(pos); + if ((token == null && Character.isWhitespace(c)) || (token != null && token.equals(c))) { + if (sb.length() > 0) { + ret.add(sb.toString()); + sb.setLength(0); // reset the string + } + } else { + sb.append(c); + } + } + if (sb.length() > 0) { + ret.add(sb.toString()); + } + return ret.toArray(new String[ret.size()]); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/Validate.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/Validate.java b/bval-jsr/src/main/java/org/apache/bval/util/Validate.java new file mode 100644 index 0000000..042dc1b --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/Validate.java @@ -0,0 +1,59 @@ +/* + * 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. + */ +package org.apache.bval.util; + +import java.util.function.Function; + +/** + * Some used validations from commons. + */ +public final class Validate { + private Validate() { + } + + public static <T> T notNull(final T object) { + return notNull(object, "The validated object is null"); + } + + public static <T> T notNull(final T object, final String message, final Object... values) { + return notNull(object, NullPointerException::new, message, values); + } + + public static <E extends Exception, T> T notNull(final T object, Function<? super String, ? extends E> fn, + final String message, final Object... values) throws E { + Exceptions.raiseIf(object == null, fn, message, values); + return object; + } + + public static void isTrue(final boolean expression, final String message, final Object... values) { + Exceptions.raiseUnless(expression, IllegalArgumentException::new, message, values); + } + + public static <T> T[] noNullElements(final T[] array, final String message, final Object... values) { + Validate.notNull(array); + + for (int i = 0; i < array.length; i++) { + Exceptions.raiseIf(array[i] == null, IllegalArgumentException::new, message, + ObjectUtils.arrayAdd(values, Integer.valueOf(i))); + } + return array; + } + + public static void validState(final boolean expression, final String message, final Object... values) { + Exceptions.raiseUnless(expression, IllegalStateException::new, message, values); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java b/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java new file mode 100644 index 0000000..79e88fb --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java @@ -0,0 +1,457 @@ +/* + * 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. + */ +package org.apache.bval.util.reflection; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; + +import org.apache.commons.weaver.privilizer.Privilizing; + +/** + * Security-agnostic "blueprint" class for reflection-related operations. Intended for use by Apache BVal code. + */ +public class Reflection { + /** + * Inclusivity literals for {@link #hierarchy(Class, Interfaces)}. + * Taken from commons-lang3. + */ + public enum Interfaces { + INCLUDE, EXCLUDE + } + + private static final Object[][] NATIVE_CODES = new Object[][]{ + { byte.class, "byte", "B" }, + { char.class, "char", "C" }, + { double.class, "double", "D" }, + { float.class, "float", "F" }, + { int.class, "int", "I" }, + { long.class, "long", "J" }, + { short.class, "short", "S" }, + { boolean.class, "boolean", "Z" }, + { void.class, "void", "V" } + }; + + /** + * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}. + */ + private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_MAP; + static { + final Map<Class<?>, Class<?>> m = new HashMap<>(); + m.put(Boolean.TYPE, Boolean.class); + m.put(Byte.TYPE, Byte.class); + m.put(Character.TYPE, Character.class); + m.put(Short.TYPE, Short.class); + m.put(Integer.TYPE, Integer.class); + m.put(Long.TYPE, Long.class); + m.put(Double.TYPE, Double.class); + m.put(Float.TYPE, Float.class); + m.put(Void.TYPE, Void.TYPE); + PRIMITIVE_WRAPPER_MAP = Collections.unmodifiableMap(m); + } + + /** + * <p>Converts the specified primitive Class object to its corresponding + * wrapper Class object.</p> + * + * <p>NOTE: From v2.2, this method handles {@code Void.TYPE}, + * returning {@code Void.TYPE}.</p> + * + * @param cls the class to convert, may be null + * @return the wrapper class for {@code cls} or {@code cls} if + * {@code cls} is not a primitive. {@code null} if null input. + * @since 2.1 + */ + public static Class<?> primitiveToWrapper(final Class<?> cls) { + Class<?> convertedClass = cls; + if (cls != null && cls.isPrimitive()) { + convertedClass = PRIMITIVE_WRAPPER_MAP.get(cls); + } + return convertedClass; + } + + public static Class<?> wrapperToPrimitive(final Class<?> cls) { + for (Map.Entry<Class<?>, Class<?>> primitiveEntry : PRIMITIVE_WRAPPER_MAP.entrySet()) { + if (primitiveEntry.getValue().equals(cls)) { + return primitiveEntry.getKey(); + } + } + return null; + } + + /** + * Get the named value from the specified {@link Annotation}. + * @param annotation + * @param name + * @return Object value + * @throws IllegalAccessException + * @throws InvocationTargetException + */ + public static Object getAnnotationValue(final Annotation annotation, final String name) + throws IllegalAccessException, InvocationTargetException { + final Method valueMethod; + try { + valueMethod = annotation.annotationType().getDeclaredMethod(name); + } catch (final NoSuchMethodException ex) { + // do nothing + return null; + } + final boolean mustUnset = setAccessible(valueMethod, true); + try { + return valueMethod.invoke(annotation); + } finally { + if (mustUnset) { + setAccessible(valueMethod, false); + } + } + } + + /** + * Get a usable {@link ClassLoader}: that of {@code clazz} if {@link Thread#getContextClassLoader()} returns {@code null}. + * @param clazz + * @return {@link ClassLoader} + */ + public static ClassLoader getClassLoader(final Class<?> clazz) { + final ClassLoader cl = Thread.currentThread().getContextClassLoader(); + return cl == null ? clazz.getClassLoader() : cl; + } + + public static Class<?> toClass(String className) throws ClassNotFoundException { + ClassLoader cl = getClassLoader(Reflection.class); + return toClass(className, cl); + } + + /** + * Return the class for the given string, correctly handling + * primitive types. If the given class loader is null, the context + * loader of the current thread will be used. + * + * @throws RuntimeException on load error + */ + public static Class<?> toClass(String className, ClassLoader loader) throws ClassNotFoundException { + return toClass(className, false, loader); + } + + /** + * Return the class for the given string, correctly handling + * primitive types. If the given class loader is null, the context + * loader of the current thread will be used. + * + * @throws RuntimeException on load error + */ + public static Class<?> toClass(String className, boolean resolve, ClassLoader loader) throws ClassNotFoundException { + if (className == null) { + throw new NullPointerException("className == null"); + } + + // array handling + int dims = 0; + while (className.endsWith("[]")) { + dims++; + className = className.substring(0, className.length() - 2); + } + + // check against primitive types + boolean primitive = false; + if (className.indexOf('.') == -1) { + for (int i = 0; !primitive && (i < NATIVE_CODES.length); i++) { + if (NATIVE_CODES[i][1].equals(className)) { + if (dims == 0) { + return (Class<?>) NATIVE_CODES[i][0]; + } + className = (String) NATIVE_CODES[i][2]; + primitive = true; + } + } + } + + if (dims > 0) { + StringBuilder buf = new StringBuilder(className.length() + dims + 2); + for (int i = 0; i < dims; i++) { + buf.append('['); + } + if (!primitive) { + buf.append('L'); + } + buf.append(className); + if (!primitive) { + buf.append(';'); + } + className = buf.toString(); + } + + if (loader == null) { + loader = Thread.currentThread().getContextClassLoader(); + } + + return Class.forName(className, resolve, loader); + } + + + /** + * Convenient point for {@link Privilizing} {@link System#getProperty(String)}. + * @param name + * @return String + */ + public static String getProperty(final String name) { + return System.getProperty(name); + } + + /** + * Get the declared field from {@code clazz}. + * @param clazz + * @param fieldName + * @return {@link Field} or {@code null} + */ + public static Field getDeclaredField(final Class<?> clazz, final String fieldName) { + try { + return clazz.getDeclaredField(fieldName); + } catch (final NoSuchFieldException e) { + return null; + } + } + + /** + * Convenient point for {@link Privilizing} {@link Class#getDeclaredFields()}. + * @param clazz + * @return {@link Field} array + */ + public static Field[] getDeclaredFields(final Class<?> clazz) { + return clazz.getDeclaredFields(); + } + + /** + * Get the declared constructor from {@code clazz}. + * @param clazz + * @param parameters + * @return {@link Constructor} or {@code null} + */ + public static <T> Constructor<T> getDeclaredConstructor(final Class<T> clazz, final Class<?>... parameters) { + try { + return clazz.getDeclaredConstructor(parameters); + } catch (final NoSuchMethodException e) { + return null; + } + } + + /** + * Get the declared method from {@code clazz}. + * @param clazz + * @param name + * @param parameters + * @return {@link Method} or {@code null} + */ + public static Method getDeclaredMethod(final Class<?> clazz, final String name, final Class<?>... parameters) { + try { + return clazz.getDeclaredMethod(name, parameters); + } catch (final NoSuchMethodException e) { + return null; + } + } + + /** + * Convenient point for {@link Privilizing} {@link Class#getDeclaredMethods()}. + * @param clazz + * @return {@link Method} array + */ + public static Method[] getDeclaredMethods(final Class<?> clazz) { + return clazz.getDeclaredMethods(); + } + + /** + * Convenient point for {@link Privilizing} {@link Class#getDeclaredConstructors()}. + * @param clazz + * @return {@link Constructor} array + */ + public static Constructor<?>[] getDeclaredConstructors(final Class<?> clazz) { + return clazz.getDeclaredConstructors(); + } + + /** + * Get the specified {@code public} {@link Method} from {@code clazz}. + * @param clazz + * @param methodName + * @return {@link Method} or {@code null} + */ + public static Method getPublicMethod(final Class<?> clazz, final String methodName, Class<?>... parameterTypes) { + try { + return clazz.getMethod(methodName, parameterTypes); + } catch (final NoSuchMethodException e) { + return null; + } + } + + /** + * Perform a search against the class hierarchy. + * @param clazz + * @param search + * @return T or {@code null} + */ + public static <T> T find(final Class<?> clazz, Function<Class<?>, T> search) { + for (Class<?> t : hierarchy(clazz, Interfaces.INCLUDE)) { + final T value = search.apply(t); + if (value != null) { + return value; + } + } + return null; + } + + /** + * Construct a new instance of {@code cls} using its default constructor. + * @param cls + * @return T + */ + public static <T> T newInstance(final Class<T> cls) { + try { + return cls.getConstructor().newInstance(); + } catch (final Exception ex) { + throw new RuntimeException("Cannot instantiate : " + cls, ex); + } + } + + /** + * Set the accessibility of {@code o} to {@code accessible}. If running without a {@link SecurityManager} + * and {@code accessible == false}, this call is ignored (because any code could reflectively make any + * object accessible at any time). + * @param o + * @param accessible + * @return whether a change was made. + */ + public static boolean setAccessible(final AccessibleObject o, boolean accessible) { + if (o == null || o.isAccessible() == accessible) { + return false; + } + if (!accessible && System.getSecurityManager() == null) { + return false; + } + final Member m = (Member) o; + + // For public members whose declaring classes are public, we need do nothing: + if (Modifier.isPublic(m.getModifiers()) && Modifier.isPublic(m.getDeclaringClass().getModifiers())) { + return false; + } + o.setAccessible(accessible); + return true; + } + + /** + * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order. + * Taken from commons-lang3. + * + * @param type the type to get the class hierarchy from + * @param interfacesBehavior switch indicating whether to include or exclude interfaces + * @return Iterable an Iterable over the class hierarchy of the given class + */ + public static Iterable<Class<?>> hierarchy(final Class<?> type, final Interfaces interfacesBehavior) { + if (type == null) { + return Collections.emptySet(); + } + final Iterable<Class<?>> classes = new Iterable<Class<?>>() { + + @Override + public Iterator<Class<?>> iterator() { + return new Iterator<Class<?>>() { + Optional<Class<?>> next; + { + next = Optional.of(type); + } + + @Override + public boolean hasNext() { + return next.isPresent(); + } + + @Override + public Class<?> next() { + final Class<?> result = next.orElseThrow(NoSuchElementException::new); + next = Optional.ofNullable(result.getSuperclass()); + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + if (interfacesBehavior != Interfaces.INCLUDE) { + return classes; + } + return new Iterable<Class<?>>() { + + @Override + public Iterator<Class<?>> iterator() { + final Set<Class<?>> seenInterfaces = new HashSet<Class<?>>(); + final Iterator<Class<?>> wrapped = classes.iterator(); + + return new Iterator<Class<?>>() { + Iterator<Class<?>> interfaces = Collections.emptyIterator(); + + @Override + public boolean hasNext() { + return interfaces.hasNext() || wrapped.hasNext(); + } + + @Override + public Class<?> next() { + if (interfaces.hasNext()) { + final Class<?> nextInterface = interfaces.next(); + seenInterfaces.add(nextInterface); + return nextInterface; + } + final Class<?> nextSuperclass = wrapped.next(); + final Set<Class<?>> currentInterfaces = new LinkedHashSet<>(); + walkInterfaces(currentInterfaces, nextSuperclass); + interfaces = currentInterfaces.iterator(); + return nextSuperclass; + } + + private void walkInterfaces(final Set<Class<?>> addTo, final Class<?> c) { + for (final Class<?> iface : c.getInterfaces()) { + if (!seenInterfaces.contains(iface)) { + addTo.add(iface); + } + walkInterfaces(addTo, iface); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } +}
