Skip to content

Commit

Permalink
Adjust TomcatServerConfigurer to Tomcat 10 API (#144)
Browse files Browse the repository at this point in the history
The WebappLoader lost the ctor with the parent class
loader parameter and instead sets the reference from
the started context.
Alas, it should be possible to directly set the parent
class loader on the context, and it should just function
as before.
  • Loading branch information
f4lco committed Sep 15, 2020
1 parent df894d0 commit b64c6a6
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Gretty
*
* Copyright (C) 2013-2015 Andrey Hihlovskiy and contributors.
*
* See the file "LICENSE" for copying and usage permission.
* See the file "CONTRIBUTORS" for complete list of contributors.
*/
package org.akhikhl.gretty

import groovy.transform.CompileStatic
import groovy.transform.TypeCheckingMode
import org.apache.catalina.WebResourceRoot
import org.apache.catalina.core.StandardContext
import org.apache.catalina.startup.ContextConfig
import org.apache.catalina.startup.Tomcat
import org.apache.catalina.webresources.StandardRoot
import org.apache.tomcat.JarScanner
import org.apache.tomcat.util.descriptor.web.WebXml
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
*
* @author akhikhl
*/
@CompileStatic(TypeCheckingMode.SKIP)
abstract class AbstractTomcatConfigurerImpl implements TomcatConfigurer {

private static final Logger log = LoggerFactory.getLogger(AbstractTomcatConfigurerImpl)

@Override
ContextConfig createContextConfig(URL[] classpathUrls) {

new ContextConfig() {

protected Map<String,WebXml> processJarsForWebFragments(WebXml application) {
def fragments = super.processJarsForWebFragments(application)
// here we enable annotation processing for non-jar urls on the classpath
for(URL url in classpathUrls.findAll { !it.path.endsWith('.jar') && new File(it.path).exists() }) {
WebXml fragment = new WebXml()
fragment.setDistributable(true)
fragment.setURL(url)
fragment.setName(url.toString())
fragments[fragment.getName()] = fragment
}
fragments
}
}
}

@Override
JarScanner createJarScanner(JarScanner jarScanner, JarSkipPatterns skipPatterns) {
new SkipPatternJarScanner(jarScanner, skipPatterns)
}

@Override
void setBaseDir(Tomcat tomcat, File baseDir) {
tomcat.baseDir = baseDir.absolutePath
tomcat.server.setCatalinaHome(baseDir)
tomcat.server.setCatalinaBase(baseDir)
}

@Override
void setResourceBase(StandardContext context, Map webappParams) {

context.setDocBase(webappParams.resourceBase)

WebResourceRoot root = new StandardRoot(context)
context.setResources(root)

if(webappParams.extraResourceBases)
webappParams.extraResourceBases.each { root.createWebResourceSet(WebResourceRoot.ResourceSetType.POST, '/', it, null, '/') }


if (webappParams.webXml)
context.setAltDDName(webappParams.webXml);

Set classpathJarParentDirs = webappParams.webappClassPath.findAll { it.endsWith('.jar') }.collect({
File jarFile = it.startsWith('file:') ? new File(new URI(it)) : new File(it)
jarFile
}) as Set

classpathJarParentDirs.each { File it ->
root.createWebResourceSet(WebResourceRoot.ResourceSetType.POST, '/WEB-INF/lib/' + it.name, it.absolutePath, null, '/')
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Gretty
*
* Copyright (C) 2013-2015 Andrey Hihlovskiy and contributors.
*
* See the file "LICENSE" for copying and usage permission.
* See the file "CONTRIBUTORS" for complete list of contributors.
*/
package org.akhikhl.gretty

import org.apache.tomcat.Jar

import jakarta.servlet.ServletContext
import org.apache.tomcat.JarScanFilter
import org.apache.tomcat.JarScanner
import org.apache.tomcat.JarScannerCallback
import org.apache.tomcat.util.scan.StandardJarScanFilter
import org.apache.tomcat.util.scan.StandardJarScanner
import org.apache.tomcat.JarScanType
import org.apache.tomcat.util.file.Matcher;
import org.slf4j.Logger
import org.slf4j.LoggerFactory

/**
*
* @author akhikhl
*/
class SkipPatternJarScanner extends StandardJarScanner {

private static final Logger log = LoggerFactory.getLogger(SkipPatternJarScanner)

protected final JarScanner jarScanner
protected final JarSkipPatterns skipPatterns

SkipPatternJarScanner(JarScanner jarScanner, JarSkipPatterns skipPatterns) {
assert jarScanner != null
this.jarScanner = jarScanner
this.skipPatterns = skipPatterns
setJarScanFilter(new StandardJarScanFilter())
}

protected JarScannerCallback augmentCallback(final JarScannerCallback callback) {

if(!log.isDebugEnabled())
return callback

return new JarScannerCallback() {

void scan(Jar jar, String webappPath, boolean isWebapp) throws IOException {
log.debug('jarScannerCallback.scan {}, {}, {}', jar, webappPath, isWebapp)
callback.scan(jar, webappPath, isWebapp)
}

void scan(File file, String webappPath, boolean isWebapp) throws IOException {
log.debug('jarScannerCallback.scan {}, {}, {}', file, webappPath, isWebapp)
callback.scan(file, webappPath, isWebapp)
}

void scanWebInfClasses() throws IOException {
log.debug('jarScannerCallback.scanWebInfClasses')
callback.scanWebInfClasses()
}
}
}

protected boolean checkJar(String path) {
String name = path.substring(path.lastIndexOf('/') + 1)
boolean result = !Matcher.matchName(skipPatterns.asSet(), name)
log.debug 'filter jar: {} -> {}', name, result
result
}

@Override
public void setJarScanFilter(JarScanFilter newFilter) {
super.setJarScanFilter(newFilter)
jarScanner.setJarScanFilter(new TomcatJarScanFilter(newFilter))
}

@Override
public void scan(JarScanType scanType, ServletContext context, JarScannerCallback callback) {
jarScanner.scan(scanType, context, augmentCallback(callback))
}

private class TomcatJarScanFilter implements JarScanFilter {

private final JarScanFilter additionalScanFilter

TomcatJarScanFilter(JarScanFilter additionalScanFilter) {
this.additionalScanFilter = additionalScanFilter
}

@Override
boolean check(JarScanType jarScanType, String jarName) {
checkJar(jarName) && (additionalScanFilter == null || additionalScanFilter.check(jarScanType, jarName))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ class TomcatServerConfigurer {
context.addLifecycleListener(new SpringloadedCleanup())
context.setParentClassLoader(classLoader)
context.setJarScanner(configurer.createJarScanner(context.getJarScanner(), new JarSkipPatterns()))
WebappLoader loader = new WebappLoader(classLoader)
context.setParentClassLoader(classLoader)
WebappLoader loader = new WebappLoader()
loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName())
loader.setDelegate(true)
context.setLoader(loader)
Expand Down
10 changes: 10 additions & 0 deletions libs/gretty-runner-tomcat10/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apply from: rootProject.file('common.gradle')

dependencies {
compile project(':libs:gretty-runner-tomcat')
compile "org.apache.tomcat.embed:tomcat-embed-core:$tomcat10_version"
compile "org.apache.tomcat.embed:tomcat-embed-el:$tomcat10_version"
compile "org.apache.tomcat.embed:tomcat-embed-jasper:$tomcat10_version"
compile "org.apache.tomcat.embed:tomcat-embed-websocket:$tomcat10_version"
compile "jakarta.servlet:jakarta.servlet-api:$tomcat10_servlet_api_version"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Gretty
*
* Copyright (C) 2013-2015 Andrey Hihlovskiy and contributors.
*
* See the file "LICENSE" for copying and usage permission.
* See the file "CONTRIBUTORS" for complete list of contributors.
*/
package org.akhikhl.gretty

import org.apache.catalina.Service
import org.apache.catalina.startup.Tomcat

class TomcatConfigurerImpl extends AbstractTomcatConfigurerImpl{

@Override
void setService(Tomcat tomcat, Service service) {

}

@Override
void setEngine(Tomcat tomcat, Service service) {

}
}

0 comments on commit b64c6a6

Please sign in to comment.