Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@

import java.beans.Introspector;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import groovy.lang.Closure;
Expand Down Expand Up @@ -173,28 +171,14 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp
}

private static ClassNode alignReturnType(final ClassNode receiver, final ClassNode originalReturnType) {
ClassNode copiedReturnType = originalReturnType.getPlainNodeReference();

List<GenericsType> redirectTypes = new ArrayList<>();
if (receiver.redirect().getGenericsTypes() != null) {
Collections.addAll(redirectTypes, receiver.redirect().getGenericsTypes());
if (!originalReturnType.isUsingGenerics()) {
return originalReturnType.getPlainNodeReference();
}
if (!redirectTypes.isEmpty()) {
GenericsType[] redirectReceiverTypes = redirectTypes.toArray(new GenericsType[0]);

GenericsType[] receiverParameterizedTypes = receiver.getGenericsTypes();
if (receiverParameterizedTypes == null) {
receiverParameterizedTypes = redirectReceiverTypes;
}

if (originalReturnType.isUsingGenerics()) {
GenericsType[] alignmentTypes = originalReturnType.getGenericsTypes();
GenericsType[] genericsTypes = GenericsUtils.alignGenericTypes(redirectReceiverTypes, receiverParameterizedTypes, alignmentTypes);
copiedReturnType.setGenericsTypes(genericsTypes);
}
}

return copiedReturnType;
var genericsSpec = GenericsUtils.createGenericsSpec(receiver);
var correctedReturnType = GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, originalReturnType);
return correctedReturnType == null ?
originalReturnType.getPlainNodeReference() :
correctedReturnType;
}

protected DelegateAsyncTransactionalMethodTransformer lookupAsyncTransactionalMethodTransformer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,92 @@ class DelegateAsyncSpec extends Specification {
then: 'the decorator is applied to the value'
val == 6
}

void 'Delegate async transform preserves generic return type for static compilation'() {
when:
def result = new GroovyShell().evaluate('''
import grails.async.*
import groovy.transform.CompileStatic

class GenericService<T> {
T echo(T value) { value }
}

class AsyncStringService {
@DelegateAsync
GenericService<String> service = new GenericService<String>()
}

@CompileStatic
String test() {
Promise<String> p = new AsyncStringService().echo('hello')
p.get()
}

test()
''')

then:
result == 'hello'
}

void 'Delegate async transform aligns generic return type from inherited interface method'() {
when:
def service = new AsyncStringHolderService()
def p = service.get()

then:
p instanceof Promise

and:
p.get() == 'hello'
}

void 'Delegate async transform preserves generic return type from inherited interface method for static compilation'() {
when:
def result = new GroovyShell().evaluate('''
import grails.async.*
import groovy.transform.CompileStatic

interface Holder<T> {
T get()
}

class StringHolder implements Holder<String> {
@Override
String get() {
'hello'
}
}

@DelegateAsync(StringHolder)
class AsyncStringHolderService {
}

@CompileStatic
String test() {
Promise<String> p = new AsyncStringHolderService().get()
p.get()
}

test()
''')

then:
result == 'hello'
}

void 'Delegate async transform aligns generic return type from parameterized interface field'() {
when:
def service = new AsyncParameterizedHolderService()
def p = service.get()

then:
p instanceof Promise

and:
p.get() == 'hello'
}
}

class MathService {
Expand Down Expand Up @@ -103,3 +189,22 @@ class AsyncMathService3 implements PromiseDecoratorProvider {
]
}

interface Holder<T> {
T get()
}

class StringHolder implements Holder<String> {
@Override
String get() {
'hello'
}
}

@DelegateAsync(StringHolder)
class AsyncStringHolderService {
}

