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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion grace-api/src/main/groovy/grails/artefact/ArtefactTypes.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022-2025 the original author or authors.
* Copyright 2022-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,6 +31,8 @@ public final class ArtefactTypes {

public static final String DOMAIN_CLASS = "Domain";

public static final String GROOVY_PAGE = "GroovyPage";

public static final String SERVICE = "Service";

public static final String TAG_LIBRARY = "TagLib";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2022 the original author or authors.
* Copyright 2011-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,12 +15,23 @@
*/
package grails.compiler.ast;

import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;

import org.grails.gsp.GroovyPage;

/**
* Extended marker interface that indicates this ClassInjector applies to GSPs.
*
* @author Stephane Maldini
* @author Michael Yan
* @since 2.0
*/
public interface GroovyPageInjector extends ClassInjector {
// marker

@Override
default boolean shouldInject(ClassNode classNode) {
return classNode.isDerivedFrom(ClassHelper.make(GroovyPage.class));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2022 the original author or authors.
* Copyright 2006-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,12 +22,13 @@
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.Phases;

import org.grails.gsp.compiler.transform.GroovyPageInjectionOperation;
import org.grails.compiler.injection.GrailsAwareInjectionOperation;

/**
* A class loader that is aware of Groovy Pages and injection operations.
*
* @author Stephane Maldini
* @author Michael Yan
* @since 2.0
*/
public class GroovyPageClassLoader extends GroovyClassLoader {
Expand Down Expand Up @@ -57,14 +58,10 @@ public GroovyPageClassLoader(ClassLoader loader, CompilerConfiguration config) {
*/
@Override
protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) {
CompilationUnit cu = super.createCompilationUnit(config, source);

GroovyPageInjectionOperation operation;

operation = new GroovyPageInjectionOperation();

cu.addPhaseOperation(operation, Phases.CANONICALIZATION);
return cu;
CompilationUnit compilationUnit = super.createCompilationUnit(config, source);
GrailsAwareInjectionOperation operation = new GrailsAwareInjectionOperation(compilationUnit);
compilationUnit.addPhaseOperation(operation, Phases.CANONICALIZATION);
return compilationUnit;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2025 the original author or authors.
* Copyright 2004-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,12 +29,15 @@ import org.apache.commons.logging.LogFactory
import org.codehaus.groovy.control.CompilationUnit
import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.Phases
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer

import grails.config.ConfigMap

import org.grails.compiler.injection.GrailsAwareInjectionOperation
import org.grails.config.CodeGenConfig
import org.grails.gsp.GroovyPageClassLoader
import org.grails.gsp.GroovyPageMetaInfo
import org.grails.gsp.compiler.transform.GroovyPageInjectionOperation
import org.grails.gsp.compiler.transform.GroovyPageTransform
import org.grails.taglib.encoder.OutputEncodingSettings

/**
Expand All @@ -53,9 +56,9 @@ class GroovyPageCompiler {
private final Object mutexObject = new Object()
File generatedGroovyPagesDirectory
File targetDir
CompilerConfiguration compilerConfig = new CompilerConfiguration()
GroovyPageInjectionOperation operation = new GroovyPageInjectionOperation()
GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().contextClassLoader, compilerConfig)
CompilerConfiguration compilerConfig
GrailsAwareInjectionOperation operation
GroovyPageClassLoader classLoader

List<File> srcFiles = []
File viewsDir
Expand All @@ -67,14 +70,20 @@ class GroovyPageCompiler {
ConfigMap configMap
ExecutorService threadPool

GroovyPageCompiler() {
this.compilerConfig = new CompilerConfiguration()
this.operation = new GrailsAwareInjectionOperation()
this.classLoader = new GroovyPageClassLoader(Thread.currentThread().contextClassLoader, this.compilerConfig)
}

void setCompilerConfig(CompilerConfiguration c) {
compilerConfig = c
classLoader = new GroovyClassLoader(Thread.currentThread().contextClassLoader, compilerConfig)
this.compilerConfig = c
this.classLoader = new GroovyPageClassLoader(Thread.currentThread().contextClassLoader, this.compilerConfig)
}

void setCleanCompilerConfig(CompilerConfiguration c) {
compilerConfig = c
classLoader = new GroovyClassLoader(System.classLoader, compilerConfig)
this.compilerConfig = c
this.classLoader = new GroovyPageClassLoader(System.classLoader, this.compilerConfig)
}

/**
Expand Down Expand Up @@ -121,7 +130,9 @@ class GroovyPageCompiler {
for (int gspIndex = 0; gspIndex < gspFiles.size(); gspIndex++) {
File gsp = gspFiles[gspIndex]
try {
compileGSP(viewsDir, gsp, viewPrefix, packagePrefix, results)
CompilerConfiguration configuration = new CompilerConfiguration(this.compilerConfig)
configuration.addCompilationCustomizers(new ASTTransformationCustomizer(new GroovyPageTransform()))
compileGSP(configuration, viewsDir, gsp, viewPrefix, packagePrefix, results)
}
catch (Exception ex) {
LOG.error("Error Compiling GSP File: ${gsp.name} - ${ex.message}")
Expand Down Expand Up @@ -178,7 +189,7 @@ class GroovyPageCompiler {
* @param packagePrefix The package prefix to use which allows scoping for different applications and plugins
*
*/
protected Map compileGSP(File viewsDir, File gspfile, String viewPrefix, String packagePrefix, Map compileGSPResults) {
protected Map compileGSP(CompilerConfiguration configuration, File viewsDir, File gspfile, String viewPrefix, String packagePrefix, Map compileGSPResults) {
String relPath = relativePath(viewsDir, gspfile)
String viewuri = viewPrefix + relPath

Expand Down Expand Up @@ -236,7 +247,7 @@ class GroovyPageCompiler {
// register viewuri -> classname mapping
compileGSPResults[viewuri] = fullClassName

CompilationUnit unit = new CompilationUnit(compilerConfig, null, classLoader)
CompilationUnit unit = new CompilationUnit(configuration, null, classLoader)
unit.addPhaseOperation(operation, Phases.CANONICALIZATION)
unit.addSource(gspgroovyfile.name, gsptarget.toString())
// unit.addSource(gspgroovyfile)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2023 the original author or authors.
* Copyright 2011-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -48,9 +48,4 @@ public void performInjection(SourceUnit source, ClassNode classNode) {
performInjection(source, null, classNode);
}

@Override
public boolean shouldInject(ClassNode classNode) {
return false;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2022 the original author or authors.
* Copyright 2011-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,8 +33,10 @@
* attempt AST injection.
*
* @author Stephane Maldini
* @deprecated since 2024.2.0, in favor of {@link GrailsAwareInjectionOperation}
* @since 2.0
*/
@Deprecated(since = "2024.2.0", forRemoval = true)
public class GroovyPageInjectionOperation extends GrailsAwareInjectionOperation {

private GroovyPageInjector[] groovyPageInjectors;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2022-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
package org.grails.gsp.compiler.transform

import groovy.transform.CompilationUnitAware
import groovy.transform.CompileStatic
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.expr.ConstantExpression
import org.codehaus.groovy.control.CompilationUnit
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.ASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation

import grails.artefact.Artefact
import grails.compiler.traits.TraitInjector
import grails.core.ArtefactHandler

import org.grails.compiler.injection.ArtefactTypeAstTransformation
import org.grails.compiler.injection.GrailsASTUtils
import org.grails.compiler.injection.TraitInjectionUtils
import org.grails.io.support.GrailsFactoriesLoader

/**
* {@link ASTTransformation} to apply {@link TraitInjector} for GroovyPage.
*
* @author Michael Yan
* @since 2024.2.0
*/
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
@CompileStatic
class GroovyPageTransform implements ASTTransformation, CompilationUnitAware {

CompilationUnit compilationUnit

@Override
void visit(ASTNode[] nodes, SourceUnit source) {
List<ClassNode> classes = source.AST.classes

String sourceName = source.name
if (!sourceName.endsWith('_gsp.groovy')) {
return
}

List<ArtefactHandler> artefactHandlers = GrailsFactoriesLoader.loadFactories(ArtefactHandler)

for (ClassNode classNode in classes) {
if (!GrailsASTUtils.isApplied(classNode, this.getClass())) {
for (ArtefactHandler handler in artefactHandlers) {
if (handler.isArtefact(classNode)) {
AnnotationNode annotationNode = new AnnotationNode(new ClassNode(Artefact))
annotationNode.addMember('value', new ConstantExpression(handler.type))
classNode.addAnnotation(annotationNode)

ArtefactTypeAstTransformation.performInjectionOnNode(source, classNode, handler.type, compilationUnit)
TraitInjectionUtils.processTraitsForNode(source, classNode, handler.type, compilationUnit)
}
}
}
GrailsASTUtils.markApplied(classNode, this.getClass())
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2022-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
package grails.core.gsp;

import grails.core.GrailsClass;

/**
* Groovy Page class
*
* @author Michael Yan
* @since 2024.2.0
*/
public interface GroovyPageClass extends GrailsClass {
}
Loading
Loading