This is an automated email from the ASF dual-hosted git repository. jdaugherty pushed a commit to branch corrupt-jar-fixes in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit ef1bfc6fc5843a015902446ad4c23d87823f4bd8 Author: James Daugherty <[email protected]> AuthorDate: Fri May 16 10:16:11 2025 -0400 Revert "Various api cleanup for update to java 17" This reverts commit 8a4414bfdd6295623a3144064332c061456d9400. --- .../internal/DelegateAsyncTransformation.java | 53 +++++--- .../cache/GrailsConcurrentLinkedMapCache.java | 30 +++-- .../compiler/web/ControllerActionTransformer.java | 59 ++++---- .../main/groovy/grails/plugins/GrailsPlugin.java | 47 ++++--- .../groovy/grails/util/GrailsStringUtils.groovy | 28 ++-- .../org/grails/plugins/DefaultGrailsPlugin.java | 134 ++++++++++-------- .../org/grails/buffer/GrailsPrintWriter.java | 45 ++++--- .../org/grails/charsequences/CharSequences.java | 28 ++-- .../main/groovy/grails/util/BuildSettings.groovy | 107 +++++++++++++++ .../org/grails/gsp/GroovyPagesTemplateEngine.java | 107 ++++++++------- .../org/grails/gsp/ModelRecordingGroovyPage.groovy | 36 ++--- .../taglib/AbstractTemplateVariableBinding.java | 39 +++--- .../web/gsp/GroovyPagesTemplateRenderer.java | 48 +++---- .../org/grails/gsp/jsp/GroovyPagesPageContext.java | 65 ++++----- .../groovy/org/grails/web/json/JSONObject.java | 46 +++---- .../context/GrailsWebApplicationContext.java | 44 +++--- .../grails/web/databinding/DataBindingUtils.java | 73 +++++----- .../grails/web/errors/GrailsExceptionResolver.java | 60 ++++----- .../org/grails/web/mapping/RegexUrlMapping.java | 149 +++++++++++---------- 19 files changed, 678 insertions(+), 520 deletions(-) diff --git a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java index fcacba60d1..74fd98d37d 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java +++ b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.async.transform.internal; @@ -20,6 +22,14 @@ import grails.async.Promise; import grails.async.Promises; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; + +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 org.apache.grails.common.compiler.GroovyTransformOrder; import org.codehaus.groovy.GroovyBugError; import org.codehaus.groovy.ast.ASTNode; @@ -49,13 +59,6 @@ import org.codehaus.groovy.transform.GroovyASTTransformation; import org.codehaus.groovy.transform.TransformWithPriority; import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport; -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; - /** * Implementation of {@link grails.async.DelegateAsync} transformation * @@ -70,14 +73,18 @@ public class DelegateAsyncTransformation implements ASTTransformation, Transform public static final ClassNode OBJECT_CLASS_NODE = new ClassNode(Object.class); public void visit(ASTNode[] nodes, SourceUnit source) { - if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode annotationNode) || !(nodes[1] instanceof AnnotatedNode parent)) { + if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new GroovyBugError("Internal error: expecting [AnnotationNode, AnnotatedNode] but got: " + Arrays.asList(nodes)); } - if (parent instanceof ClassNode classNode) { + AnnotatedNode parent = (AnnotatedNode) nodes[1]; + AnnotationNode annotationNode = (AnnotationNode) nodes[0]; + + if (parent instanceof ClassNode) { Expression value = annotationNode.getMember("value"); if (value instanceof ClassExpression) { ClassNode targetApi = value.getType().getPlainNodeReference(); + ClassNode classNode = (ClassNode)parent; final String fieldName = '$' + Introspector.decapitalize(targetApi.getNameWithoutPackage()); FieldNode fieldNode = classNode.getField(fieldName); @@ -88,7 +95,9 @@ public class DelegateAsyncTransformation implements ASTTransformation, Transform applyDelegateAsyncTransform(classNode, targetApi, fieldName); } - } else if (parent instanceof FieldNode fieldNode) { + } + else if(parent instanceof FieldNode) { + FieldNode fieldNode = (FieldNode)parent; ClassNode targetApi = fieldNode.getType().getPlainNodeReference(); ClassNode classNode = fieldNode.getOwner(); applyDelegateAsyncTransform(classNode, targetApi, fieldNode.getName()); diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java index ade7ac0efe..f7530e86f0 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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 grails.plugin.cache; @@ -30,7 +32,7 @@ import java.util.concurrent.ConcurrentMap; public class GrailsConcurrentLinkedMapCache implements GrailsCache { private static final Object NULL_HOLDER = new NullHolder(); - private final String name; + private String name; private long capacity; private final ConcurrentLinkedHashMap<Object, Object> store; private final boolean allowNullValues; @@ -164,6 +166,8 @@ public class GrailsConcurrentLinkedMapCache implements GrailsCache { return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null); } + @SuppressWarnings("serial") + private static class NullHolder implements Serializable { } } diff --git a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java index ec48903e1e..3de3f27943 100644 --- a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java +++ b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.compiler.web; @@ -98,18 +100,7 @@ import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import static org.codehaus.groovy.ast.tools.GeneralUtils.args; -import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.boolX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.callX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.classX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.constX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.declX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS; -import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt; -import static org.codehaus.groovy.ast.tools.GeneralUtils.varX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.*; import static org.grails.compiler.injection.GrailsASTUtils.applyDefaultMethodTarget; import static org.grails.compiler.injection.GrailsASTUtils.applyMethodTarget; import static org.grails.compiler.injection.GrailsASTUtils.buildGetMapExpression; @@ -195,7 +186,7 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, ClassHelper.Boolean_TYPE, "boolean", ClassHelper.Byte_TYPE, "byte", ClassHelper.Character_TYPE, "char"); - private static final List<ClassNode> PRIMITIVE_CLASS_NODES = CollectionUtils.newList( + private static List<ClassNode> PRIMITIVE_CLASS_NODES = CollectionUtils.<ClassNode>newList( ClassHelper.boolean_TYPE, ClassHelper.char_TYPE, ClassHelper.int_TYPE, @@ -208,7 +199,7 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, public static final String CONVERT_CLOSURES_KEY = "grails.compile.artefacts.closures.convert"; - private final Boolean converterEnabled; + private Boolean converterEnabled; private CompilationUnit compilationUnit; public ControllerActionTransformer() { @@ -243,7 +234,7 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, private boolean isExceptionHandlingMethod(MethodNode methodNode) { boolean isExceptionHandler = false; - if (!methodNode.isPrivate() && !methodNode.getName().contains("$")) { + if(!methodNode.isPrivate() && methodNode.getName().indexOf("$") == -1) { Parameter[] parameters = methodNode.getParameters(); if(parameters.length == 1) { ClassNode parameterTypeClassNode = parameters[0].getType(); @@ -258,7 +249,7 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, private void processMethods(ClassNode classNode, SourceUnit source, GeneratorContext context) { - List<MethodNode> deferredNewMethods = new ArrayList<>(); + List<MethodNode> deferredNewMethods = new ArrayList<MethodNode>(); for (MethodNode method : classNode.getMethods()) { if (methodShouldBeConfiguredAsControllerAction(method)) { final List<MethodNode> declaredMethodsWithThisName = classNode.getDeclaredMethods(method.getName()); @@ -334,7 +325,7 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, } protected Collection<MethodNode> getExceptionHandlerMethods(final ClassNode classNode, SourceUnit sourceUnit) { - final Map<ClassNode, MethodNode> exceptionTypeToHandlerMethodMap = new HashMap<>(); + final Map<ClassNode, MethodNode> exceptionTypeToHandlerMethodMap = new HashMap<ClassNode, MethodNode>(); final List<MethodNode> methods = classNode.getMethods(); for(MethodNode methodNode : methods) { if(isExceptionHandlingMethod(methodNode)) { @@ -456,7 +447,7 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, private void processClosures(ClassNode classNode, SourceUnit source, GeneratorContext context) { - List<PropertyNode> propertyNodes = new ArrayList<>(classNode.getProperties()); + List<PropertyNode> propertyNodes = new ArrayList<PropertyNode>(classNode.getProperties()); Expression initialExpression; ClosureExpression closureAction; @@ -531,12 +522,14 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, if(allowedMethodsField != null) { final Expression initialAllowedMethodsExpression = allowedMethodsField.getInitialExpression(); - if (initialAllowedMethodsExpression instanceof MapExpression allowedMethodsMapExpression) { + if(initialAllowedMethodsExpression instanceof MapExpression) { boolean actionIsRestricted = false; + final MapExpression allowedMethodsMapExpression = (MapExpression) initialAllowedMethodsExpression; final List<MapEntryExpression> allowedMethodsMapEntryExpressions = allowedMethodsMapExpression.getMapEntryExpressions(); for(MapEntryExpression allowedMethodsMapEntryExpression : allowedMethodsMapEntryExpressions) { final Expression allowedMethodsMapEntryKeyExpression = allowedMethodsMapEntryExpression.getKeyExpression(); - if (allowedMethodsMapEntryKeyExpression instanceof ConstantExpression allowedMethodsMapKeyConstantExpression) { + if(allowedMethodsMapEntryKeyExpression instanceof ConstantExpression) { + final ConstantExpression allowedMethodsMapKeyConstantExpression = (ConstantExpression) allowedMethodsMapEntryKeyExpression; final Object allowedMethodsMapKeyValue = allowedMethodsMapKeyConstantExpression.getValue(); if(methodName.equals(allowedMethodsMapKeyValue)) { actionIsRestricted = true; @@ -732,7 +725,7 @@ public class ControllerActionTransformer implements GrailsArtefactClassInjector, Parameter[] parameters = methods.get(0).getParameters(); //Look for a parameter of index (argX) in the method. //The $self is the first parameter, so arg1 == index of 1 - int argNum = Integer.parseInt(paramName.replaceFirst("arg", "")); + int argNum = Integer.valueOf(paramName.replaceFirst("arg", "")); if (parameters.length >= argNum + 1) { Parameter helperParam = parameters[argNum]; //Set the request parameter name based off of the parameter in the trait helper method diff --git a/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java b/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java index 0dc3cb0746..4222206163 100644 --- a/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java +++ b/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java @@ -1,36 +1,39 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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 grails.plugins; -import grails.core.GrailsApplication; import grails.util.Environment; import groovy.lang.GroovyObject; -import org.grails.plugins.support.WatchPattern; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import grails.core.GrailsApplication; import org.grails.spring.RuntimeSpringConfiguration; +import org.grails.plugins.support.WatchPattern; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.env.PropertySource; import org.springframework.core.io.Resource; import org.springframework.core.type.filter.TypeFilter; -import java.util.Collection; -import java.util.List; -import java.util.Map; - /** * <p>Plugin interface that adds Spring {@link org.springframework.beans.factory.config.BeanDefinition}s * to a registry based on a {@link GrailsApplication} object. After all <code>GrailsPlugin</code> classes @@ -211,6 +214,14 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail */ boolean supportsCurrentScopeAndEnvironment(); + /** + * Write some documentation to the DocumentationContext + * @deprecated Dynamic document generation no longer supported + * @param text + */ + @Deprecated + void doc(String text); + /** * Returns the path of the plug-in * diff --git a/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy b/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy index 1ed039edd4..3e1b73351e 100644 --- a/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy +++ b/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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 grails.util @@ -28,7 +30,7 @@ import java.util.regex.Pattern * @since 2.3.6 */ @CompileStatic -abstract class GrailsStringUtils extends StringUtils { +abstract class GrailsStringUtils extends StringUtils{ private static final Pattern BOOLEAN_PATTERN = Pattern.compile(/^on$|^true$|^yes$|^1$/, Pattern.CASE_INSENSITIVE) diff --git a/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java b/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java index c7b5823ac0..8e9a1f93fd 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java +++ b/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java @@ -1,48 +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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.plugins; -import grails.core.ArtefactHandler; -import grails.core.GrailsApplication; -import grails.core.support.GrailsApplicationAware; -import grails.core.support.ParentApplicationContextAware; import grails.plugins.GrailsPlugin; import grails.plugins.GrailsPluginManager; import grails.plugins.Plugin; -import grails.plugins.exceptions.PluginException; import grails.spring.BeanBuilder; import grails.util.CollectionUtils; import grails.util.Environment; -import grails.util.GrailsArrayUtils; -import grails.util.GrailsClassUtils; import grails.util.GrailsUtil; -import groovy.lang.Binding; -import groovy.lang.Closure; -import groovy.lang.GroovyClassLoader; -import groovy.lang.GroovyObject; -import groovy.lang.MetaClass; +import groovy.lang.*; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; +import grails.core.ArtefactHandler; +import grails.core.GrailsApplication; +import grails.util.GrailsArrayUtils; +import grails.util.GrailsClassUtils; import org.grails.core.io.CachingPathMatchingResourcePatternResolver; import org.grails.core.io.SpringResource; +import org.grails.spring.RuntimeSpringConfiguration; +import grails.plugins.exceptions.PluginException; import org.grails.plugins.support.WatchPattern; import org.grails.plugins.support.WatchPatternParser; -import org.grails.spring.RuntimeSpringConfiguration; +import grails.core.support.GrailsApplicationAware; +import grails.core.support.ParentApplicationContextAware; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.BeansException; @@ -57,19 +68,6 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.type.filter.TypeFilter; -import java.io.File; -import java.io.IOException; -import java.io.Serial; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - /** * Implementation of the GrailsPlugin interface that wraps a Groovy plugin class * and provides the magic to invoke its various methods from Java. @@ -107,8 +105,8 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA private Class<?>[] providedArtefacts = {}; private Collection profiles = null; private Map pluginEnvs; - private List<String> pluginExcludes = new ArrayList<>(); - private Collection<? extends TypeFilter> typeFilters = new ArrayList<>(); + private List<String> pluginExcludes = new ArrayList<String>(); + private Collection<? extends TypeFilter> typeFilters = new ArrayList<TypeFilter>(); private Resource pluginDescriptor; private List<WatchPattern> watchedResourcePatterns; @@ -176,7 +174,8 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA private void initialisePlugin(Class<?> clazz) { pluginGrailsClass = new GrailsPluginClass(clazz); plugin = (GroovyObject)pluginGrailsClass.newInstance(); - if (plugin instanceof Plugin p) { + if(plugin instanceof Plugin) { + Plugin p = (Plugin)plugin; p.setApplicationContext(applicationContext); p.setPlugin(this); p.setGrailsApplication(grailsApplication); @@ -220,7 +219,6 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA private void evaluatePluginScopes() { // Damn I wish Java had closures pluginEnvs = evaluateIncludeExcludeProperty(ENVIRONMENTS, new Closure(this) { - @Serial private static final long serialVersionUID = 1; @Override public Object call(Object arguments) { @@ -235,7 +233,8 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA private Map evaluateIncludeExcludeProperty(String name, Closure converter) { Map resultMap = new HashMap(); Object propertyValue = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, name); - if (propertyValue instanceof Map containedMap) { + if (propertyValue instanceof Map) { + Map containedMap = (Map)propertyValue; Object includes = containedMap.get(INCLUDES); evaluateAndAddIncludeExcludeObject(resultMap, includes, true, converter); @@ -250,16 +249,20 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA } private void evaluateAndAddIncludeExcludeObject(Map targetMap, Object includeExcludeObject, boolean include, Closure converter) { - if (includeExcludeObject instanceof String includeExcludeString) { + if (includeExcludeObject instanceof String) { + final String includeExcludeString = (String) includeExcludeObject; evaluateAndAddToIncludeExcludeSet(targetMap,includeExcludeString, include, converter); - } else if (includeExcludeObject instanceof List includeExcludeList) { + } + else if (includeExcludeObject instanceof List) { + List includeExcludeList = (List) includeExcludeObject; evaluateAndAddListOfValues(targetMap,includeExcludeList, include, converter); } } private void evaluateAndAddListOfValues(Map targetMap, List includeExcludeList, boolean include, Closure converter) { for (Object value : includeExcludeList) { - if (value instanceof String scopeName) { + if (value instanceof String) { + final String scopeName = (String) value; evaluateAndAddToIncludeExcludeSet(targetMap, scopeName, include, converter); } } @@ -285,8 +288,9 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA @SuppressWarnings("unchecked") private void evaluateProvidedArtefacts() { Object result = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, PROVIDED_ARTEFACTS); - if (result instanceof Collection artefactList) { - providedArtefacts = (Class<?>[]) artefactList.toArray(new Class[0]); + if (result instanceof Collection) { + final Collection artefactList = (Collection) result; + providedArtefacts = (Class<?>[])artefactList.toArray(new Class[artefactList.size()]); } } @@ -305,7 +309,8 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA private void evaluateObservedPlugins() { if (pluginBean.isReadableProperty(OBSERVE)) { Object observeProperty = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, OBSERVE); - if (observeProperty instanceof Collection observeList) { + if (observeProperty instanceof Collection) { + Collection observeList = (Collection)observeProperty; observedPlugins = new String[observeList.size()]; int j = 0; for (Object anObserveList : observeList) { @@ -342,7 +347,7 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA } Environment env = Environment.getCurrent(); - final boolean warDeployed = Environment.isWarDeployed(); + final boolean warDeployed = env.isWarDeployed(); final boolean reloadEnabled = env.isReloadEnabled(); if (!((reloadEnabled || !warDeployed))) { @@ -367,7 +372,7 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA return; } - List<String> resourceListTmp = new ArrayList<>(); + List<String> resourceListTmp = new ArrayList<String>(); final String baseLocation = env.getReloadLocation(); for (Object ref : resourceList) { @@ -448,13 +453,13 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA if (pluginBean.isReadableProperty(PLUGIN_LOAD_AFTER_NAMES)) { List loadAfterNamesList = (List) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, PLUGIN_LOAD_AFTER_NAMES); if (loadAfterNamesList != null) { - loadAfterNames = (String[]) loadAfterNamesList.toArray(new String[0]); + loadAfterNames = (String[])loadAfterNamesList.toArray(new String[loadAfterNamesList.size()]); } } if (pluginBean.isReadableProperty(PLUGIN_LOAD_BEFORE_NAMES)) { List loadBeforeNamesList = (List) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, PLUGIN_LOAD_BEFORE_NAMES); if (loadBeforeNamesList != null) { - loadBeforeNames = (String[]) loadBeforeNamesList.toArray(new String[0]); + loadBeforeNames = (String[])loadBeforeNamesList.toArray(new String[loadBeforeNamesList.size()]); } } } @@ -466,7 +471,7 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA } dependencies = (Map) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, DEPENDS_ON); - dependencyNames = dependencies.keySet().toArray(new String[0]); + dependencyNames = dependencies.keySet().toArray(new String[dependencies.size()]); } @Override @@ -497,7 +502,9 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA } public void doWithApplicationContext(ApplicationContext ctx) { - if (plugin instanceof Plugin pluginObject) { + if(plugin instanceof Plugin) { + Plugin pluginObject = (Plugin) plugin; + pluginObject.setApplicationContext(ctx); pluginObject.doWithApplicationContext(); } @@ -600,6 +607,15 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA return !(excludes != null && excludes.contains(value)); } + /** + * @deprecated Dynamic document generation no longer supported + * @param text + */ + @Deprecated + public void doc(String text) { + // no-op + } + @Override public String[] getDependencyNames() { return dependencyNames; @@ -779,12 +795,13 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA onChangeListener.setDelegate(this); onChangeListener.call(new Object[]{event}); - if (!(applicationContext instanceof GenericApplicationContext ctx)) { + if (!(applicationContext instanceof GenericApplicationContext)) { return; } // Apply any factory post processors in case the change listener has changed any // bean definitions (GRAILS-5763) + GenericApplicationContext ctx = (GenericApplicationContext) applicationContext; ConfigurableListableBeanFactory beanFactory = ctx.getBeanFactory(); for (BeanFactoryPostProcessor postProcessor : ctx.getBeanFactoryPostProcessors()) { try { @@ -810,7 +827,8 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA l = (List)plugin.getProperty(ARTEFACTS); } for (Object artefact : l) { - if (artefact instanceof Class artefactClass) { + if (artefact instanceof Class) { + Class artefactClass = (Class) artefact; if (ArtefactHandler.class.isAssignableFrom(artefactClass)) { try { grailsApplication.registerArtefactHandler((ArtefactHandler) artefactClass.newInstance()); diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java index 873948e900..df4fb5f60e 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java @@ -1,29 +1,33 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.buffer; import groovy.lang.GroovyObject; import groovy.lang.MetaClass; import groovy.lang.Writable; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.runtime.GStringImpl; -import org.codehaus.groovy.runtime.InvokerHelper; -import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; import org.grails.charsequences.CharSequences; import org.grails.encoder.EncodedAppender; import org.grails.encoder.EncodedAppenderFactory; @@ -33,10 +37,9 @@ import org.grails.encoder.Encoder; import org.grails.encoder.EncodingStateRegistry; import org.grails.encoder.StreamingEncoder; import org.grails.encoder.StreamingEncoderWriter; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; +import org.codehaus.groovy.runtime.GStringImpl; +import org.codehaus.groovy.runtime.InvokerHelper; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; /** * PrintWriter implementation that doesn't have synchronization. null object @@ -46,7 +49,7 @@ import java.io.Writer; */ public class GrailsPrintWriter extends Writer implements GrailsWrappedWriter, EncodedAppenderWriterFactory, GroovyObject { protected static final Log LOG = LogFactory.getLog(GrailsPrintWriter.class); - protected static final char[] CRLF = {'\r', '\n'}; + protected static final char CRLF[] = { '\r', '\n' }; protected boolean trouble = false; protected Writer out; protected boolean allowUnwrappingOut = true; @@ -98,7 +101,7 @@ public class GrailsPrintWriter extends Writer implements GrailsWrappedWriter, En * * @param obj The value * @return Returns this object - * @throws IOException If an I/O error occurs + * @throws IOException */ public GrailsPrintWriter leftShift(Object obj) throws IOException { if (trouble || obj == null) { diff --git a/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java b/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java index 05c5677949..a814e50b7c 100644 --- a/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java +++ b/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.charsequences; @@ -82,7 +84,7 @@ public class CharSequences { * @param csq source CharSequence instance * @param start start/offset index * @param end end index + 1 - * @throws IOException If an I/O error occurs + * @throws IOException */ public static void writeCharSequence(Writer target, CharSequence csq, int start, int end) throws IOException { final Class<?> csqClass = csq.getClass(); diff --git a/grails-gradle/model/src/main/groovy/grails/util/BuildSettings.groovy b/grails-gradle/model/src/main/groovy/grails/util/BuildSettings.groovy index 915d696a93..dd7dd52d89 100644 --- a/grails-gradle/model/src/main/groovy/grails/util/BuildSettings.groovy +++ b/grails-gradle/model/src/main/groovy/grails/util/BuildSettings.groovy @@ -19,6 +19,8 @@ package grails.util import grails.io.IOUtils import groovy.transform.CompileStatic +import java.util.regex.Pattern + /** * Build time settings and configuration * @@ -57,21 +59,118 @@ class BuildSettings { */ public static final String PROFILE_REPOSITORIES = "grails.profiles.repositories" + public static final String BUILD_SCOPE = "build" + public static final String COMPILE_SCOPE = "compileClasspath" + public static final String RUNTIME_SCOPE = "runtimeClasspath" + public static final String TEST_SCOPE = "testCompileClasspath" + public static final String PROVIDED_SCOPE = "provided" + + public static final String BUILD_SCOPE_DESC = "Dependencies for the build system only" + public static final String COMPILE_SCOPE_DESC = "Dependencies placed on the classpath for compilation" + public static final String RUNTIME_SCOPE_DESC = "Dependencies needed at runtime but not for compilation" + public static final String TEST_SCOPE_DESC = "Dependencies needed for test compilation and execution but not at runtime" + public static final String PROVIDED_SCOPE_DESC = "Dependencies needed at development time, but not during deployment" + + public static final Map<String, String> SCOPE_TO_DESC = [ + (BUILD_SCOPE): BUILD_SCOPE_DESC, + (PROVIDED_SCOPE): PROVIDED_SCOPE_DESC, + (COMPILE_SCOPE): COMPILE_SCOPE_DESC, + (RUNTIME_SCOPE): RUNTIME_SCOPE_DESC, + (TEST_SCOPE): TEST_SCOPE_DESC + ] + + public static final Pattern JAR_PATTERN = ~/^\S+\.jar$/ + + /** + * The compiler source level to use + */ + public static final String COMPILER_SOURCE_LEVEL = "grails.project.source.level" + + /** + * The compiler source level to use + */ + public static final String COMPILER_TARGET_LEVEL = "grails.project.target.level" + /** + * The version of the servlet API + */ + public static final String SERVLET_VERSION = "grails.servlet.version" /** * The base directory of the application */ public static final String APP_BASE_DIR = "base.dir" + /** + * The name of the system property for the Grails work directory. + */ + public static final String WORK_DIR = "grails.work.dir" + + /** + * The name of the system property for the project work directory + */ + public static final String PROJECT_WORK_DIR = "grails.project.work.dir" + + public static final String OFFLINE_MODE= "grails.offline.mode" /** * The name of the system property for {@link #}. */ public static final String PROJECT_RESOURCES_DIR = "grails.project.resource.dir" + /** + * The name of the system property for project source directory. Must be set if changed from src/main/groovy + */ + public static final String PROJECT_SOURCE_DIR = "grails.project.source.dir" + /** * The name of the system property for the project classes directory. Must be set if changed from build/main/classes. */ public static final String PROJECT_CLASSES_DIR = "grails.project.class.dir" + /** + * The name of the system property for project test classes directory. Must be set if changed from build/test/classes + */ + public static final String PROJECT_TEST_CLASSES_DIR = "grails.project.test.class.dir" + + /** + * The name of the system property for test reported directory + */ + public static final String PROJECT_TEST_REPORTS_DIR = "grails.project.test.reports.dir" + + /** + * The name of the system property for documentation output directory + */ + public static final String PROJECT_DOCS_OUTPUT_DIR = "grails.project.docs.output.dir" + + /** + * The name of the property specification test locations, must be set of the directory is changed from src/test/groovy + */ + public static final String PROJECT_TEST_SOURCE_DIR = "grails.project.test.source.dir" + + /** + * The name of the system property for the the project target directory. Must be set if Gradle build location is changed. + */ + public static final String PROJECT_TARGET_DIR = "grails.project.target.dir" + + /** + * The name of the WAR file of the project + */ + public static final String PROJECT_WAR_FILE = "grails.project.war.file" + + /** + * The name of the WAR file of the project + */ + public static final String PROJECT_AUTODEPLOY_DIR = "grails.project.autodeploy.dir" + + /** + * A system property with this name is populated in the preparation phase of functional testing + * with the base URL that tests should be run against. + */ + public static final String FUNCTIONAL_BASE_URL_PROPERTY = 'grails.testing.functional.baseUrl' + + /** + * The name of the working directory for commands that don't belong to a project (like create-app) + */ + public static final String CORE_WORKING_DIR_NAME = '.core' + /** * A property name to enable/disable AST conversion of closures actions&tags to methods */ @@ -99,6 +198,7 @@ class BuildSettings { * The classes directory of the project, null outside of the development environment */ public static final File CLASSES_DIR + public static final String RUN_EXECUTED = "grails.run.executed" /** * The path to the build classes directory @@ -119,6 +219,13 @@ class BuildSettings { BuildSettings.package.implementationVersion } + /** + * @return Whether the current version of Grails being used is a development version + */ + static boolean isDevelopmentGrailsVersion() { + BuildSettings.package.implementationVersion.endsWith('-SNAPSHOT') + } + static { boolean grailsAppDirPresent = new File( "grails-app").exists() || new File( "Application.groovy").exists() if(!grailsAppDirPresent) { diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java index 205d26aeb8..fc107c6acf 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.gsp; @@ -35,11 +37,7 @@ import org.grails.core.artefact.DomainClassArtefactHandler; import org.grails.core.exceptions.DefaultErrorsPrinter; import org.grails.exceptions.ExceptionUtils; import org.grails.gsp.compiler.GroovyPageParser; -import org.grails.gsp.io.DefaultGroovyPageLocator; -import org.grails.gsp.io.GroovyPageCompiledScriptSource; -import org.grails.gsp.io.GroovyPageLocator; -import org.grails.gsp.io.GroovyPageResourceScriptSource; -import org.grails.gsp.io.GroovyPageScriptSource; +import org.grails.gsp.io.*; import org.grails.gsp.jsp.TagLibraryResolver; import org.grails.taglib.TagLibraryLookup; import org.springframework.beans.BeansException; @@ -48,11 +46,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.io.UrlResource; +import org.springframework.core.io.*; import org.springframework.scripting.ScriptSource; import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.util.Assert; @@ -61,12 +55,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.security.PrivilegedAction; +import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -75,7 +65,7 @@ import java.util.concurrent.atomic.AtomicInteger; /** * Based on (but not extending) the existing TemplateEngine implementations * within Groovy. It allows GSP pages to be re-used in different context using code like the below: - * <p> + * * <code> * Template t = new GroovyPagesTemplateEngine() * .createTemplate(context,request,response); @@ -98,9 +88,9 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple private static final Log LOG = LogFactory.getLog(GroovyPagesTemplateEngine.class); private static File dumpLineNumbersTo; - private final ConcurrentMap<String, CacheEntry<GroovyPageMetaInfo>> pageCache = new ConcurrentHashMap<>(); + private ConcurrentMap<String, CacheEntry<GroovyPageMetaInfo>> pageCache = new ConcurrentHashMap<String, CacheEntry<GroovyPageMetaInfo>>(); private ClassLoader classLoader; - private final AtomicInteger scriptNameCount = new AtomicInteger(0); + private AtomicInteger scriptNameCount=new AtomicInteger(0); private GroovyPageLocator groovyPageLocator = new DefaultGroovyPageLocator(); @@ -113,7 +103,7 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple private GrailsApplication grailsApplication; private Map<String, Class<?>> cachedDomainsWithoutPackage; - private List<GroovyPageSourceDecorator> groovyPageSourceDecorators = new ArrayList<>(); + private List<GroovyPageSourceDecorator> groovyPageSourceDecorators = new ArrayList(); static { String dirPath = System.getProperty("grails.dump.gsp.line.numbers.to.dir"); @@ -316,7 +306,7 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple * * @param uri The URI of the page to create the template for * @return The Template instance - * @throws CompilationFailedException if the gsp compilation fails + * @throws CompilationFailedException */ @Override public Template createTemplate(String uri) { @@ -336,12 +326,14 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple } private GroovyPageMetaInfo initializeCompiledMetaInfo(GroovyPageMetaInfo meta) { - meta.initializeOnDemand(metaInfo -> { - metaInfo.setGrailsApplication(grailsApplication); - metaInfo.setJspTagLibraryResolver(jspTagLibraryResolver); - metaInfo.setTagLibraryLookup(tagLibraryLookup); - metaInfo.initialize(); - GroovyPagesMetaUtils.registerMethodMissingForGSP(metaInfo.getPageClass(), tagLibraryLookup); + meta.initializeOnDemand(new GroovyPageMetaInfo.GroovyPageMetaInfoInitializer() { + public void initialize(GroovyPageMetaInfo metaInfo) { + metaInfo.setGrailsApplication(grailsApplication); + metaInfo.setJspTagLibraryResolver(jspTagLibraryResolver); + metaInfo.setTagLibraryLookup(tagLibraryLookup); + metaInfo.initialize(); + GroovyPagesMetaUtils.registerMethodMissingForGSP(metaInfo.getPageClass(), tagLibraryLookup); + } }); return meta; } @@ -379,7 +371,8 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple return createTemplateFromPrecompiled((GroovyPageCompiledScriptSource) scriptSource); } - if (scriptSource instanceof ResourceScriptSource resourceSource) { + if (scriptSource instanceof ResourceScriptSource) { + ResourceScriptSource resourceSource = (ResourceScriptSource) scriptSource; Resource resource = resourceSource.getResource(); return createTemplate(resource, true); } @@ -399,14 +392,14 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple * @param pageName The name of the page being parsed * * @return The Template instance - * @throws CompilationFailedException if gsp template compilation fails + * @throws CompilationFailedException * @throws IOException Thrown if an IO exception occurs creating the Template */ public Template createTemplate(String txt, String pageName) throws IOException { Assert.hasLength(txt, "Argument [txt] cannot be null or blank"); Assert.hasLength(pageName, "Argument [pageName] cannot be null or blank"); - return createTemplate(new ByteArrayResource(txt.getBytes(StandardCharsets.UTF_8), pageName), pageName, pageName != null); + return createTemplate(new ByteArrayResource(txt.getBytes("UTF-8"), pageName), pageName, pageName != null); } /** @@ -451,9 +444,13 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple } protected GroovyPageMetaInfo buildPageMetaInfo(Resource resource, String pageName) throws IOException { - try (InputStream inputStream = resource.getInputStream()) { + InputStream inputStream = resource.getInputStream(); + try { return buildPageMetaInfo(inputStream, resource, pageName); } + finally { + inputStream.close(); + } } private StringBuilder decorateGroovyPageSource(StringBuilder source) throws IOException { @@ -471,7 +468,11 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple * @return true if it is reloadable */ private boolean isGroovyPageReloadable(final Resource resource, GroovyPageMetaInfo meta) { - return isReloadEnabled() && meta.shouldReload(() -> resource); + return isReloadEnabled() && meta.shouldReload(new PrivilegedAction<Resource>() { + public Resource run() { + return resource; + } + }); } /** @@ -500,7 +501,7 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple */ public Resource getResourceForUri(String uri) { GroovyPageScriptSource scriptSource = getResourceWithinContext(uri); - if ((scriptSource instanceof GroovyPageResourceScriptSource)) { + if (scriptSource != null && (scriptSource instanceof GroovyPageResourceScriptSource)) { return ((GroovyPageResourceScriptSource)scriptSource).getResource(); } return null; @@ -508,7 +509,11 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple private GroovyPageScriptSource getResourceWithinContext(String uri) { Assert.state(groovyPageLocator != null, "TemplateEngine not initialised correctly, no [groovyPageLocator] specified!"); - return groovyPageLocator.findPage(uri); + GroovyPageScriptSource scriptSource = groovyPageLocator.findPage(uri); + if (scriptSource != null) { + return scriptSource; + } + return null; } /** @@ -682,7 +687,11 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple // a word character or a digit with an underscore if (name.startsWith("/")) name = name.substring(1); return name.replaceAll("[^\\w\\d]", "_"); - } catch (IllegalStateException | IOException e) { + } + catch (IllegalStateException e) { + return generateTemplateName(); + } + catch (IOException ioex) { return generateTemplateName(); } } @@ -772,12 +781,12 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple /** * The domainClassMap is used in GSP binding to "auto-import" domain classes in packages without package prefix. * real imports aren't used, instead each class is added to the binding - * <p> + * * This feature has existed earlier, the code has just been refactored and moved to GroovyPagesTemplateEngine * to prevent using the static cache that was used previously. */ private Map<String, Class<?>> createDomainClassMap() { - Map<String, Class<?>> domainsWithoutPackage = new HashMap<>(); + Map<String, Class<?>> domainsWithoutPackage = new HashMap<String, Class<?>>(); if (grailsApplication != null) { GrailsClass[] domainClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE); for (GrailsClass domainClass : domainClasses) { diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy b/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy index 574050f24b..2194a9c4c2 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.gsp @@ -39,8 +41,12 @@ import java.util.concurrent.ConcurrentHashMap */ @CompileStatic abstract class ModelRecordingGroovyPage extends GroovyPage { - public static final String CONFIG_SYSTEM_PROPERTY_NAME = "grails.views.gsp.modelrecording" - public static final boolean ENABLED = Boolean.getBoolean(CONFIG_SYSTEM_PROPERTY_NAME) + public static final String CONFIG_SYSTEM_PROPERTY_NAME + public static final boolean ENABLED + static { + CONFIG_SYSTEM_PROPERTY_NAME = "grails.views.gsp.modelrecording" + ENABLED = Boolean.getBoolean(CONFIG_SYSTEM_PROPERTY_NAME) + } private static final ModelRecordingCache modelRecordingCache = new ModelRecordingCache() private ModelEntry modelEntry @@ -186,7 +192,7 @@ class ModelEntry { if (defaultTypeClass.isAssignableFrom(fieldTypeClass)) { cleanedFieldType = defaultType } - } catch (ignored) { + } catch (e) { // ignore } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java index 693e853b99..0a5bf32c47 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java @@ -1,30 +1,26 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.taglib; import groovy.lang.Binding; -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Abstract super class for GroovyPage bindings @@ -181,7 +177,7 @@ public abstract class AbstractTemplateVariableBinding extends Binding { } protected static class BindingMapEntry implements Map.Entry { - private final AbstractTemplateVariableBinding binding; + private AbstractTemplateVariableBinding binding; private Object key; private Object value; @@ -215,9 +211,10 @@ public abstract class AbstractTemplateVariableBinding extends Binding { if (obj == this) { return true; } - if (!(obj instanceof Map.Entry other)) { + if (!(obj instanceof Map.Entry)) { return false; } + Map.Entry other = (Map.Entry) obj; return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue())); diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java index dd3bc84c93..49832d5c17 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java +++ b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.web.gsp; @@ -50,7 +52,6 @@ import org.springframework.util.ReflectionUtils; import java.io.IOException; import java.io.Writer; import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; @@ -61,7 +62,7 @@ import java.util.concurrent.ConcurrentMap; /** * Service that provides the actual implementation to RenderTagLib's render tag. - * <p> + * * This is an internal Grails service and should not be used by plugins directly. * The implementation was moved from RenderTagLib, ported to Java and then refactored. * @@ -73,7 +74,7 @@ import java.util.concurrent.ConcurrentMap; public class GroovyPagesTemplateRenderer implements InitializingBean { private GrailsConventionGroovyPageLocator groovyPageLocator; private GroovyPagesTemplateEngine groovyPagesTemplateEngine; - private final ConcurrentMap<String, CacheEntry<Template>> templateCache = new ConcurrentHashMap<>(); + private ConcurrentMap<String,CacheEntry<Template>> templateCache = new ConcurrentHashMap<String,CacheEntry<Template>>(); private Object scaffoldingTemplateGenerator; private Map<String, Collection<String>> scaffoldedActionMap; private Map<String, GrailsDomainClass> controllerToScaffoldedDomainClassMap; @@ -157,23 +158,23 @@ public class GroovyPagesTemplateRenderer implements InitializingBean { return CacheEntry.getValue(templateCache, cacheKey, reloadEnabled ? GroovyPageMetaInfo.LASTMODIFIED_CHECK_INTERVAL : -1, null, new Callable<CacheEntry<Template>>() { public CacheEntry<Template> call() { - return new CacheEntry<>() { + return new CacheEntry<Template>() { boolean allowCaching = cacheEnabled; boolean neverExpire = false; @Override protected boolean hasExpired(long timeout, Object cacheRequestObject) { - return !neverExpire && (!allowCaching || super.hasExpired(timeout, cacheRequestObject)); + return neverExpire ? false : (allowCaching ? super.hasExpired(timeout, cacheRequestObject) : true); } - + @Override public boolean isInitialized() { - return allowCaching && super.isInitialized(); + return allowCaching ? super.isInitialized() : false; } - + @Override public void setValue(Template val) { - if (allowCaching) { + if(allowCaching) { super.setValue(val); } } @@ -229,7 +230,8 @@ public class GroovyPagesTemplateRenderer implements InitializingBean { if (key == null && GrailsStringUtils.isBlank(var) && it != null) { key = GrailsNameUtils.getPropertyName(it.getClass()); } - Map itmap = new LinkedHashMap<String, Object>(b); + Map itmap = new LinkedHashMap<String, Object>(); + itmap.putAll(b); if (GrailsStringUtils.isNotBlank(var)) { itmap.put(var, it); } @@ -280,7 +282,7 @@ public class GroovyPagesTemplateRenderer implements InitializingBean { } FastStringWriter sw = new FastStringWriter(); ReflectionUtils.invokeMethod(generateViewMethod, scaffoldingTemplateGenerator, domainClass, scaffoldedtemplateName, sw); - t = groovyPagesTemplateEngine.createTemplate(new ByteArrayResource(sw.toString().getBytes(StandardCharsets.UTF_8), uri), false); + t = groovyPagesTemplateEngine.createTemplate(new ByteArrayResource(sw.toString().getBytes("UTF-8"), uri), false); } } return t; diff --git a/grails-gsp/grails-web-jsp/src/main/groovy/org/grails/gsp/jsp/GroovyPagesPageContext.java b/grails-gsp/grails-web-jsp/src/main/groovy/org/grails/gsp/jsp/GroovyPagesPageContext.java index fd30f737d9..7c762ba45d 100644 --- a/grails-gsp/grails-web-jsp/src/main/groovy/org/grails/gsp/jsp/GroovyPagesPageContext.java +++ b/grails-gsp/grails-web-jsp/src/main/groovy/org/grails/gsp/jsp/GroovyPagesPageContext.java @@ -1,38 +1,30 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.gsp.jsp; import groovy.lang.Binding; import jakarta.el.ELContext; -import jakarta.servlet.GenericServlet; -import jakarta.servlet.Servlet; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; +import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import jakarta.servlet.jsp.JspApplicationContext; -import jakarta.servlet.jsp.JspContext; -import jakarta.servlet.jsp.JspFactory; -import jakarta.servlet.jsp.JspWriter; -import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.*; import jakarta.servlet.jsp.tagext.BodyContent; import org.grails.gsp.GroovyPage; import org.grails.web.servlet.mvc.GrailsWebRequest; @@ -41,14 +33,7 @@ import org.springframework.web.context.request.RequestContextHolder; import java.io.IOException; import java.io.Writer; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.Enumeration; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.NoSuchElementException; +import java.util.*; /** * A JSP PageContext implementation for use with GSP. @@ -107,7 +92,7 @@ public class GroovyPagesPageContext extends PageContext { void popWriter() { outStack.pop(); - jspOut = outStack.peek(); + jspOut = (JspWriter) outStack.peek(); setCurrentOut(); } @@ -285,13 +270,13 @@ public class GroovyPagesPageContext extends PageContext { public Object getAttribute(String name, int scope) { Assert.notNull(name, "Attribute name cannot be null"); - return switch (scope) { - case PAGE_SCOPE -> getAttribute(name); - case REQUEST_SCOPE -> request.getAttribute(name); - case SESSION_SCOPE -> request.getSession(true).getAttribute(name); - case APPLICATION_SCOPE -> servletContext.getAttribute(name); - default -> getAttribute(name); - }; + switch (scope) { + case PAGE_SCOPE: return getAttribute(name); + case REQUEST_SCOPE: return request.getAttribute(name); + case SESSION_SCOPE: return request.getSession(true).getAttribute(name); + case APPLICATION_SCOPE: return servletContext.getAttribute(name); + default: return getAttribute(name); + } } @Override diff --git a/grails-web-common/src/main/groovy/org/grails/web/json/JSONObject.java b/grails-web-common/src/main/groovy/org/grails/web/json/JSONObject.java index 01782094ec..e7e554c852 100644 --- a/grails-web-common/src/main/groovy/org/grails/web/json/JSONObject.java +++ b/grails-web-common/src/main/groovy/org/grails/web/json/JSONObject.java @@ -30,12 +30,7 @@ import org.springframework.util.ClassUtils; import java.io.IOException; import java.io.Writer; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * A JSONObject is an unordered collection of name/value pairs. Its @@ -97,7 +92,7 @@ public class JSONObject implements JSONElement, Map { private static boolean useStreamingJavascriptEncoder=false; static { try { - javascriptEncoder = (StreamingEncoder) ClassUtils.forName("grails.encoders.JSONEncoder", JSONObject.class.getClassLoader()).getDeclaredConstructor().newInstance(); + javascriptEncoder = (StreamingEncoder)ClassUtils.forName("grails.encoders.JSONEncoder", JSONObject.class.getClassLoader()).newInstance(); javascriptEncoderStateless = (EncodesToWriter)javascriptEncoder; useStreamingJavascriptEncoder = true; } @@ -109,7 +104,7 @@ public class JSONObject implements JSONElement, Map { /** * The hash map where the JSONObject's properties are kept. */ - private final HashMap myHashMap; + private HashMap myHashMap; /** * Construct an empty JSONObject. @@ -130,8 +125,8 @@ public class JSONObject implements JSONElement, Map { */ public JSONObject(JSONObject jo, String[] sa) throws JSONException { this(); - for (String s : sa) { - putOpt(s, jo.opt(s)); + for (int i = 0; i < sa.length; i += 1) { + putOpt(sa[i], jo.opt(sa[i])); } } @@ -446,7 +441,7 @@ public class JSONObject implements JSONElement, Map { while (keys.hasNext()) { ja.put(keys.next()); } - return ja.isEmpty() ? null : ja; + return ja.length() == 0 ? null : ja; } /** @@ -484,11 +479,12 @@ public class JSONObject implements JSONElement, Map { static public String collectionToString(Collection c) { StringBuilder sb = new StringBuilder("["); boolean first = true; - for (Object o : c) { + Iterator iterator = c.iterator(); + while(iterator.hasNext()) { if (!first) { sb.append(','); } - sb.append(valueToString(o)); + sb.append(valueToString(iterator.next())); first = false; } sb.append("]"); @@ -566,7 +562,7 @@ public class JSONObject implements JSONElement, Map { try { Object o = opt(key); return o instanceof Number ? ((Number) o).doubleValue() : - Double.parseDouble((String) o); + Double.valueOf((String) o); } catch (Exception e) { return defaultValue; } @@ -805,7 +801,7 @@ public class JSONObject implements JSONElement, Map { * @return A String correctly formatted for insertion in a JSON text. */ public static String quote(String string) { - if (string == null || string.isEmpty()) { + if (string == null || string.length() == 0) { return "\"\""; } @@ -850,7 +846,7 @@ public class JSONObject implements JSONElement, Map { default: if (c < ' ') { t = "000" + Integer.toHexString(c); - sb.append("\\u").append(t.substring(t.length() - 4)); + sb.append("\\u" + t.substring(t.length() - 4)); } else { sb.append(c); } @@ -904,7 +900,7 @@ public class JSONObject implements JSONElement, Map { * @throws JSONException If any of the values are non-finite numbers. */ public JSONArray toJSONArray(JSONArray names) throws JSONException { - if (names == null || names.isEmpty()) { + if (names == null || names.length() == 0) { return null; } JSONArray ja = new JSONArray(); @@ -1038,7 +1034,7 @@ public class JSONObject implements JSONElement, Map { * @throws JSONException If the value is or contains an invalid number. */ static String valueToString(Object value) throws JSONException { - if (value == null) { + if (value == null || value.equals(null)) { return "null"; } if (value instanceof Number) { @@ -1057,7 +1053,7 @@ public class JSONObject implements JSONElement, Map { } static void writeValue(Writer writer, Object value) throws IOException { - if (value == null) { + if (value == null || value.equals(null)) { writer.write("null"); } else if (value instanceof Number) { writeNumber(writer, (Number) value); @@ -1124,7 +1120,7 @@ public class JSONObject implements JSONElement, Map { */ static String valueToString(Object value, int indentFactor, int indent) throws JSONException { - if (value == null) { + if (value == null || value.equals(null)) { return "null"; } if (value instanceof Number) { @@ -1153,14 +1149,14 @@ public class JSONObject implements JSONElement, Map { * Warning: This method assumes that the data structure is acyclical. * * @return The writer. - * @throws JSONException if an I/O exception occurs using the writer + * @throws JSONException */ public Writer write(Writer writer) throws JSONException { try { boolean notFirst = false; writer.write('{'); - for (Object o : myHashMap.entrySet()) { - Entry entry = (Entry) o; + for(Iterator it = myHashMap.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = (Entry)it.next(); if (notFirst) { writer.write(','); } @@ -1231,7 +1227,9 @@ public class JSONObject implements JSONElement, Map { JSONObject that = (JSONObject) o; - return myHashMap != null ? myHashMap.equals(that.myHashMap) : that.myHashMap == null; + if (myHashMap != null ? !myHashMap.equals(that.myHashMap) : that.myHashMap != null) return false; + + return true; } @Override diff --git a/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java b/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java index 76fbe0523f..04916cf41e 100644 --- a/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java +++ b/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java @@ -1,26 +1,30 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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 grails.web.servlet.context; -import grails.core.GrailsApplication; import grails.spring.BeanBuilder; -import grails.web.servlet.context.support.GrailsEnvironment; + import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletContext; + +import grails.core.GrailsApplication; +import grails.web.servlet.context.support.GrailsEnvironment; import org.grails.spring.GrailsApplicationContext; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -174,11 +178,13 @@ public class GrailsWebApplicationContext extends GrailsApplicationContext @Override protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { - for (String configLocation : configLocations) { - BeanBuilder beanBuilder = new BeanBuilder(getParent(), getClassLoader()); - final ServletContextResource resource = new ServletContextResource(getServletContext(), configLocation); - beanBuilder.loadBeans(resource); - beanBuilder.registerBeans(this); + if (configLocations.length > 0) { + for (String configLocation : configLocations) { + BeanBuilder beanBuilder = new BeanBuilder(getParent(),getClassLoader()); + final ServletContextResource resource = new ServletContextResource(getServletContext(), configLocation); + beanBuilder.loadBeans(resource); + beanBuilder.registerBeans(this); + } } super.prepareBeanFactory(beanFactory); } diff --git a/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java b/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java index 76d078b312..f45424747a 100644 --- a/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java +++ b/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java @@ -1,34 +1,44 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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 grails.web.databinding; -import grails.core.GrailsApplication; import grails.databinding.CollectionDataBindingSource; import grails.databinding.DataBinder; import grails.databinding.DataBindingSource; import grails.util.Environment; import grails.util.Holders; import grails.validation.ValidationErrors; -import grails.web.mime.MimeType; -import grails.web.mime.MimeTypeResolver; -import grails.web.mime.MimeTypeUtils; import groovy.lang.GroovySystem; import groovy.lang.MetaClass; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + import jakarta.servlet.ServletRequest; + +import grails.core.GrailsApplication; +import grails.web.mime.MimeType; +import grails.web.mime.MimeTypeResolver; +import grails.web.mime.MimeTypeUtils; + import org.grails.core.exceptions.GrailsConfigurationException; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; @@ -43,15 +53,6 @@ import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - /** * Utility methods to perform data binding from Grails objects. * @@ -63,7 +64,7 @@ public class DataBindingUtils { public static final String DATA_BINDER_BEAN_NAME = "grailsWebDataBinder"; private static final String BLANK = ""; - private static final Map<Class, List> CLASS_TO_BINDING_INCLUDE_LIST = new ConcurrentHashMap<>(); + private static final Map<Class, List> CLASS_TO_BINDING_INCLUDE_LIST = new ConcurrentHashMap<Class, List>(); /** * Associations both sides of any bidirectional relationships found in the object and source map to bind @@ -84,7 +85,7 @@ public class DataBindingUtils { } PersistentProperty prop = persistentEntity.getPropertyByName(propertyName); - if (prop instanceof OneToOne && ((OneToOne) prop).isBidirectional()) { + if (prop != null && prop instanceof OneToOne && ((OneToOne) prop).isBidirectional()) { Object val = source.get(key); PersistentProperty otherSide = ((OneToOne) prop).getInverseSide(); if (val != null && otherSide != null) { @@ -120,17 +121,19 @@ public class DataBindingUtils { includeList = CLASS_TO_BINDING_INCLUDE_LIST.get(objectClass); } else { final Field whiteListField = objectClass.getDeclaredField(DefaultASTDatabindingHelper.DEFAULT_DATABINDING_WHITELIST); - if ((whiteListField.getModifiers() & Modifier.STATIC) != 0) { - final Object whiteListValue = whiteListField.get(objectClass); - if (whiteListValue instanceof List) { - includeList = (List) whiteListValue; + if (whiteListField != null) { + if ((whiteListField.getModifiers() & Modifier.STATIC) != 0) { + final Object whiteListValue = whiteListField.get(objectClass); + if (whiteListValue instanceof List) { + includeList = (List)whiteListValue; + } } } if (!Environment.getCurrent().isReloadEnabled()) { CLASS_TO_BINDING_INCLUDE_LIST.put(objectClass, includeList); } } - } catch (Exception ignored) { + } catch (Exception e) { } return includeList; } @@ -250,7 +253,8 @@ public class DataBindingUtils { if (entity != null && bindingResult != null) { BindingResult newResult = new ValidationErrors(object); for (Object error : bindingResult.getAllErrors()) { - if (error instanceof FieldError fieldError) { + if (error instanceof FieldError) { + FieldError fieldError = (FieldError)error; final boolean isBlank = BLANK.equals(fieldError.getRejectedValue()); if (!isBlank) { newResult.addError(fieldError); @@ -285,7 +289,8 @@ public class DataBindingUtils { protected static String[] getMessageCodes(String messageCode, Class objectType) { - return new String[]{objectType.getName() + "." + messageCode, messageCode}; + String[] codes = {objectType.getName() + "." + messageCode, messageCode}; + return codes; } public static DataBindingSourceRegistry getDataBindingSourceRegistry(GrailsApplication grailsApplication) { diff --git a/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java b/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java index 31693e1c35..23c4faa98c 100644 --- a/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java +++ b/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java @@ -1,46 +1,53 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.web.errors; import grails.config.Config; import grails.config.Settings; -import grails.core.GrailsApplication; -import grails.core.support.GrailsApplicationAware; import grails.util.Environment; -import grails.web.mapping.UrlMappingInfo; -import grails.web.mapping.UrlMappingsHolder; -import grails.web.mapping.exceptions.UrlMappingException; + +import java.io.IOException; +import java.util.*; + import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + +import grails.web.mapping.exceptions.UrlMappingException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.control.CompilationFailedException; -import org.codehaus.groovy.runtime.InvokerInvocationException; -import org.grails.core.exceptions.GrailsRuntimeException; -import org.grails.exceptions.ExceptionUtils; +import grails.core.GrailsApplication; import org.grails.exceptions.reporting.DefaultStackTraceFilterer; +import org.grails.core.exceptions.GrailsRuntimeException; import org.grails.exceptions.reporting.StackTraceFilterer; +import grails.core.support.GrailsApplicationAware; +import grails.web.mapping.UrlMappingInfo; +import org.grails.exceptions.ExceptionUtils; import org.grails.web.mapping.DefaultUrlMappingInfo; import org.grails.web.mapping.UrlMappingUtils; -import org.grails.web.servlet.mvc.exceptions.GrailsMVCException; +import grails.web.mapping.UrlMappingsHolder; import org.grails.web.util.GrailsApplicationAttributes; +import org.grails.web.servlet.mvc.exceptions.GrailsMVCException; import org.grails.web.util.WebUtils; +import org.codehaus.groovy.runtime.InvokerInvocationException; import org.springframework.beans.BeanUtils; import org.springframework.web.context.ServletContextAware; import org.springframework.web.servlet.ModelAndView; @@ -48,13 +55,6 @@ import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; -import java.io.IOException; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - /** * Wraps any runtime exceptions with a GrailsWrappedException instance. * @@ -65,7 +65,7 @@ public class GrailsExceptionResolver extends SimpleMappingExceptionResolver impl public static final String EXCEPTION_ATTRIBUTE = WebUtils.EXCEPTION_ATTRIBUTE; protected static final Log LOG = LogFactory.getLog(GrailsExceptionResolver.class); - protected static final String LINE_SEPARATOR = System.lineSeparator(); + protected static final String LINE_SEPARATOR = System.getProperty("line.separator"); protected ServletContext servletContext; protected GrailsApplication grailsApplication; @@ -283,7 +283,7 @@ public class GrailsExceptionResolver extends SimpleMappingExceptionResolver impl if (params.hasMoreElements()) { String param; - String[] values; + String values[]; int i; sb.append(" - parameters:"); diff --git a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java index 147f670474..a98ba3c92a 100644 --- a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java +++ b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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. + * 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.grails.web.mapping; @@ -36,19 +38,10 @@ import org.springframework.validation.Errors; import org.springframework.validation.MapBindingResult; import org.springframework.web.context.request.RequestContextHolder; -import java.io.Serial; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -73,7 +66,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { public static final String FORMAT_PARAMETER = "format"; private Pattern[] patterns; - private final Map<Integer, List<Pattern>> patternByTokenCount = new HashMap<>(); + private Map<Integer, List<Pattern>> patternByTokenCount = new HashMap<Integer, List<Pattern>>(); private UrlMappingData urlData; private static final String DEFAULT_ENCODING = "UTF-8"; private static final Logger LOG = LoggerFactory.getLogger(RegexUrlMapping.class); @@ -132,7 +125,11 @@ public class RegexUrlMapping extends AbstractUrlMapping { for (int i = 0; i < urls.length; i++) { String url = urls[i]; Integer slashCount = org.springframework.util.StringUtils.countOccurrencesOf(url, "/"); - List<Pattern> tokenCountPatterns = patternByTokenCount.computeIfAbsent(slashCount, k -> new ArrayList<>()); + List<Pattern> tokenCountPatterns = patternByTokenCount.get(slashCount); + if (tokenCountPatterns == null) { + tokenCountPatterns = new ArrayList<>(); + patternByTokenCount.put(slashCount, tokenCountPatterns); + } Pattern pattern = convertToRegex(url); if (pattern == null) { @@ -198,8 +195,9 @@ public class RegexUrlMapping extends AbstractUrlMapping { } private void setNullable(ConstrainedProperty constraint) { - if (!constraint.isNullable()) { - constraint.applyConstraint(ConstrainedProperty.NULLABLE_CONSTRAINT, true); + ConstrainedProperty constrainedProperty = constraint; + if(!constrainedProperty.isNullable()) { + constrainedProperty.applyConstraint(ConstrainedProperty.NULLABLE_CONSTRAINT, true); } } @@ -221,13 +219,13 @@ public class RegexUrlMapping extends AbstractUrlMapping { int lastSlash = pattern.lastIndexOf('/'); String urlRoot = lastSlash > -1 ? pattern.substring(0, lastSlash) : pattern; - String urlEnd = lastSlash > -1 ? pattern.substring(lastSlash) : ""; + String urlEnd = lastSlash > -1 ? pattern.substring(lastSlash, pattern.length()) : ""; // Now replace "*" with "[^/]" and "**" with ".*". pattern = "^" + urlRoot .replace("(\\.(*))", "(\\.[^/]+)?") - .replaceAll("([^*])\\*([^*])", "$1[^/]+?$2") - .replaceAll("([^*])\\*$", "$1[^/]+?") + .replaceAll("([^\\*])\\*([^\\*])", "$1[^/]+?$2") + .replaceAll("([^\\*])\\*$", "$1[^/]+?") .replaceAll("\\*\\*", ".*"); if("/(*)(\\.(*))".equals(urlEnd)) { @@ -238,11 +236,11 @@ public class RegexUrlMapping extends AbstractUrlMapping { } else { pattern += urlEnd .replace("(\\.(*))", "(\\.[^/]+)?") - .replaceAll("([^*])\\*([^*])", "$1[^/]+?$2") - .replaceAll("([^*])\\*$", "$1[^/]+?") + .replaceAll("([^\\*])\\*([^\\*])", "$1[^/]+?$2") + .replaceAll("([^\\*])\\*$", "$1[^/]+?") .replaceAll("\\*\\*", ".*") - .replaceAll("\\(\\[\\^/]\\+\\)\\\\\\.", "([^/.]+?)\\\\.") - .replaceAll("\\(\\[\\^/]\\+\\)\\?\\\\\\.", "([^/.]+?)?\\\\.") + .replaceAll("\\(\\[\\^\\/\\]\\+\\)\\\\\\.", "([^/.]+?)\\\\.") + .replaceAll("\\(\\[\\^\\/\\]\\+\\)\\?\\\\\\.", "([^/.]+?)\\?\\\\.") ; } pattern += "/??$"; @@ -352,7 +350,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { } m = DOUBLE_WILDCARD_PATTERN.matcher(token); if (m.find()) { - StringBuilder buf = new StringBuilder(); + StringBuffer buf = new StringBuffer(); do { ConstrainedProperty prop = constraints[paramIndex++]; String propName = prop.getPropertyName(); @@ -376,7 +374,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { try { String v = buf.toString(); - if (v.contains(SLASH) && CAPTURED_DOUBLE_WILDCARD.equals(token)) { + if (v.indexOf(SLASH) > -1 && CAPTURED_DOUBLE_WILDCARD.equals(token)) { // individually URL encode path segments if (v.startsWith(SLASH)) { // get rid of leading slash @@ -386,7 +384,8 @@ public class RegexUrlMapping extends AbstractUrlMapping { for (String segment : segs) { uri.append(SLASH).append(encode(segment, encoding)); } - } else if (!v.isEmpty()) { + } + else if (v.length() > 0) { // original behavior uri.append(SLASH).append(encode(v, encoding)); } @@ -407,7 +406,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { populateParameterList(paramValues, encoding, uri, usedParams); if (LOG.isDebugEnabled()) { - LOG.debug("Created reverse URL mapping [" + uri + "] for parameters [" + paramValues + "]"); + LOG.debug("Created reverse URL mapping [" + uri.toString() + "] for parameters [" + paramValues + "]"); } return uri.toString(); } @@ -548,7 +547,8 @@ public class RegexUrlMapping extends AbstractUrlMapping { uri.append(AMPERSAND); } Object value = paramValues.get(name); - if (value instanceof Collection multiValues) { + if (value != null && value instanceof Collection) { + Collection multiValues = (Collection) value; for (Iterator j = multiValues.iterator(); j.hasNext();) { Object o = j.next(); appendValueToURI(encoding, uri, name, o); @@ -595,7 +595,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { Map params = new HashMap(); Errors errors = new MapBindingResult(params, "urlMapping"); int groupCount = m.groupCount(); - String lastGroup; + String lastGroup = null; for (int i = 0; i < groupCount; i++) { lastGroup = m.group(i + 1); // if null optional.. ignore @@ -614,7 +614,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { } } // if the format is specified but the value is empty, ignore it - if (!(FORMAT_PARAMETER.equals(propertyName) && !GrailsStringUtils.hasLength(lastGroup))) { + if (!(FORMAT_PARAMETER.equals(propertyName) && GrailsStringUtils.isEmpty(lastGroup))) { params.put(propertyName, lastGroup); } break; @@ -638,7 +638,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { lastGroup = lastGroup.substring(1); } // if the format is specified but the value is empty, ignore it - if (!(FORMAT_PARAMETER.equals(propertyName) && !GrailsStringUtils.hasLength(lastGroup))) { + if (!(FORMAT_PARAMETER.equals(propertyName) && GrailsStringUtils.isEmpty(lastGroup))) { params.put(propertyName, lastGroup); } } @@ -703,7 +703,6 @@ public class RegexUrlMapping extends AbstractUrlMapping { for (ConstrainedProperty constraint : constraints) { if (constraint.getPropertyName().equals(name)) { return new Closure(this) { - @Serial private static final long serialVersionUID = -2404119898659287216L; @Override @@ -741,12 +740,14 @@ public class RegexUrlMapping extends AbstractUrlMapping { * @return a negative integer, zero, or a positive integer as this {@link UrlMapping} is less than, equal to, or greater than the specified {@link UrlMapping}. */ public int compareTo(Object o) { - if (!(o instanceof UrlMapping other)) { + if (!(o instanceof UrlMapping)) { throw new IllegalArgumentException("Cannot compare with Object [" + o + "]. It is not an instance of UrlMapping!"); } if (equals(o)) return 0; + UrlMapping other = (UrlMapping) o; + // this wild card count final int thisStaticTokenCount = getStaticTokenCount(this); final int thisSingleWildcardCount = getSingleWildcardCount(this); @@ -769,27 +770,27 @@ public class RegexUrlMapping extends AbstractUrlMapping { } else if(isThisRoot) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] because it is the root", this, other); + LOG.debug("Mapping [{}] has a higher precedence than [{}] because it is the root", this.toString(), other.toString()); } return 1; } else if(isThatRoot) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter is the root", this, other); + LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter is the root", this.toString(), other.toString()); } return -1; } if (otherStaticTokenCount == 0 && thisStaticTokenCount > 0) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more path tokens", this, other); + LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more path tokens", this.toString(), other.toString()); } return 1; } if (thisStaticTokenCount == 0 && otherStaticTokenCount > 0) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] because it has fewer path tokens", this, other); + LOG.debug("Mapping [{}] has a lower precedence than [{}] because it has fewer path tokens", this.toString(), other.toString()); } return -1; } @@ -799,13 +800,13 @@ public class RegexUrlMapping extends AbstractUrlMapping { if (otherStaticAndWildcardTokenCount==0 && thisStaticAndWildcardTokenCount>0) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more path tokens [{} vs {}]", this, other, thisStaticAndWildcardTokenCount, otherStaticAndWildcardTokenCount); + LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticAndWildcardTokenCount, otherStaticAndWildcardTokenCount); } return 1; } if (thisStaticAndWildcardTokenCount==0 && otherStaticAndWildcardTokenCount>0) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] because the latter has more path tokens [{} vs {}]", this, other, thisStaticAndWildcardTokenCount, otherStaticAndWildcardTokenCount); + LOG.debug("Mapping [{}] has a higher precedence than [{}] because the latter has more path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticAndWildcardTokenCount, otherStaticAndWildcardTokenCount); } return -1; } @@ -813,13 +814,13 @@ public class RegexUrlMapping extends AbstractUrlMapping { final int staticDiff = thisStaticTokenCount - otherStaticTokenCount; if (staticDiff < 0 && !otherHasWildCards) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter has more concrete path tokens [{} vs {}]", this, other, thisStaticTokenCount, otherStaticTokenCount); + LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter has more concrete path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticTokenCount, otherStaticTokenCount); } return -1; } else if(staticDiff > 0 && !hasWildCards) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more concrete path tokens [{} vs {}]", this, other, thisStaticTokenCount, otherStaticTokenCount); + LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more concrete path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticTokenCount, otherStaticTokenCount); } return 1; } @@ -829,7 +830,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { final int thisTokensLength = thisTokens.length; final int otherTokensLength = otherTokens.length; - int greaterLength = Math.max(thisTokensLength, otherTokensLength); + int greaterLength = thisTokensLength > otherTokensLength ? thisTokensLength : otherTokensLength; for (int i = 0; i < greaterLength; i++) { final boolean thisHasMoreTokens = i < thisTokensLength; final boolean otherHasMoreTokens = i < otherTokensLength; @@ -838,13 +839,13 @@ public class RegexUrlMapping extends AbstractUrlMapping { boolean otherTokenIsWildcard = !otherHasMoreTokens || isSingleWildcard(otherTokens[i]); if (thisTokenIsWildcard && !otherTokenIsWildcard) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter contains more concrete tokens", this, other); + LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter contains more concrete tokens", this.toString(), other.toString()); } return -1; } if (!thisTokenIsWildcard && otherTokenIsWildcard) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] because it contains more concrete tokens", this, other); + LOG.debug("Mapping [{}] has a higher precedence than [{}] because it contains more concrete tokens", this.toString(), other.toString()); } return 1; } @@ -854,10 +855,10 @@ public class RegexUrlMapping extends AbstractUrlMapping { if (doubleWildcardDiff != 0) { if(LOG.isDebugEnabled()) { if(doubleWildcardDiff > 0) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] due containing more double wild cards [{} vs. {}]", this, other, thisDoubleWildcardCount, otherDoubleWildcardCount); + LOG.debug("Mapping [{}] has a higher precedence than [{}] due containing more double wild cards [{} vs. {}]", this.toString(), other.toString(), thisDoubleWildcardCount, otherDoubleWildcardCount); } else if(doubleWildcardDiff < 0) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the latter containing more double wild cards [{} vs. {}]", this, other, thisDoubleWildcardCount, otherDoubleWildcardCount); + LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the latter containing more double wild cards [{} vs. {}]", this.toString(), other.toString(), thisDoubleWildcardCount, otherDoubleWildcardCount); } } return doubleWildcardDiff; @@ -867,10 +868,10 @@ public class RegexUrlMapping extends AbstractUrlMapping { if (singleWildcardDiff != 0) { if(LOG.isDebugEnabled()) { if(singleWildcardDiff > 0) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] because it contains more single wild card matches [{} vs. {}]", this, other, thisSingleWildcardCount, otherSingleWildcardCount); + LOG.debug("Mapping [{}] has a higher precedence than [{}] because it contains more single wild card matches [{} vs. {}]", this.toString(), other.toString(), thisSingleWildcardCount, otherSingleWildcardCount); } else if(singleWildcardDiff < 0) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the latter containing more single wild card matches[{} vs. {}]", this, other, thisSingleWildcardCount, otherSingleWildcardCount); + LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the latter containing more single wild card matches[{} vs. {}]", this.toString(), other.toString(), thisSingleWildcardCount, otherSingleWildcardCount); } } return singleWildcardDiff; @@ -882,10 +883,10 @@ public class RegexUrlMapping extends AbstractUrlMapping { if (constraintDiff != 0) { if(LOG.isDebugEnabled()) { if(constraintDiff > 0) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] since it defines more constraints [{} vs. {}]", this, other, thisConstraintCount, thatConstraintCount); + LOG.debug("Mapping [{}] has a higher precedence than [{}] since it defines more constraints [{} vs. {}]", this.toString(), other.toString(), thisConstraintCount, thatConstraintCount); } else if(constraintDiff < 0) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] since the latter defines more constraints [{} vs. {}]", this, other, thisConstraintCount, thatConstraintCount); + LOG.debug("Mapping [{}] has a lower precedence than [{}] since the latter defines more constraints [{} vs. {}]", this.toString(), other.toString(), thisConstraintCount, thatConstraintCount); } } return constraintDiff; @@ -895,10 +896,10 @@ public class RegexUrlMapping extends AbstractUrlMapping { if(allDiff != 0) { if(LOG.isDebugEnabled()) { if(allDiff > 0) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] due to the overall diff", this, other); + LOG.debug("Mapping [{}] has a higher precedence than [{}] due to the overall diff", this.toString(), other.toString()); } else if(allDiff < 0) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the overall diff", this, other); + LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the overall diff", this.toString(), other.toString()); } } return allDiff; @@ -911,13 +912,13 @@ public class RegexUrlMapping extends AbstractUrlMapping { } else if(thisVersion.equals(ANY_VERSION) && !thatVersion.equals(ANY_VERSION)) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] due to version precedence [{} vs {}]", this, other, thisVersion, thatVersion); + LOG.debug("Mapping [{}] has a lower precedence than [{}] due to version precedence [{} vs {}]", this.toString(), other.toString(), thisVersion, thatVersion); } return -1; } else if(!thisVersion.equals(ANY_VERSION) && thatVersion.equals(ANY_VERSION)) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] due to version precedence [{} vs {}]", this, other, thisVersion, thatVersion); + LOG.debug("Mapping [{}] has a higher precedence than [{}] due to version precedence [{} vs {}]", this.toString(), other.toString(), thisVersion, thatVersion); } return 1; } @@ -926,13 +927,13 @@ public class RegexUrlMapping extends AbstractUrlMapping { if(i > 0) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a higher precedence than [{}] due to version precedence [{} vs. {}]", this, other, thisVersion, thatVersion); + LOG.debug("Mapping [{}] has a higher precedence than [{}] due to version precedence [{} vs. {}]", this.toString(), other.toString(), thisVersion, thatVersion); } return 1; } else if(i < 0) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has a lower precedence than [{}] due to version precedence [{} vs. {}]", this, other, thisVersion, thatVersion); + LOG.debug("Mapping [{}] has a lower precedence than [{}] due to version precedence [{} vs. {}]", this.toString(), other.toString(), thisVersion, thatVersion); } return -1; } @@ -945,35 +946,35 @@ public class RegexUrlMapping extends AbstractUrlMapping { private int evaluatePluginOrder(UrlMapping other) { if (isDefinedInPlugin() && !other.isDefinedInPlugin()) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has lower precedence than [{}] because the latter has priority over plugins", this, other); + LOG.debug("Mapping [{}] has lower precedence than [{}] because the latter has priority over plugins", this.toString(), other.toString()); } return -1; } else if (!isDefinedInPlugin() && other.isDefinedInPlugin()) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has higher precedence than [{}] because it has priority over plugins", this, other); + LOG.debug("Mapping [{}] has higher precedence than [{}] because it has priority over plugins", this.toString(), other.toString()); } return 1; } else { if (isDefinedInPlugin()) { if (pluginIndex > other.getPluginIndex()) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has higher precedence than [{}] because it was loaded after", this, other); + LOG.debug("Mapping [{}] has higher precedence than [{}] because it was loaded after", this.toString(), other.toString()); } return 1; } else if (pluginIndex < other.getPluginIndex()) { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has lower precedence than [{}] because it was loaded before", this, other); + LOG.debug("Mapping [{}] has lower precedence than [{}] because it was loaded before", this.toString(), other.toString()); } return -1; } else { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has equal precedence with mapping [{}]", this, other); + LOG.debug("Mapping [{}] has equal precedence with mapping [{}]", this.toString(), other.toString()); } return 0; } } else { if(LOG.isDebugEnabled()) { - LOG.debug("Mapping [{}] has equal precedence with mapping [{}]", this, other.toString()); + LOG.debug("Mapping [{}] has equal precedence with mapping [{}]", this.toString(), other.toString()); } return 0; } @@ -1012,7 +1013,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { String[] tokens = mapping.getUrlData().getTokens(); int count = 0; for (String token : tokens) { - if (!isSingleWildcard(token) && !token.isEmpty()) count++; + if (!isSingleWildcard(token) && !"".equals(token)) count++; } return count; } @@ -1030,7 +1031,7 @@ public class RegexUrlMapping extends AbstractUrlMapping { int count = 0; for (String token : tokens) { token = token.replace(OPTIONAL_EXTENSION_WILDCARD, "").replace(CAPTURED_DOUBLE_WILDCARD,"").replace(CAPTURED_WILDCARD,""); - if (!token.isEmpty()) count++; + if (!"".equals(token)) count++; } return count; }
