From 5a96f10f9610162c5e99b6cd4928c8d5d4000a94 Mon Sep 17 00:00:00 2001 From: Michael Yan Date: Wed, 22 May 2024 17:18:15 +0800 Subject: [PATCH 1/2] Start building against SiteMesh 2.6.0 snapshots See gh-299 * Use `DefaultFactory` instead of `Grails5535Factory` * Use `NoDecorator` * Use `TokenizedHTMLPage` instead of `GrailsTokenizedHTMLPage` * Remove `Grails5535Factory`, `GrailsTokenizedHTMLPage` --- .../view/SitemeshLayoutViewResolver.java | 28 +- grace-web-sitemesh/build.gradle | 2 +- .../web/sitemesh/Grails5535Factory.java | 343 ------------------ .../web/sitemesh/GrailsHTMLPageParser.java | 7 +- .../web/sitemesh/GrailsNoDecorator.java | 42 +-- .../web/sitemesh/GrailsTokenizedHTMLPage.java | 64 ---- .../sitemesh/TokenizedHTMLPage2Content.java | 11 +- gradle/libs.versions.toml | 2 +- settings.gradle | 2 +- 9 files changed, 28 insertions(+), 473 deletions(-) delete mode 100644 grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/Grails5535Factory.java delete mode 100644 grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsTokenizedHTMLPage.java diff --git a/grace-web-gsp/src/main/groovy/org/grails/web/servlet/view/SitemeshLayoutViewResolver.java b/grace-web-gsp/src/main/groovy/org/grails/web/servlet/view/SitemeshLayoutViewResolver.java index 43feb12d73..1e619b7794 100644 --- a/grace-web-gsp/src/main/groovy/org/grails/web/servlet/view/SitemeshLayoutViewResolver.java +++ b/grace-web-gsp/src/main/groovy/org/grails/web/servlet/view/SitemeshLayoutViewResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2023 the original author or authors. + * Copyright 2014-2024 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. @@ -15,14 +15,16 @@ */ package org.grails.web.servlet.view; +import java.util.Collections; import java.util.Enumeration; -import java.util.NoSuchElementException; +import java.util.Map; import jakarta.servlet.FilterConfig; import jakarta.servlet.ServletContext; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Factory; +import com.opensymphony.module.sitemesh.factory.DefaultFactory; import com.opensymphony.sitemesh.ContentProcessor; import com.opensymphony.sitemesh.compatability.PageParser2ContentProcessor; import org.springframework.beans.factory.DisposableBean; @@ -36,7 +38,6 @@ import grails.core.support.GrailsApplicationAware; import org.grails.web.sitemesh.FactoryHolder; -import org.grails.web.sitemesh.Grails5535Factory; import org.grails.web.sitemesh.GroovyPageLayoutFinder; import org.grails.web.sitemesh.SitemeshLayoutView; @@ -80,6 +81,10 @@ public void init() { protected Factory loadSitemeshConfig() { FilterConfig filterConfig = new FilterConfig() { + private final Map customConfig = + Collections.singletonMap("configFile", + "classpath:org/grails/web/sitemesh/sitemesh-default.xml"); + @Override public ServletContext getServletContext() { return servletContext; @@ -87,22 +92,12 @@ public ServletContext getServletContext() { @Override public Enumeration getInitParameterNames() { - return new Enumeration() { - @Override - public boolean hasMoreElements() { - return false; - } - - @Override - public String nextElement() { - throw new NoSuchElementException(); - } - }; + return Collections.enumeration(this.customConfig.keySet()); } @Override public String getInitParameter(String name) { - return null; + return this.customConfig.get(name); } @Override @@ -110,8 +105,9 @@ public String getFilterName() { return null; } }; + Config config = new Config(filterConfig); - Grails5535Factory sitemeshFactory = new Grails5535Factory(config); + DefaultFactory sitemeshFactory = new DefaultFactory(config); if (servletContext != null) { servletContext.setAttribute(FACTORY_SERVLET_CONTEXT_ATTRIBUTE, sitemeshFactory); } diff --git a/grace-web-sitemesh/build.gradle b/grace-web-sitemesh/build.gradle index 0e663f3fbc..9d5ec90e4c 100644 --- a/grace-web-sitemesh/build.gradle +++ b/grace-web-sitemesh/build.gradle @@ -1,6 +1,6 @@ dependencies { api libs.jakarta.servlet - api project(":grace-sitemesh") + api libs.sitemesh api project(":grace-web-common") testImplementation libs.spring.test diff --git a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/Grails5535Factory.java b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/Grails5535Factory.java deleted file mode 100644 index 389dec55f2..0000000000 --- a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/Grails5535Factory.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright 2011-2022 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.web.sitemesh; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import com.opensymphony.module.sitemesh.Config; -import com.opensymphony.module.sitemesh.factory.BaseFactory; -import com.opensymphony.module.sitemesh.factory.FactoryException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; -import org.xml.sax.SAXException; - -/** - * TODO remove this once http://jira.opensymphony.com/browse/SIM-263 is fixed. - * - * Replaces DefaultFactory to fix http://jira.codehaus.org/browse/GRAILS-5535. There - * are two changes, both replacing toURL() with toURI().toURL(). - */ -@SuppressWarnings({ "unchecked", "rawtypes" }) -public class Grails5535Factory extends BaseFactory { - - private static final Log log = LogFactory.getLog(Grails5535Factory.class); - - String configFileName; - - private static final String DEFAULT_CONFIG_FILENAME = "/WEB-INF/sitemesh.xml"; - - File configFile; - - long configLastModified; - - private long configLastCheck = 0L; - - public static long configCheckMillis = 3000L; - - Map configProps = new HashMap(); - - String excludesFileName; - - File excludesFile; - - public Grails5535Factory(Config config) { - super(config); - - this.configFileName = config.getServletContext().getInitParameter("sitemesh.configfile"); - if (this.configFileName == null) { - this.configFileName = DEFAULT_CONFIG_FILENAME; - } - - // configFilePath is null if loaded from war file - String initParamConfigFile = config.getConfigFile(); - if (initParamConfigFile != null) { - this.configFileName = initParamConfigFile; - } - - String configFilePath = config.getServletContext().getRealPath(this.configFileName); - - if (configFilePath != null) { // disable config auto reloading for .war files - this.configFile = new File(configFilePath); - } - - loadConfig(); - } - - @Override - protected void pushDecoratorMapper(String className, Properties properties) { - try { - super.pushDecoratorMapper(className, properties); - } - catch (Exception e) { - log.warn("Error initializing decorator mapper", e); - } - } - - /** Load configuration from file. */ - private synchronized void loadConfig() { - try { - // Load and parse the sitemesh.xml file - Element root = loadSitemeshXML(); - - NodeList sections = root.getChildNodes(); - // Loop through child elements of root node - for (int i = 0; i < sections.getLength(); i++) { - if (sections.item(i) instanceof Element) { - Element curr = (Element) sections.item(i); - NodeList children = curr.getChildNodes(); - - if ("config-refresh".equalsIgnoreCase(curr.getTagName())) { - String seconds = curr.getAttribute("seconds"); - configCheckMillis = Long.parseLong(seconds) * 1000L; - } - else if ("property".equalsIgnoreCase(curr.getTagName())) { - String name = curr.getAttribute("name"); - String value = curr.getAttribute("value"); - if (!"".equals(name) && !"".equals(value)) { - this.configProps.put("${" + name + "}", value); - } - } - else if ("page-parsers".equalsIgnoreCase(curr.getTagName())) { - // handle - loadPageParsers(children); - } - else if ("decorator-mappers".equalsIgnoreCase(curr.getTagName())) { - // handle - loadDecoratorMappers(children); - } - else if ("excludes".equalsIgnoreCase(curr.getTagName())) { - // handle - String fileName = replaceProperties(curr.getAttribute("file")); - if (!"".equals(fileName)) { - this.excludesFileName = fileName; - loadExcludes(); - } - } - } - } - } - catch (ParserConfigurationException e) { - throw new FactoryException("Could not get XML parser", e); - } - catch (IOException e) { - throw new FactoryException("Could not read config file : " + this.configFileName, e); - } - catch (SAXException e) { - throw new FactoryException("Could not parse config file : " + this.configFileName, e); - } - } - - private Element loadSitemeshXML() throws ParserConfigurationException, IOException, SAXException { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - - InputStream is = null; - - if (this.configFile == null) { - is = this.config.getServletContext().getResourceAsStream(this.configFileName); - } - else if (this.configFile.exists() && this.configFile.canRead()) { - is = this.configFile.toURI().toURL().openStream(); - } - - if (is == null) { // load the default sitemesh configuration - is = getClass().getResourceAsStream("sitemesh-default.xml"); - } - - if (is == null) { // load the default sitemesh configuration - is = getClass().getClassLoader().getResourceAsStream("com/opensymphony/module/sitemesh/factory/sitemesh-default.xml"); - } - - if (is == null) { // load the default sitemesh configuration using another classloader - is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/opensymphony/module/sitemesh/factory/sitemesh-default.xml"); - } - - if (is == null) { - throw new IllegalStateException("Cannot load default configuration from jar"); - } - - if (this.configFile != null) { - this.configLastModified = this.configFile.lastModified(); - } - - Document doc = builder.parse(is); - Element root = doc.getDocumentElement(); - // Verify root element - if (!"sitemesh".equalsIgnoreCase(root.getTagName())) { - throw new FactoryException("Root element of sitemesh configuration file not ", null); - } - return root; - } - - private void loadExcludes() throws ParserConfigurationException, IOException, SAXException { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - - InputStream is = null; - - if (this.excludesFile == null) { - is = this.config.getServletContext().getResourceAsStream(this.excludesFileName); - } - else if (this.excludesFile.exists() && this.excludesFile.canRead()) { - is = this.excludesFile.toURI().toURL().openStream(); - } - - if (is == null) { - log.warn("Cannot load excludes configuration file \"" - + this.excludesFileName + "\" as specified in \"sitemesh.xml\" or \"sitemesh-default.xml\""); - return; - } - - Document document = builder.parse(is); - Element root = document.getDocumentElement(); - NodeList sections = root.getChildNodes(); - - // Loop through child elements of root node looking for the block - for (int i = 0; i < sections.getLength(); i++) { - if (sections.item(i) instanceof Element) { - Element curr = (Element) sections.item(i); - if ("excludes".equalsIgnoreCase(curr.getTagName())) { - loadExcludeUrls(curr.getChildNodes()); - } - } - } - } - - /** Loop through children of 'page-parsers' element and add all 'parser' mappings. */ - private void loadPageParsers(NodeList nodes) { - clearParserMappings(); - for (int i = 0; i < nodes.getLength(); i++) { - if (nodes.item(i) instanceof Element) { - Element curr = (Element) nodes.item(i); - - if ("parser".equalsIgnoreCase(curr.getTagName())) { - String className = curr.getAttribute("class"); - String contentType = curr.getAttribute("content-type"); - mapParser(contentType, className); - } - } - } - } - - private void loadDecoratorMappers(NodeList nodes) { - clearDecoratorMappers(); - Properties emptyProps = new Properties(); - - pushDecoratorMapper("com.opensymphony.module.sitemesh.mapper.NullDecoratorMapper", emptyProps); - - // note, this works from the bottom node up. - for (int i = nodes.getLength() - 1; i > 0; i--) { - if (nodes.item(i) instanceof Element) { - Element curr = (Element) nodes.item(i); - if ("mapper".equalsIgnoreCase(curr.getTagName())) { - String className = curr.getAttribute("class"); - Properties props = new Properties(); - // build properties from tags. - NodeList children = curr.getChildNodes(); - for (int j = 0; j < children.getLength(); j++) { - if (children.item(j) instanceof Element) { - Element currC = (Element) children.item(j); - if ("param".equalsIgnoreCase(currC.getTagName())) { - String value = currC.getAttribute("value"); - props.put(currC.getAttribute("name"), replaceProperties(value)); - } - } - } - // add mapper - pushDecoratorMapper(className, props); - } - } - } - - pushDecoratorMapper("com.opensymphony.module.sitemesh.mapper.InlineDecoratorMapper", emptyProps); - } - - /** - * Reads in all the url patterns to exclude from decoration. - */ - private void loadExcludeUrls(NodeList nodes) { - clearExcludeUrls(); - for (int i = 0; i < nodes.getLength(); i++) { - if (nodes.item(i) instanceof Element) { - Element p = (Element) nodes.item(i); - if ("pattern".equalsIgnoreCase(p.getTagName()) || "url-pattern".equalsIgnoreCase(p.getTagName())) { - Text patternText = (Text) p.getFirstChild(); - if (patternText != null) { - String pattern = patternText.getData().trim(); - if (pattern != null) { - addExcludeUrl(pattern); - } - } - } - } - } - } - - /** Check if configuration file has been modified, and if so reload it. */ - @Override - public void refresh() { - long time = System.currentTimeMillis(); - if (time - this.configLastCheck < configCheckMillis) { - return; - } - this.configLastCheck = time; - - if (this.configFile != null && this.configLastModified != this.configFile.lastModified()) { - loadConfig(); - } - } - - /** - * Replaces any properties that appear in the supplied string - * with their actual values - * - * @param str the string to replace the properties in - * @return the same string but with any properties expanded out to their - * actual values - */ - private String replaceProperties(String str) { - Set props = this.configProps.entrySet(); - for (Iterator it = props.iterator(); it.hasNext(); ) { - Map.Entry entry = (Map.Entry) it.next(); - String key = (String) entry.getKey(); - int idx; - while ((idx = str.indexOf(key)) >= 0) { - StringBuilder buf = new StringBuilder(100); - buf.append(str.substring(0, idx)); - buf.append(entry.getValue()); - buf.append(str.substring(idx + key.length())); - str = buf.toString(); - } - } - return str; - } - -} diff --git a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsHTMLPageParser.java b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsHTMLPageParser.java index 85c0d5404a..86c32e222d 100644 --- a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsHTMLPageParser.java +++ b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsHTMLPageParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the original author or authors. + * Copyright 2004-2023 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. @@ -33,6 +33,7 @@ import com.opensymphony.module.sitemesh.html.rules.TitleExtractingRule; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.parser.HTMLPageParser; +import com.opensymphony.module.sitemesh.parser.TokenizedHTMLPage; import com.opensymphony.sitemesh.Content; public class GrailsHTMLPageParser extends HTMLPageParser { @@ -41,7 +42,7 @@ public class GrailsHTMLPageParser extends HTMLPageParser { public Page parse(char[] data) throws IOException { CharArray head = new CharArray(64); CharArray body = new CharArray(4096); - GrailsTokenizedHTMLPage page = new GrailsTokenizedHTMLPage(data, body, head); + TokenizedHTMLPage page = new TokenizedHTMLPage(data, body, head); HTMLProcessor processor = new HTMLProcessor(data, body); State html = processor.defaultState(); @@ -59,7 +60,7 @@ public Page parse(char[] data) throws IOException { } public Content parseContent(char[] data) throws IOException { - return new TokenizedHTMLPage2Content((GrailsTokenizedHTMLPage) parse(data)); + return new TokenizedHTMLPage2Content((TokenizedHTMLPage) parse(data)); } @Override diff --git a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsNoDecorator.java b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsNoDecorator.java index f28c62c032..a1d8bee4d2 100644 --- a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsNoDecorator.java +++ b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsNoDecorator.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the original author or authors. + * Copyright 2004-2024 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. @@ -15,53 +15,17 @@ */ package org.grails.web.sitemesh; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; import java.util.Iterator; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - import com.opensymphony.module.sitemesh.Decorator; -import com.opensymphony.sitemesh.Content; -import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; -import com.opensymphony.sitemesh.webapp.decorator.BaseWebAppDecorator; +import com.opensymphony.sitemesh.webapp.decorator.NoDecorator; /** * Grails version of Sitemesh's NoDecorator * - * original version always calls response.setContentLength which would require the calculation of - * resulting bytes. Calculation would be extra overhead. - * - * bug exists for OutputStream / byte version: http://jira.opensymphony.com/browse/SIM-196 - * skip setting ContentLength because of that bug. - * * @author Lari Hotari, Sagire Software Oy */ -public class GrailsNoDecorator extends BaseWebAppDecorator implements Decorator { - - @Override - protected void render(Content content, HttpServletRequest request, HttpServletResponse response, - ServletContext servletContext, SiteMeshWebAppContext webAppContext) - throws IOException, ServletException { - - if (webAppContext.isUsingStream()) { - // http://jira.opensymphony.com/browse/SIM-196 , skip setting setContentLength - //response.setContentLength(content.originalLength()); - OutputStream output = response.getOutputStream(); - PrintWriter writer = new PrintWriter(output); - content.writeOriginal(writer); - writer.flush(); - } - else { - PrintWriter writer = response.getWriter(); - content.writeOriginal(writer); - writer.flush(); - } - } +public class GrailsNoDecorator extends NoDecorator implements Decorator { public String getPage() { return null; diff --git a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsTokenizedHTMLPage.java b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsTokenizedHTMLPage.java deleted file mode 100644 index ef7243b0ef..0000000000 --- a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/GrailsTokenizedHTMLPage.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2004-2022 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.web.sitemesh; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; - -import com.opensymphony.module.sitemesh.html.util.CharArray; -import com.opensymphony.module.sitemesh.parser.TokenizedHTMLPage; - -public class GrailsTokenizedHTMLPage extends TokenizedHTMLPage { - - private final CharArray body; - - private final CharArray head; - - private final char[] data; - - public GrailsTokenizedHTMLPage(char[] data, CharArray body, CharArray head) { - super(data, body, head); - this.data = data; - this.body = body; - this.head = head; - } - - @Override - public void writeHead(Writer out) throws IOException { - if (out instanceof PrintWriter) { - this.head.writeTo((PrintWriter) out); - } - else { - super.writeHead(out); - } - } - - @Override - public void writeBody(Writer out) throws IOException { - if (out instanceof PrintWriter) { - this.body.writeTo((PrintWriter) out); - } - else { - super.writeBody(out); - } - } - - public char[] getData() { - return this.data; - } - -} diff --git a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/TokenizedHTMLPage2Content.java b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/TokenizedHTMLPage2Content.java index 45811e4f58..101090a720 100644 --- a/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/TokenizedHTMLPage2Content.java +++ b/grace-web-sitemesh/src/main/groovy/org/grails/web/sitemesh/TokenizedHTMLPage2Content.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 the original author or authors. + * Copyright 2014-2024 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. @@ -18,19 +18,20 @@ import java.io.IOException; import java.io.Writer; +import com.opensymphony.module.sitemesh.parser.TokenizedHTMLPage; import com.opensymphony.sitemesh.Content; final class TokenizedHTMLPage2Content implements Content { - private final GrailsTokenizedHTMLPage page; + private final TokenizedHTMLPage page; - TokenizedHTMLPage2Content(GrailsTokenizedHTMLPage page) { + TokenizedHTMLPage2Content(TokenizedHTMLPage page) { this.page = page; } @Override public void writeOriginal(Writer out) throws IOException { - out.write(this.page.getData()); + this.page.writePage(out); } @Override @@ -68,7 +69,7 @@ public void addProperty(String name, String value) { this.page.addProperty(name, value); } - public GrailsTokenizedHTMLPage getPage() { + public TokenizedHTMLPage getPage() { return this.page; } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2751da0ea6..52405069c8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ methvin-directory-watcher = "0.18.0" mockito = "4.5.1" mongodb-java-driver = "4.6.1" objenesis = "3.3" -sitemesh = "2.4.2" +sitemesh = "2.6.0-SNAPSHOT" slf4j = "2.0.9" snakeyaml = "2.0" spock = "2.3-groovy-4.0" diff --git a/settings.gradle b/settings.gradle index c32e459d2f..c39044fd7c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,7 +14,7 @@ include ( 'grace-gsp', 'grace-logging', 'grace-shell', - 'grace-sitemesh', + // 'grace-sitemesh', 'grace-spring', 'grace-spring-boot', 'grace-taglib', From ab166212e5a11491dd04c449dea037084e4235a7 Mon Sep 17 00:00:00 2001 From: Michael Yan Date: Sun, 26 May 2024 22:24:39 +0800 Subject: [PATCH 2/2] Upgrade to SiteMesh 2.6.0-M1 Closes gh-299 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 52405069c8..66546727ea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ methvin-directory-watcher = "0.18.0" mockito = "4.5.1" mongodb-java-driver = "4.6.1" objenesis = "3.3" -sitemesh = "2.6.0-SNAPSHOT" +sitemesh = "2.6.0-M1" slf4j = "2.0.9" snakeyaml = "2.0" spock = "2.3-groovy-4.0"