diff options
| author | Benjamin Culkin <scorpress@gmail.com> | 2024-05-15 18:59:22 -0400 |
|---|---|---|
| committer | Benjamin Culkin <scorpress@gmail.com> | 2024-05-15 18:59:22 -0400 |
| commit | 68dbb2b7eaae8379bcb185428e46e083a2bf6ecb (patch) | |
| tree | f74400ff9979c1290e74a51c527fb2abda4969ea | |
Initial commit
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | pom.xml | 182 | ||||
| -rw-r--r-- | src/it/settings.xml | 37 | ||||
| -rw-r--r-- | src/it/simple-it/pom.xml | 34 | ||||
| -rw-r--r-- | src/it/simple-it/verify.groovy | 3 | ||||
| -rw-r--r-- | src/main/java/com/ashardalon/maven/tomcat/TomcatMojo.java | 141 | ||||
| -rw-r--r-- | src/test/java/com/ashardalon/maven/tomcat/TomcatMojoTest.java | 61 | ||||
| -rw-r--r-- | src/test/resources/project-to-test/pom.xml | 27 |
8 files changed, 490 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d3b77e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.classpath +.project +.settings/ +target/ +tags @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="UTF-8"?> + + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.ashardalon</groupId> + <artifactId>slim-tomcat-maven-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>maven-plugin</packaging> + + <name>Slim Tomcat Maven Plugin</name> + + <!-- FIXME change it to the project's website --> + <url>http://www.example.com</url> + + <prerequisites> + <maven>${maven.version}</maven> + </prerequisites> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>11</maven.compiler.source> + <maven.compiler.target>11</maven.compiler.target> + <maven.version>3.3.9</maven.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-compat</artifactId> + <version>${maven.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <version>3.6.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-testing</groupId> + <artifactId>maven-plugin-testing-harness</artifactId> + <version>3.3.0</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> + <plugins> + <plugin> + <artifactId>maven-clean-plugin</artifactId> + <version>3.1.0</version> + </plugin> + <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_maven-plugin_packaging --> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.2</version> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.0</version> + </plugin> + <plugin> + <artifactId>maven-plugin-plugin</artifactId> + <version>3.6.0</version> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.22.1</version> + </plugin> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <version>3.0.2</version> + </plugin> + <plugin> + <artifactId>maven-install-plugin</artifactId> + <version>2.5.2</version> + </plugin> + <plugin> + <artifactId>maven-deploy-plugin</artifactId> + <version>2.8.2</version> + </plugin> + <plugin> + <artifactId>maven-invoker-plugin</artifactId> + <version>3.1.0</version> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>3.6.0</version> + <configuration> + <!-- <goalPrefix>maven-archetype-plugin</goalPrefix> --> + <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> + </configuration> + <executions> + <execution> + <id>mojo-descriptor</id> + <goals> + <goal>descriptor</goal> + </goals> + </execution> + <execution> + <id>help-goal</id> + <goals> + <goal>helpmojo</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>run-its</id> + <build> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-invoker-plugin</artifactId> + <version>3.1.0</version> + <configuration> + <debug>true</debug> + <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo> + <pomIncludes> + <pomInclude>*/pom.xml</pomInclude> + </pomIncludes> + <postBuildHookScript>verify</postBuildHookScript> + <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath> + <settingsFile>src/it/settings.xml</settingsFile> + <goals> + <goal>clean</goal> + <goal>test-compile</goal> + </goals> + </configuration> + <executions> + <execution> + <id>integration-test</id> + <goals> + <goal>install</goal> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/src/it/settings.xml b/src/it/settings.xml new file mode 100644 index 0000000..000e726 --- /dev/null +++ b/src/it/settings.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> + + +<settings> + <profiles> + <profile> + <id>it-repo</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + </profiles> +</settings> diff --git a/src/it/simple-it/pom.xml b/src/it/simple-it/pom.xml new file mode 100644 index 0000000..0b7e415 --- /dev/null +++ b/src/it/simple-it/pom.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.ashardalon.it</groupId> + <artifactId>simple-it</artifactId> + <version>1.0-SNAPSHOT</version> + + <description>A simple IT verifying the basic use case.</description> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <groupId>@project.groupId@</groupId> + <artifactId>@project.artifactId@</artifactId> + <version>@project.version@</version> + <executions> + <execution> + <id>touch</id> + <phase>validate</phase> + <goals> + <goal>touch</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/src/it/simple-it/verify.groovy b/src/it/simple-it/verify.groovy new file mode 100644 index 0000000..7b307c7 --- /dev/null +++ b/src/it/simple-it/verify.groovy @@ -0,0 +1,3 @@ +File touchFile = new File( basedir, "target/touch.txt" ); + +assert touchFile.isFile() diff --git a/src/main/java/com/ashardalon/maven/tomcat/TomcatMojo.java b/src/main/java/com/ashardalon/maven/tomcat/TomcatMojo.java new file mode 100644 index 0000000..e2a030d --- /dev/null +++ b/src/main/java/com/ashardalon/maven/tomcat/TomcatMojo.java @@ -0,0 +1,141 @@ +package com.ashardalon.maven.tomcat; + + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.settings.DefaultMavenSettingsBuilder; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; +import org.apache.maven.settings.building.SettingsBuilder; +import org.apache.maven.settings.building.SettingsBuildingException; +import org.apache.maven.settings.building.SettingsBuildingRequest; +import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; +import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; +import org.apache.maven.settings.crypto.SettingsDecrypter; +import org.apache.maven.settings.crypto.SettingsDecryptionRequest; +import org.apache.maven.settings.crypto.SettingsDecryptionResult; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; + +/** + * Goal that uploads a WAR file to a remote tomcat server + * + * @author bjculkin + */ +@Mojo( name = "deploy", defaultPhase = LifecyclePhase.PROCESS_SOURCES ) +public class TomcatMojo extends AbstractMojo { + @Component + SettingsDecrypter decrypter; + @Component + SettingsBuilder builder; + + //---------------------------------------- + // Mojo parameters + //--------------------------------------- + /** + * Location of the file. + */ + @Parameter( defaultValue = "${project.build.directory}/${project.build.finalName}.war", property = "targetWar", required = false ) + private File targetWar; + + @Parameter (property = "serverName", required = true) + private String serverName; + @Parameter (defaultValue = "http://localhost:8080", property = "serverURL", required = true) + private String serverURL; + @Parameter(defaultValue = "${project.build.finalName}", property = "appPath", required = false) + private String appPath; + + public void execute() throws MojoExecutionException { + Path propFile = Paths.get(System.getProperty("user.home"), ".m2", "settings.xml"); + URL url; + try { + url = new URL(serverURL + "/manager/text/deploy?path=" + appPath); + } catch (MalformedURLException e) { + throw new MojoExecutionException("Error creating target URL", e); + } + + try { + SettingsBuildingRequest req = new DefaultSettingsBuildingRequest(); + req.setUserSettingsFile(propFile.toFile()); + Settings settings = builder.build(req).getEffectiveSettings(); + + Server server = settings.getServer(serverName); + + SettingsDecryptionRequest decRequest = new DefaultSettingsDecryptionRequest(server); + SettingsDecryptionResult decrypt = decrypter.decrypt(decRequest); + + Server decServer = decrypt.getServer(); + + String auth = decServer.getUsername() + ":" + decServer.getPassword(); + System.out.println("auth header: " + auth); + byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8)); + String authHeaderValue = "Basic " + new String(encodedAuth); + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + + conn.setRequestMethod("PUT"); + conn.setRequestProperty("Authorization", authHeaderValue); + OutputStream output = conn.getOutputStream(); + + InputStream input = new FileInputStream(targetWar); + int res = input.read(); + while (res != -1) { + output.write(res); + + res = input.read(); + } + output.close(); + input.close(); + + int responseCode = conn.getResponseCode(); + + switch (responseCode) { + case 200: + BufferedReader bis = new BufferedReader(new InputStreamReader(conn.getInputStream())); + char[] buff = new char[4]; + int num = bis.read(buff); + if (num == 2) { // OK + break; + } else { // FAIL + buff = new char[256]; + num = bis.read(buff); + throw new MojoExecutionException("Attempt to deploy app failed: " + new String(buff)); + } + case 401: + String authHeader = conn.getHeaderField("WWW-Authenticate"); + throw new MojoExecutionException("Unable to authenticate to Tomcat (" + authHeader + "). Are your username/password correct?"); + default: + throw new MojoExecutionException("Received unexpected HTTP status code: " + responseCode); + } + } catch (IOException e) { + MojoExecutionException exception = new MojoExecutionException("I/O exception attempting to deploy (URL " + url.toString() + ")"); + exception.initCause(e); + throw exception; + } catch (SettingsBuildingException e) { + MojoExecutionException exception = new MojoExecutionException("Exception partinsing settings attempting to deploy"); + exception.initCause(e); + throw exception; + } + } +} diff --git a/src/test/java/com/ashardalon/maven/tomcat/TomcatMojoTest.java b/src/test/java/com/ashardalon/maven/tomcat/TomcatMojoTest.java new file mode 100644 index 0000000..f2ef215 --- /dev/null +++ b/src/test/java/com/ashardalon/maven/tomcat/TomcatMojoTest.java @@ -0,0 +1,61 @@ +package com.ashardalon.maven.tomcat; + + +import org.apache.maven.plugin.testing.MojoRule; +import org.apache.maven.plugin.testing.WithoutMojo; + +import org.junit.Rule; +import static org.junit.Assert.*; +import org.junit.Test; +import java.io.File; + +public class TomcatMojoTest +{ + @Rule + public MojoRule rule = new MojoRule() + { + @Override + protected void before() throws Throwable + { + } + + @Override + protected void after() + { + } + }; + + /** + * @throws Exception if any + */ + @Test + public void testSomething() + throws Exception + { + File pom = new File( "target/test-classes/project-to-test/" ); + assertNotNull( pom ); + assertTrue( pom.exists() ); + + TomcatMojo myMojo = ( TomcatMojo ) rule.lookupConfiguredMojo( pom, "deploy" ); + assertNotNull( myMojo ); + myMojo.execute(); + + File outputDirectory = ( File ) rule.getVariableValueFromObject( myMojo, "outputDirectory" ); + assertNotNull( outputDirectory ); + assertTrue( outputDirectory.exists() ); + + File touch = new File( outputDirectory, "touch.txt" ); + assertTrue( touch.exists() ); + + } + + /** Do not need the MojoRule. */ + @WithoutMojo + @Test + public void testSomethingWhichDoesNotNeedTheMojoAndProbablyShouldBeExtractedIntoANewClassOfItsOwn() + { + assertTrue( true ); + } + +} + diff --git a/src/test/resources/project-to-test/pom.xml b/src/test/resources/project-to-test/pom.xml new file mode 100644 index 0000000..e7f929d --- /dev/null +++ b/src/test/resources/project-to-test/pom.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.ashardalon</groupId> + <artifactId>slim-tomcat-maven-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>jar</packaging> + <name>Test MyMojo</name> + + <build> + <plugins> + <plugin> + <groupId>com.ashardalon</groupId> + <artifactId>slim-tomcat-maven-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <configuration> + <!-- Specify the MyMojo parameter --> + <serverName>ashardalon-tomcat</serverName> + <targetWar>stachetype.war</targetWar> + </configuration> + </plugin> + </plugins> + </build> +</project> |
