This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit e08dbf4559da7612c4060b68dfee8ce03560ce07 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Feb 11 17:13:52 2021 +0000 Integrate Java EE -> Jakarta EE migration with automatic deployment --- build.properties.default | 12 +++ build.xml | 22 +++++ conf/catalina.properties | 1 + java/org/apache/catalina/startup/HostConfig.java | 109 +++++++++++++++++++++ .../catalina/startup/LocalStrings.properties | 1 + webapps/docs/changelog.xml | 11 ++- 6 files changed, 154 insertions(+), 2 deletions(-) diff --git a/build.properties.default b/build.properties.default index 7253e7a..6d4476b 100644 --- a/build.properties.default +++ b/build.properties.default @@ -303,3 +303,15 @@ osgi-annotations.checksum.value=153054f987534244f95a399539b11375|b6e802bceba0682 osgi-annotations.home=${base.path}/osgi-annotations-${osgi-annotations.version} osgi-annotations.jar=${osgi-annotations.home}/org.osgi.annotation.bundle-${osgi-annotations.version}.jar osgi-annotations.loc=${base-maven.loc}/org/osgi/org.osgi.annotation.bundle/${osgi-annotations.version}/org.osgi.annotation.bundle-${osgi-annotations.version}.jar + +# ----- Tomcat Migration Tool for Jakarta EE ----- +migration-lib.version=0.2.0 + +# checksums for jakartaee-migration-0.2.0-shaded.jar +migration-lib.checksum.enabled=true +migration-lib.checksum.algorithm=MD5|SHA-1 +migration-lib.checksum.value=c7dc838f46901157722ac2f49af854c8|73f53ba52e443f0e992a2aa57d42927d884709eb + +migration-lib.home=${base.path}/migration-${migration-lib.version} +migration-lib.jar=${migration-lib.home}/jakartaee-migration-${migration-lib.version}-shaded.jar +migration-lib.loc=${base-maven.loc}/org/apache/tomcat/jakartaee-migration/${migration-lib.version}/jakartaee-migration-${migration-lib.version}-shaded.jar diff --git a/build.xml b/build.xml index 98d180e..a4c9d05 100644 --- a/build.xml +++ b/build.xml @@ -240,6 +240,7 @@ <pathelement location="${jdt.jar}"/> <pathelement location="${jaxrpc-lib.jar}"/> <pathelement location="${wsdl4j-lib.jar}"/> + <pathelement location="${migration-lib.jar}"/> </path> <path id="tomcat.classpath"> @@ -1462,6 +1463,17 @@ </delete> <copy file="${jdt.jar}" todir="${tomcat.build}/lib"/> + <!-- Delete all other versions of Tomcat Migration Tool for Jakarta EE and copy the current one --> + <local name="migration.jar.filename" /> + <basename property="migration.jar.filename" file="${migration-lib.jar}"/> + <delete verbose="true"> + <fileset dir="${tomcat.build}/lib"> + <include name="jakartaee-migration-*.jar"/> + <exclude name="${migration-lib.jar.filename}"/> + </fileset> + </delete> + <copy file="${migration-lib.jar}" todir="${tomcat.build}/lib"/> + <!-- Add sources for examples --> <antcall target="examples-sources" /> </target> @@ -3125,6 +3137,16 @@ skip.installer property in build.properties" /> <param name="checksum.value" value="${wsdl4j-lib.checksum.value}"/> </antcall> + <!-- Tomcat Migration Tool for Jakarta EE --> + <antcall target="downloadfile"> + <param name="sourcefile" value="${migration-lib.loc}"/> + <param name="destfile" value="${migration-lib.jar}"/> + <param name="destdir" value="${migration-lib.home}"/> + <param name="checksum.enabled" value="${migration-lib.checksum.enabled}"/> + <param name="checksum.algorithm" value="${migration-lib.checksum.algorithm}"/> + <param name="checksum.value" value="${migration-lib.checksum.value}"/> + </antcall> + </target> <target name="download-test-compile" diff --git a/conf/catalina.properties b/conf/catalina.properties index cff2aa2..012d8fd 100644 --- a/conf/catalina.properties +++ b/conf/catalina.properties @@ -144,6 +144,7 @@ hamcrest-*.jar,\ hibernate*.jar,\ httpclient*.jar,\ icu4j-*.jar,\ +jakartaee-migration-*.jar,\ jasper-el.jar,\ jasper.jar,\ jaspic-api.jar,\ diff --git a/java/org/apache/catalina/startup/HostConfig.java b/java/org/apache/catalina/startup/HostConfig.java index 2079117..1aac2df 100644 --- a/java/org/apache/catalina/startup/HostConfig.java +++ b/java/org/apache/catalina/startup/HostConfig.java @@ -68,6 +68,7 @@ import org.apache.catalina.util.ContextName; import org.apache.catalina.util.IOTools; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jakartaee.Migration; import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.buf.UriUtil; import org.apache.tomcat.util.digester.Digester; @@ -465,6 +466,8 @@ public class HostConfig implements LifecycleListener { * in our "application root" directory. */ protected void deployApps() { + // Migrate legacy Java EE apps from legacyAppBase + migrateLegacyApps(); File appBase = host.getAppBaseFile(); File configBase = host.getConfigBaseFile(); String[] filteredAppPaths = filterAppPaths(appBase.list()); @@ -1224,6 +1227,87 @@ public class HostConfig implements LifecycleListener { } + protected void migrateLegacyApps() { + File appBase = host.getAppBaseFile(); + File legacyAppBase = host.getLegacyAppBaseFile(); + if (!legacyAppBase.isDirectory()) { + return; + } + + ExecutorService es = host.getStartStopExecutor(); + List<Future<?>> results = new ArrayList<>(); + + String[] migrationCandidates = legacyAppBase.list(); + for (String migrationCandidate : migrationCandidates) { + File source = new File(legacyAppBase, migrationCandidate); + File destination = new File(appBase, migrationCandidate); + + ContextName cn; + if (source.lastModified() > destination.lastModified()) { + if (source.isFile() && source.getName().toLowerCase(Locale.ENGLISH).endsWith(".war")) { + cn = new ContextName(migrationCandidate, true); + } else if (source.isDirectory()) { + cn = new ContextName(migrationCandidate, false); + } else { + continue; + } + + if (tryAddServiced(cn.getBaseName())) { + try { + // MigrateApp will call removeServiced + results.add(es.submit(new MigrateApp(this, cn, source, destination))); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + removeServiced(cn.getName()); + throw t; + } + } + } + } + + for (Future<?> result : results) { + try { + result.get(); + } catch (Exception e) { + log.error(sm.getString("hostConfig.migrateApp.threaded.error"), e); + } + } + } + + + protected void migrateLegacyApp(File source, File destination) { + File tempNew = null; + File tempOld = null; + try { + tempNew = File.createTempFile("new", null, host.getLegacyAppBaseFile()); + tempOld = File.createTempFile("old", null, host.getLegacyAppBaseFile()); + + // The use of defaults is deliberate here to avoid having to + // recreate every configuration option on the host. Better to change + // the defaults if necessary than to start adding configuration + // options. Users that need non-default options can convert manually + // via migration.[sh|bat] + Migration migration = new Migration(); + migration.setSource(source); + migration.setDestination(tempNew); + migration.execute(); + + // Use rename + destination.renameTo(tempOld); + tempNew.renameTo(destination); + ExpandWar.delete(tempOld); + + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.warn("Migration failure", t); + } finally { + if (tempNew != null && tempNew.exists()) { + ExpandWar.delete(tempNew); + } + } + } + + /** * Check if a webapp is already deployed in this host. * @@ -1930,6 +2014,31 @@ public class HostConfig implements LifecycleListener { } + private static class MigrateApp implements Runnable { + + private HostConfig config; + private ContextName cn; + private File source; + private File destination; + + public MigrateApp(HostConfig config, ContextName cn, File source, File destination) { + this.config = config; + this.cn = cn; + this.source = source; + this.destination = destination; + } + + @Override + public void run() { + try { + config.migrateLegacyApp(source, destination); + } finally { + config.removeServiced(cn.getName()); + } + } + } + + /* * The purpose of this class is to provide a way for HostConfig to get * a Context to delete an expanded WAR after the Context stops. This is to diff --git a/java/org/apache/catalina/startup/LocalStrings.properties b/java/org/apache/catalina/startup/LocalStrings.properties index 27c7c9b..e31a53f 100644 --- a/java/org/apache/catalina/startup/LocalStrings.properties +++ b/java/org/apache/catalina/startup/LocalStrings.properties @@ -136,6 +136,7 @@ hostConfig.ignorePath=Ignoring path [{0}] in appBase for automatic deployment hostConfig.illegalWarName=The war name [{0}] is invalid. The archive will be ignored. hostConfig.jmx.register=Register context [{0}] failed hostConfig.jmx.unregister=Unregister context [{0}] failed +hostConfig.migrateApp.threaded.error=Error waiting for multi-thread migration of legacy applications to complete hostConfig.reload=Reloading context [{0}] hostConfig.resourceNotAbsolute=Unable to remove resource from context [{0}] since [{1}] is not an absolute path hostConfig.start=HostConfig: Processing START diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 6a2b77e..0d19158 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -121,12 +121,19 @@ of use in JMX descriptors. (remm) </fix> <update> - Allow the loader to directly use the JakartaEE migration tool as a - <code>ClassFileTransformer</code> using the + Allow the loader to directly use the Tomcat Migration Tool for JakartaEE + as a <code>ClassFileTransformer</code> using the <code>jakartaConverter</code> attribute. This only supports javax to jakarta conversion for classes, not for classloader resources or static files. (remm) </update> + <add> + Integrate the Tomcat Migration Tool for JakartaEE at deployment time. + Java EE web applications placed in the <code>webapps-ee</code> directory + will be migrated to Jakarta EE 9 and placed in the <code>webapps</code> + where it will be deployed (or not) based on the current settings for + automatic deployment. (markt) + </add> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org