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

Reply via email to