DEVPLAT-58 - replace refresh profiles with alfresco-maven-plugin goals

This commit is contained in:
Martin Bergljung 2015-05-01 16:18:54 +01:00
parent c79889e662
commit da6c97d857
5 changed files with 434 additions and 137 deletions

View File

@ -79,6 +79,14 @@
<artifactId>maven-plugin-api</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.2</version>
<!-- Annotations are not needed for plugin execution so you
can remove this dependency for execution by using provided scope. -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
@ -105,6 +113,16 @@
<artifactId>maven-core</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>

View File

@ -0,0 +1,287 @@
/**
* Copyright (C) 2015 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.alfresco.maven.plugin;
import org.apache.commons.net.telnet.TelnetClient;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
import java.io.Closeable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract Maven Mojo with generic functionality common to
* both the Refresh Repo and Refresh Share Mojos.
*
* @author martin.bergljung@alfresco.com
* @since 2.1.0
*/
public abstract class AbstractRefreshWebappMojo extends AbstractMojo {
public static final String DEFAULT_USERNAME = "admin";
public static final String DEFAULT_PASSWORD = "admin";
public static final String DEFAULT_HOST = "localhost";
public static final String DEFAULT_PORT = "8080";
/**
* The hostname for where the Alfresco Tomcat server is running.
*/
@Parameter(property = "refreshHost", defaultValue = DEFAULT_USERNAME, alias = "refreshHost")
private String _host = DEFAULT_HOST;
/**
* The port number for where the Alfresco Tomcat server is running.
*/
@Parameter(property = "refreshPort", defaultValue = DEFAULT_USERNAME, alias = "refreshPort")
private String _port = DEFAULT_PORT;
/**
* The username for authenticating against Alfresco Repo.
*/
@Parameter(property = "refreshUsername", defaultValue = DEFAULT_USERNAME, alias = "refreshUsername")
private String _username = DEFAULT_USERNAME;
/**
* The password for authenticating against Alfresco Repo.
*/
@Parameter(property = "refreshPassword", defaultValue = DEFAULT_PASSWORD, alias = "refreshPassword")
private String _password = DEFAULT_PASSWORD;
/**
* The Refresh URL to call, can be either for Share or Repo
*/
private String refreshUrl;
/**
* The Clear Dependency Caches URL to call, currently only applicable to Share.
*/
private String clearDependencyCachesUrl;
/**
* The name of the web application we are refreshing, just for logging purpose
*/
private String refreshWebappName;
/**
* Mojo interface implementation
*/
@Override
public void execute() throws MojoExecutionException {
// Do a ping to see if the server is up, if not, log and just exit
if (!ping()) {
getLog().warn("Connection failed to " + _host + ":" + _port + ", " + getAbortedMsg());
return;
}
executeRefresh();
}
/**
* To be implemented by webapp "refresh" Mojos
*/
protected abstract void executeRefresh();
/**
* The following methods are called by specific refresh mojo implementations
*/
protected void setRefreshUrl(String refreshUrl) {
this.refreshUrl = refreshUrl;
}
protected void setClearDependencyCachesUrl(String clearDependencyCachesUrl) {
this.clearDependencyCachesUrl = clearDependencyCachesUrl;
}
protected void setWebappName(String refreshWebappName) {
this.refreshWebappName = refreshWebappName;
}
/**
* Perform a Refresh of Web Scripts container in webapp.
* Called by specific refresh mojo implementation.
*/
protected void refreshWebScripts() {
// Create the Refresh URL for the Alfresco Tomcat server
URL alfrescoTomcatUrl = buildFinalUrl(refreshUrl);
if (alfrescoTomcatUrl == null) {
getLog().error("Could not build refresh URL for " + refreshWebappName + ", " + getAbortedMsg());
}
// Set up the data we need to POST to the server for the refresh to work
List<NameValuePair> postData = new ArrayList<NameValuePair>();
postData.add(new BasicNameValuePair("reset", "on"));
postData.add(new BasicNameValuePair("submit", "Refresh Web Scripts"));
// Do the refresh
makePostCall(alfrescoTomcatUrl, postData, "Refresh Web Scripts");
}
/**
* Perform a Clear Dependency Caches call on Share webapp.
* Called by specific refresh mojo implementation, currently only applicable to Share webapp.
*/
protected void clearDependencyCaches() {
// Create the Clear Cache URL for the Alfresco Tomcat server
URL alfrescoTomcatUrl = buildFinalUrl(clearDependencyCachesUrl);
if (alfrescoTomcatUrl == null) {
getLog().error("Could not build clear dependency caches URL for " +
refreshWebappName + ", " + getAbortedMsg());
}
// Do the refresh
makePostCall(alfrescoTomcatUrl, null, "Clear Dependency Caches");
}
/**
* Helper method to make a POST request to the Alfresco Webapp
*
* @param alfrescoTomcatUrl the URL for the webapp we want to post to
* @param postData the POST data that should be sent
* @param operation information about the operation we are performing
*/
private void makePostCall(URL alfrescoTomcatUrl, List<NameValuePair> postData, String operation) {
CloseableHttpClient client = null;
CloseableHttpResponse response = null;
try {
// Set up a HTTP POST request to the Alfresco Webapp we are targeting
HttpHost targetHost = new HttpHost(
alfrescoTomcatUrl.getHost(), alfrescoTomcatUrl.getPort(), alfrescoTomcatUrl.getProtocol());
// Set up authentication parameters
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()),
new UsernamePasswordCredentials(_username, _password));
// Create the HTTP Client we will use to make the call
client = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
// Make the call to Refresh the Alfresco Webapp
HttpPost httpPost = new HttpPost(alfrescoTomcatUrl.toURI());
response = client.execute(httpPost);
if (postData != null) {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postData, "UTF-8");
httpPost.setEntity(entity);
}
httpPost.setHeader("Accept-Charset", "iso-8859-1,utf-8");
httpPost.setHeader("Accept-Language", "en-us");
response = client.execute(httpPost);
// If no response, no method has been passed
if (response == null) {
getLog().error("POST request failed to " + alfrescoTomcatUrl.toString() + ", " + getAbortedMsg());
return;
}
// Check if we got a successful response or not
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
getLog().info("Successfull " + operation + " for " + refreshWebappName);
} else {
String reasonPhrase = response.getStatusLine().getReasonPhrase();
getLog().warn("Failed to " + operation + " for " + refreshWebappName + ". Response status: " +
statusCode + ", message: " + reasonPhrase);
}
} catch (Exception ex) {
getLog().error("POST request failed to " + _host + ":" + _port + refreshUrl + ", " + getAbortedMsg());
getLog().error("Exception Msg: " + ex.getMessage());
} finally {
closeQuietly(response);
closeQuietly(client);
}
}
private URL buildFinalUrl(String specificRefreshUrlPath) {
try {
return new URL("http://" + _host + ":" + _port + specificRefreshUrlPath);
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
/**
* Utility method to ping/call the Alfresco Tomcat server and see if it is up (running)
*
* @return true if the Alfresco Tomcat server was reachable and up
*/
private boolean ping() {
try {
URL alfrescoTomcatUrl = buildFinalUrl("");
TelnetClient telnetClient = new TelnetClient();
telnetClient.setDefaultTimeout(500);
telnetClient.connect(alfrescoTomcatUrl.getHost(), alfrescoTomcatUrl.getPort());
return true;
} catch (Exception ex) {
return false;
}
}
/**
* Close down communication objects without any messages
*
* @param closeable
*/
private void closeQuietly(Closeable closeable) {
try {
closeable.close();
} catch (Exception ex) {
// swallow any exceptions
}
}
/**
* Helper to get consistent aborted message
* @return
*/
private String getAbortedMsg() {
return refreshWebappName + " webapp refresh aborted";
}
}

View File

@ -0,0 +1,55 @@
/**
* Copyright (C) 2015 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.alfresco.maven.plugin;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
/**
* Refresh Alfresco Repository (alfresco.war) Mojo.
* Will refresh the Web Script container so new and changed
* Web Scripts are detected.
* <p/>
* It is important to execute the refresh calls in the compile phase,
* otherwise the files will be copied after this and the refresh calls
* will not be recognized.
*
* @author martin.bergljung@alfresco.com
* @since 2.1.0
*/
@Mojo(name = "refresh-repo", defaultPhase = LifecyclePhase.COMPILE)
public class RefreshRepoWebappMojo extends AbstractRefreshWebappMojo {
public static final String DEFAULT_REPO_REFRESH_URL = "/alfresco/service/index";
/**
* The URL to send the POST to when you want to refresh Alfresco Repo Web Scripts container.
*/
@Parameter(property = "refreshRepoUrl", required = true, alias = "refreshRepoUrl")
private String _refreshRepoUrl = DEFAULT_REPO_REFRESH_URL;
public RefreshRepoWebappMojo() {
setRefreshUrl(_refreshRepoUrl);
setWebappName("Alfresco Repository");
}
@Override
protected void executeRefresh() {
refreshWebScripts();
}
}

View File

@ -0,0 +1,67 @@
/**
* Copyright (C) 2015 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.alfresco.maven.plugin;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
/**
* Refresh Alfresco Share (share.war) Mojo.
* Will refresh the Web Script container so new and changed
* Spring Surf Web Scripts are detected.
* Will also clear the dependency caches for web resources (CSS, JS, etc).
* <p/>
* It is important to execute the refresh calls in the compile phase,
* otherwise the files will be copied after this and the refresh calls
* will not be recognized.
*
* @author martin.bergljung@alfresco.com
* @since 2.1.0
*/
@Mojo(name = "refresh-share", defaultPhase = LifecyclePhase.COMPILE)
public class RefreshShareWebappMojo extends AbstractRefreshWebappMojo {
public static final String DEFAULT_SHARE_REFRESH_URL = "/share/page/index";
public static final String DEFAULT_SHARE_CLEAR_DEPENDENCY_CACHES_URL = "/share/page/caches/dependency/clear";
/**
* The URL to send the POST to when you want to refresh Alfresco Share Spring Surf Web Scripts container.
*/
@Parameter(property = "refreshShareUrl", required = true, alias = "refreshShareUrl")
private String _refreshShareUrl = DEFAULT_SHARE_REFRESH_URL;
/**
* The URL to send the POST to when you want to clear dependency caches for the Alfresco Share webapp.
*/
@Parameter(property = "clearCacheShareUrl", required = true, alias = "clearCacheShareUrl")
private String _clearCacheShareUrl = DEFAULT_SHARE_CLEAR_DEPENDENCY_CACHES_URL;
public RefreshShareWebappMojo() {
setRefreshUrl(_refreshShareUrl);
setClearDependencyCachesUrl(_clearCacheShareUrl);
setWebappName("Alfresco Share");
}
/**
* Call the Share Webapp and refresh web scripts and clear caches.
*/
protected void executeRefresh() {
refreshWebScripts();
clearDependencyCaches();
}
}

View File

@ -228,6 +228,13 @@
<extensions>true</extensions>
<configuration>
<snapshotToTimestamp>true</snapshotToTimestamp>
<refreshHost>localhost</refreshHost>
<refreshPort>8080</refreshPort>
<refreshRepoUrl>/alfresco/service/index</refreshRepoUrl>
<refreshShareUrl>/share/page/index</refreshShareUrl>
<clearCacheShareUrl>/share/page/caches/dependency/clear</clearCacheShareUrl>
<refreshUsername>admin</refreshUsername>
<refreshPassword>admin</refreshPassword>
</configuration>
</plugin>
<plugin>
@ -411,25 +418,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<!-- Important to execute the Groovy scripts in the compile phase,
otherwise the files will be copied after this and the web script
refresh will not be recognized.
See the refresh-share and refresh-repo profiles.
-->
<phase>compile</phase>
<goals>
<goal>execute</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
@ -518,124 +506,6 @@
</repositories>
</profile>
<!--
Refresh Spring Surf Web Scripts and clear JS & CSS Dependency Caches for Share.
You will have to activate this profile manually while you are compiling.
For example: $mvn compile -Prefresh-share
-->
<profile>
<id>refresh-share</id>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy.modules.http-builder</groupId>
<artifactId>http-builder</artifactId>
<version>0.7.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<configuration>
<properties>
<tomcatPort>${maven.tomcat.port}</tomcatPort>
</properties>
<!-- See pluginManagement for the rest of the configuration -->
<source>
<![CDATA[
import groovyx.net.http.RESTClient
import groovyx.net.http.HttpResponseException
import org.apache.http.conn.HttpHostConnectException
import static groovyx.net.http.ContentType.*
try {
def share = new RESTClient('http://localhost:' + project.properties.tomcatPort + '/share/')
// Clear Alfresco Share Dependency Caches for JS, CSS, Templates
def clearDependencyCachesPath = 'page/caches/dependency/clear'
share.auth.basic 'admin', 'admin'
def resp = share.post(path: clearDependencyCachesPath)
log.info "\nRequest: Alfresco Share Clear Dependency Caches. Response status: ${resp.status}"
// Refresh Share Web Scripts
refreshWebScriptsPath = 'page/index'
resp = share.post(path: refreshWebScriptsPath, body: [reset: 'on', submit: 'Refresh Web Scripts'], requestContentType: URLENC)
log.info "\nRequest: Alfresco Share Refresh Web Scripts. Response status: ${resp.status}"
} catch (HttpHostConnectException hcex) {
println "Embedded Tomcat is not running, skipping Share Webapp Refresh."
} catch (HttpResponseException ex) {
println "Unexpected response error: ${ex.statusCode}"
}
]]>
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!--
Refresh Repository Web Scripts.
You will have to activate this profile manually while you are compiling.
For example: $mvn compile -Prefresh-repo
-->
<profile>
<id>refresh-repo</id>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy.modules.http-builder</groupId>
<artifactId>http-builder</artifactId>
<version>0.7.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<configuration>
<properties>
<tomcatPort>${maven.tomcat.port}</tomcatPort>
</properties>
<!-- See pluginManagement for the rest of the configuration -->
<source>
<![CDATA[
import groovyx.net.http.RESTClient
import groovyx.net.http.HttpResponseException
import org.apache.http.conn.HttpHostConnectException
import static groovyx.net.http.ContentType.*
try {
def alfresco = new RESTClient('http://localhost:' + project.properties.tomcatPort + '/alfresco/')
// Refresh Alfresco Repo Web Scripts
def refreshWebScriptsPath = 's/index'
alfresco.auth.basic 'admin', 'admin'
def resp = alfresco.post(path: refreshWebScriptsPath, body: [reset: 'on', submit: 'Refresh Web Scripts'], requestContentType: URLENC)
log.info "\nRequest: Alfresco Repo Refresh Web Scripts. Response status: ${resp.status}"
} catch (HttpHostConnectException hcex) {
println "Embedded Tomcat is not running, skipping Repo Webapp Refresh."
} catch (HttpResponseException ex) {
println "Unexpected response error: ${ex.statusCode}"
}
]]>
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!--
Profile related to the stand-alone AMP extension projects.
This profile will enable you to apply a Repo AMP or Share AMP to the Alfresco.WAR or Share.war web application,