class AsyncParameterizedHolderService {
@DelegateAsync
Holder<String> holder = new StringHolder()
}
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ public static GrailsConsole createInstance() throws IOException {
try {
@SuppressWarnings("unchecked")
Class<? extends GrailsConsole> klass = (Class<? extends GrailsConsole>) Class.forName(className);
return klass.newInstance();
return klass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public void messageLogged(BuildEvent event) {
}

if (null != targetName) {
console.verbose(StringUtils.LINE_SEP + targetName + ":");
console.verbose(System.lineSeparator() + targetName + ":");
targetName = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ public DirectoryWatcher() {

}
if (jnaAvailable) {
directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.MacOsWatchServiceDirectoryWatcher").newInstance();
directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.MacOsWatchServiceDirectoryWatcher").getDeclaredConstructor().newInstance();
} else {
directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").newInstance();
directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").getDeclaredConstructor().newInstance();
}
} else {
directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").newInstance();
directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").getDeclaredConstructor().newInstance();
}
} catch (Throwable e) {
LOG.info("Exception while trying to load WatchServiceDirectoryWatcher (this is probably Java 6 and WatchService isn't available). Falling back to PollingDirectoryWatcher.", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static Object createConverter(Class<?> converterClass, Object target) thr

public static <T> T createConverter(Class<T> converterClass, Object target, ApplicationContext applicationContext) throws ConverterException {
try {
T converter = converterClass.newInstance();
T converter = converterClass.getDeclaredConstructor().newInstance();
if (converter instanceof ApplicationContextAware && applicationContext != null) {
((ApplicationContextAware) converter).setApplicationContext(applicationContext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void marshalObject(Object o, JSON json) throws ConverterException {
}
for (Field field : o.getClass().getDeclaredFields()) {
int modifiers = field.getModifiers();
if (field.isAccessible() && Modifier.isPublic(modifiers) && !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) {
if (field.canAccess(o) && Modifier.isPublic(modifiers) && !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) {
String name = field.getName();
if (!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) continue;
writer.key(field.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void marshalObject(Object o, XML xml) throws ConverterException {
}
for (Field field : o.getClass().getDeclaredFields()) {
int modifiers = field.getModifiers();
if (field.isAccessible() && Modifier.isPublic(modifiers) &&
if (field.canAccess(o) && Modifier.isPublic(modifiers) &&
!(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) {
xml.startNode(field.getName());
xml.convertAnother(field.get(o));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
Expand Down Expand Up @@ -952,7 +953,13 @@ public static Object instantiateFromFlatConfig(Map<String, Object> flatConfig, S
if (configName instanceof CharSequence) {
className = configName.toString();
}
return ClassUtils.forName(className, ClassUtils.getDefaultClassLoader()).newInstance();
try {
return ClassUtils.forName(className, ClassUtils.getDefaultClassLoader()).getDeclaredConstructor().newInstance();
} catch (InvocationTargetException | NoSuchMethodException e) {
throw new InstantiationException(
"Could not instantiate class [" + className + "]: " + e.getMessage()
);
}
}

/**
Expand Down
13 changes: 3 additions & 10 deletions grails-core/src/main/groovy/grails/util/Holders.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package grails.util;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -220,17 +221,9 @@ private static <T> T get(Holder<T> holder, String type, boolean mappedOnly) {
private static void createServletContextsHolder() {
try {
Class<?> clazz = Holders.class.getClassLoader().loadClass("grails.web.context.WebRequestServletHolder");
servletContexts = (Holder) clazz.newInstance();
servletContexts = (Holder) clazz.getDeclaredConstructor().newInstance();
}
catch (ClassNotFoundException e) {
// shouldn't happen
LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e);
}
catch (InstantiationException e) {
// shouldn't happen
LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e);
}
catch (IllegalAccessException e) {
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// shouldn't happen
LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Set;

import org.apache.groovy.ast.tools.AnnotatedNodeUtils;
import org.apache.groovy.util.BeanUtils;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
Expand All @@ -53,7 +54,6 @@
import org.codehaus.groovy.ast.stmt.ThrowStatement;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;

Expand Down Expand Up @@ -344,7 +344,7 @@ protected void addApiLookupFieldAndSetter(ClassNode classNode, ClassNode impleme
fieldNode = new FieldNode(apiProperty, Modifier.PRIVATE | Modifier.STATIC, implementationNode, classNode, initialValueExpression);
classNode.addField(fieldNode);

String setterName = "set" + MetaClassHelper.capitalize(apiProperty);
String setterName = "set" + BeanUtils.capitalize(apiProperty);
Parameter setterParameter = new Parameter(implementationNode, apiProperty);
BlockStatement setterBody = new BlockStatement();
setterBody.addStatement(new ExpressionStatement(new BinaryExpression(new AttributeExpression(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import groovy.transform.TypeChecked;
import groovy.transform.TypeCheckingMode;
import org.apache.groovy.ast.tools.AnnotatedNodeUtils;
import org.apache.groovy.util.BeanUtils;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
Expand Down Expand Up @@ -84,7 +85,6 @@
import org.codehaus.groovy.control.Janitor;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.codehaus.groovy.syntax.SyntaxException;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;
Expand Down Expand Up @@ -1371,7 +1371,7 @@ public static MethodCallExpression buildGetPropertyExpression(final Expression o
* @return The method call expression
*/
public static MethodCallExpression buildGetPropertyExpression(final Expression objectExpression, final String propertyName, final ClassNode targetClassNode, final boolean useBooleanGetter) {
String methodName = (useBooleanGetter ? "is" : "get") + MetaClassHelper.capitalize(propertyName);
String methodName = (useBooleanGetter ? "is" : "get") + BeanUtils.capitalize(propertyName);
MethodCallExpression methodCallExpression = new MethodCallExpression(objectExpression, methodName, MethodCallExpression.NO_ARGUMENTS);
MethodNode getterMethod = targetClassNode.getGetterMethod(methodName);
if (getterMethod != null) {
Expand All @@ -1390,7 +1390,7 @@ public static MethodCallExpression buildGetPropertyExpression(final Expression o
* @return The method call expression
*/
public static MethodCallExpression buildSetPropertyExpression(final Expression objectExpression, final String propertyName, final ClassNode targetClassNode, final Expression valueExpression) {
String methodName = "set" + MetaClassHelper.capitalize(propertyName);
String methodName = "set" + BeanUtils.capitalize(propertyName);
MethodCallExpression methodCallExpression = new MethodCallExpression(objectExpression, methodName, new ArgumentListExpression(valueExpression));
MethodNode setterMethod = targetClassNode.getSetterMethod(methodName);
if (setterMethod != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -55,7 +56,7 @@
* @author Graeme Rocher
* @since 0.6
*/
public class GrailsAwareInjectionOperation extends CompilationUnit.PrimaryClassNodeOperation {
public class GrailsAwareInjectionOperation implements CompilationUnit.IPrimaryClassNodeOperation {

private static final String INJECTOR_SCAN_PACKAGE = "org.grails.compiler";
private static final String INJECTOR_CODEHAUS_SCAN_PACKAGE = "org.codehaus.groovy.grails.compiler";
Expand Down Expand Up @@ -136,14 +137,14 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (ClassInjector.class.isAssignableFrom(injectorClass)) {

injectorClasses.add(injectorClass);
ClassInjector classInjector = (ClassInjector) injectorClass.newInstance();
ClassInjector classInjector = (ClassInjector) injectorClass.getDeclaredConstructor().newInstance();
injectors.add(classInjector);
if (GlobalClassInjector.class.isAssignableFrom(injectorClass)) {
globalInjectors.add(classInjector);
}
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// ignore
}
return super.visitAnnotation(desc, visible);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ public Class<?> getClazz() {
public Object newInstance() {
try {
Constructor<?> defaultConstructor = getClazz().getDeclaredConstructor(new Class[]{});
if (!defaultConstructor.isAccessible()) {
if (!defaultConstructor.canAccess(null)) {
defaultConstructor.setAccessible(true);
}
return defaultConstructor.newInstance(new Object[]{});
return defaultConstructor.newInstance();
}
catch (Exception e) {
Throwable targetException;
Expand Down
Loading
Loading