diff --git a/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java b/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java index 29801a3d3..60b13c620 100644 --- a/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java +++ b/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java @@ -57,7 +57,7 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor Method method = invocation.getMethod(); - if (!org.springframework.data.util.ReflectionUtils.isDefaultMethod(method)) { + if (!method.isDefault()) { return invocation.proceed(); } diff --git a/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java b/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java index 7dccbad56..5d4f2b560 100644 --- a/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java +++ b/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java @@ -19,6 +19,7 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.Set; +import java.util.stream.Stream; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.Repository; @@ -28,7 +29,6 @@ import org.springframework.data.repository.util.QueryExecutionConverters; import org.springframework.data.repository.util.ReactiveWrappers; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.Lazy; -import org.springframework.data.util.ReflectionUtils; import org.springframework.data.util.TypeInformation; import org.springframework.util.Assert; @@ -140,7 +140,7 @@ public abstract class AbstractRepositoryMetadata implements RepositoryMetadata { Class rawType = type.getType(); boolean needToUnwrap = Iterable.class.isAssignableFrom(rawType) || rawType.isArray() - || QueryExecutionConverters.supports(rawType) || ReflectionUtils.isJava8StreamType(rawType); + || QueryExecutionConverters.supports(rawType) || Stream.class.isAssignableFrom(rawType); return needToUnwrap ? unwrapWrapperTypes(type.getRequiredComponentType()) : rawType; } diff --git a/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java b/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java index 3098f1b41..ddbc51795 100644 --- a/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java +++ b/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java @@ -43,7 +43,6 @@ import org.springframework.data.repository.core.CrudMethods; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.util.Optionals; -import org.springframework.data.util.ReflectionUtils; import org.springframework.data.util.Streamable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -185,7 +184,7 @@ class DefaultRepositoryInformation implements RepositoryInformation { * @return */ private boolean isQueryMethodCandidate(Method method) { - return !method.isBridge() && !ReflectionUtils.isDefaultMethod(method) // + return !method.isBridge() && !method.isDefault() // && !Modifier.isStatic(method.getModifiers()) // && (isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method)); } diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java index 10ec276b7..051b46ff0 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java @@ -364,9 +364,10 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, Class baseClass = information.getRepositoryBaseClass(); Optional> constructor = ReflectionUtils.findConstructor(baseClass, constructorArguments); - return constructor.map(it -> (R) BeanUtils.instantiateClass(it, constructorArguments)).orElseThrow(() -> new IllegalStateException(String.format( - "No suitable constructor found on %s to match the given arguments: %s. Make sure you implement a constructor taking these", - baseClass, Arrays.stream(constructorArguments).map(Object::getClass).collect(Collectors.toList())))); + return constructor.map(it -> (R) BeanUtils.instantiateClass(it, constructorArguments)) + .orElseThrow(() -> new IllegalStateException(String.format( + "No suitable constructor found on %s to match the given arguments: %s. Make sure you implement a constructor taking these", + baseClass, Arrays.stream(constructorArguments).map(Object::getClass).collect(Collectors.toList())))); } /** diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/src/main/java/org/springframework/data/repository/query/QueryMethod.java index 9b8f8eb34..62831a4ed 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -19,6 +19,7 @@ import static org.springframework.data.repository.util.ClassUtils.*; import java.lang.reflect.Method; import java.util.Set; +import java.util.stream.Stream; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -30,7 +31,6 @@ import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.util.QueryExecutionConverters; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.Lazy; -import org.springframework.data.util.ReflectionUtils; import org.springframework.data.util.TypeInformation; import org.springframework.util.Assert; @@ -232,7 +232,7 @@ public class QueryMethod { * @since 1.10 */ public boolean isStreamQuery() { - return ReflectionUtils.isJava8StreamType(unwrappedReturnType); + return Stream.class.isAssignableFrom(unwrappedReturnType); } /** diff --git a/src/main/java/org/springframework/data/util/CastUtils.java b/src/main/java/org/springframework/data/util/CastUtils.java index d0ee70f55..c9e5bbdd0 100644 --- a/src/main/java/org/springframework/data/util/CastUtils.java +++ b/src/main/java/org/springframework/data/util/CastUtils.java @@ -1,12 +1,24 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.data.util; -import lombok.experimental.UtilityClass; - -@UtilityClass -public class CastUtils { +public interface CastUtils { @SuppressWarnings("unchecked") - public T cast(Object object) { + public static T cast(Object object) { return (T) object; } } diff --git a/src/main/java/org/springframework/data/util/ParsingUtils.java b/src/main/java/org/springframework/data/util/ParsingUtils.java index 011701527..999957abd 100644 --- a/src/main/java/org/springframework/data/util/ParsingUtils.java +++ b/src/main/java/org/springframework/data/util/ParsingUtils.java @@ -15,6 +15,8 @@ */ package org.springframework.data.util; +import lombok.experimental.UtilityClass; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -29,7 +31,8 @@ import org.springframework.util.StringUtils; * @author Oliver Gierke * @since 1.5 */ -public abstract class ParsingUtils { +@UtilityClass +public class ParsingUtils { private static final String UPPER = "\\p{Lu}|\\P{InBASIC_LATIN}"; private static final String LOWER = "\\p{Ll}"; @@ -38,8 +41,6 @@ public abstract class ParsingUtils { private static final Pattern CAMEL_CASE = Pattern.compile(CAMEL_CASE_REGEX); - private ParsingUtils() {} - /** * Splits up the given camel-case {@link String}. * diff --git a/src/main/java/org/springframework/data/util/ReflectionUtils.java b/src/main/java/org/springframework/data/util/ReflectionUtils.java index 437d982a7..639d6f2ed 100644 --- a/src/main/java/org/springframework/data/util/ReflectionUtils.java +++ b/src/main/java/org/springframework/data/util/ReflectionUtils.java @@ -17,12 +17,12 @@ package org.springframework.data.util; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.experimental.UtilityClass; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -45,22 +45,8 @@ import org.springframework.util.ReflectionUtils.FieldFilter; * @author Christoph Strobl * @since 1.5 */ -public abstract class ReflectionUtils { - - private static final Class JAVA8_STREAM_TYPE; - - static { - - Class cls = null; - - try { - cls = Class.forName("java.util.stream.Stream"); - } catch (ClassNotFoundException ignore) {} - - JAVA8_STREAM_TYPE = cls; - } - - private ReflectionUtils() {} +@UtilityClass +public class ReflectionUtils { /** * Creates an instance of the class with the given fully qualified name or returns the given default instance if the @@ -81,18 +67,6 @@ public abstract class ReflectionUtils { } } - /** - * Back-port of Java 8's {@code isDefault()} method on {@link Method}. - * - * @param method must not be {@literal null}. - * @return - */ - public static boolean isDefaultMethod(Method method) { - - return ((method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC) - && method.getDeclaringClass().isInterface(); - } - /** * A {@link FieldFilter} that has a description. * @@ -227,21 +201,6 @@ public abstract class ReflectionUtils { org.springframework.util.ReflectionUtils.setField(field, target, value); } - /** - * Tests whether the given type is assignable to a Java 8 {@link Stream}. - * - * @param type can be {@literal null}. - * @return - */ - public static boolean isJava8StreamType(Class type) { - - if (type == null || JAVA8_STREAM_TYPE == null) { - return false; - } - - return JAVA8_STREAM_TYPE.isAssignableFrom(type); - } - /** * Finds a constructor on the given type that matches the given constructor arguments. * @@ -276,15 +235,31 @@ public abstract class ReflectionUtils { return Stream.concat(returnType, parameterTypes); } + /** + * Returns the {@link Method} with the given name and parameters declared on the given type, if available. + * + * @param type must not be {@literal null}. + * @param name must not be {@literal null} or empty. + * @param parameterTypes must not be {@literal null}. + * @return + * @since 2.0 + */ public static Optional getMethod(Class type, String name, ResolvableType... parameterTypes) { - List> collect = Arrays.stream(parameterTypes).map(ResolvableType::getRawClass).collect(Collectors.toList()); + Assert.notNull(type, "Type must not be null!"); + Assert.hasText(name, "Name must not be null or empty!"); + Assert.notNull(parameterTypes, "Parameter types must not be null!"); + + List> collect = Arrays.stream(parameterTypes)// + .map(ResolvableType::getRawClass)// + .collect(Collectors.toList()); - Optional method = Optional.ofNullable( - org.springframework.util.ReflectionUtils.findMethod(type, name, collect.toArray(new Class[collect.size()]))); + Method method = org.springframework.util.ReflectionUtils.findMethod(type, name, + collect.toArray(new Class[collect.size()])); - return method.filter(it -> IntStream.range(0, it.getParameterCount())// - .allMatch(index -> ResolvableType.forMethodParameter(it, index).equals(parameterTypes[index]))); + return Optional.ofNullable(method)// + .filter(it -> IntStream.range(0, it.getParameterCount())// + .allMatch(index -> ResolvableType.forMethodParameter(it, index).equals(parameterTypes[index]))); } private static boolean argumentsMatch(Class[] parameterTypes, Object[] arguments) { diff --git a/src/main/java/org/springframework/data/util/StreamUtils.java b/src/main/java/org/springframework/data/util/StreamUtils.java index fdb6c75ba..1cb8fb4b0 100644 --- a/src/main/java/org/springframework/data/util/StreamUtils.java +++ b/src/main/java/org/springframework/data/util/StreamUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,9 +30,7 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @since 1.10 */ -public class StreamUtils { - - private StreamUtils() {} +public interface StreamUtils { /** * Returns a {@link Stream} backed by the given {@link Iterator}. @@ -51,50 +49,8 @@ public class StreamUtils { Spliterator spliterator = Spliterators.spliteratorUnknownSize(iterator, Spliterator.NONNULL); Stream stream = StreamSupport.stream(spliterator, false); - return iterator instanceof CloseableIterator - ? stream.onClose(new CloseableIteratorDisposingRunnable((CloseableIterator) iterator)) : stream; - } - - /** - * A {@link Runnable} that closes the given {@link CloseableIterator} in its {@link #run()} method. If the given - * {@code closeable} is {@literal null} the {@link #run()} method effectively becomes a noop. - *

- * Can be used in conjunction with streams as close action via: - * - *

-	 * CloseableIterator result = ...;
-	 * Spliterator spliterator = ...;
-	 * 
-	 * return StreamSupport.stream(spliterator, false).onClose(new CloseableIteratorDisposingRunnable(result));
-	 * 
- * - * @author Thomas Darimont - * @author Oliver Gierke - * @since 1.10 - */ - private static class CloseableIteratorDisposingRunnable implements Runnable { - - private CloseableIterator closeable; - - /** - * Creates a new {@link CloseableIteratorDisposingRunnable} for the given {@link CloseableIterator}. - * - * @param closeable can be {@literal null}. - */ - public CloseableIteratorDisposingRunnable(CloseableIterator closeable) { - this.closeable = closeable; - } - - /* - * (non-Javadoc) - * @see java.lang.Runnable#run() - */ - @Override - public void run() { - - if (closeable != null) { - closeable.close(); - } - } + return iterator instanceof CloseableIterator// + ? stream.onClose(() -> ((CloseableIterator) iterator).close()) // + : stream; } }