r577 - in trunk: . src/main/java/org/nuiton src/main/java/org/nuiton/io src/main/java/org/nuiton/io/rest src/main/java/org/nuiton/mail src/main/java/org/nuiton/mail/plugin src/main/java/org/nuiton/plugin src/main/java/org/nuiton/util src/main/resources/META-INF src/main/resources/META-INF/plexus src/test/java/org/nuiton src/test/java/org/nuiton/mail src/test/java/org/nuiton/mail/plugin src/test/resources/org/nuiton src/test/resources/org/nuiton/mail src/test/resources/org/nuito
Author: tchemit Date: 2009-09-19 18:29:35 +0200 (Sat, 19 Sep 2009) New Revision: 577 Added: trunk/src/main/java/org/nuiton/io/rest/ trunk/src/main/java/org/nuiton/io/rest/DefaultRestClientConfiguration.java trunk/src/main/java/org/nuiton/io/rest/RestClient.java trunk/src/main/java/org/nuiton/io/rest/RestClientConfiguration.java trunk/src/main/java/org/nuiton/io/rest/RestDataNotFoundException.java trunk/src/main/java/org/nuiton/io/rest/RestException.java trunk/src/main/java/org/nuiton/io/rest/RestRequest.java trunk/src/main/java/org/nuiton/io/rest/RestRequestBuilder.java trunk/src/main/java/org/nuiton/io/rest/RestSession.java trunk/src/main/java/org/nuiton/mail/ trunk/src/main/java/org/nuiton/mail/MailSender.java trunk/src/main/java/org/nuiton/mail/ProjectJavamailMailSender.java trunk/src/main/java/org/nuiton/mail/plugin/ trunk/src/main/java/org/nuiton/mail/plugin/SendEmailMojo.java trunk/src/main/java/org/nuiton/plugin/CheckProjectFilesPlugin.java trunk/src/main/java/org/nuiton/plugin/CollectFilesMojo.java trunk/src/main/resources/META-INF/plexus/ trunk/src/main/resources/META-INF/plexus/components.xml trunk/src/test/java/org/nuiton/mail/ trunk/src/test/java/org/nuiton/mail/plugin/ trunk/src/test/java/org/nuiton/mail/plugin/SendEmailMojoTest.java trunk/src/test/resources/org/nuiton/mail/ trunk/src/test/resources/org/nuiton/mail/plugin/ trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/ trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/mailContentFile.txt trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/sendEmail.xml trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/skipSendEmail.xml Removed: trunk/src/main/java/org/nuiton/CheckProjectFilesPlugin.java Modified: trunk/pom.xml trunk/src/main/java/org/nuiton/plugin/AbstractPlugin.java trunk/src/main/java/org/nuiton/util/PluginHelper.java Log: [EVOLUTION #42] : ajout d'un goal pour collecter des donn?\195?\169es [EVOLUTION #43] : ajout d'un goal pour envoyer des mails [EVOLUTION #44] : ajout d'un client REST [AUtre...] - optimisation des d?\195?\169pendances, deplacement d'un goal Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2009-09-19 16:19:34 UTC (rev 576) +++ trunk/pom.xml 2009-09-19 16:29:35 UTC (rev 577) @@ -22,19 +22,86 @@ <version>1.1.1</version> </dependency> + <!-- fix dependency pb in xpp3Reader (need at least version > 2.2) --> <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.4</version> + </dependency> + + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + <version>3.1</version> + </dependency> + + <dependency> <groupId>org.apache.maven.shared</groupId> <artifactId>maven-dependency-tree</artifactId> <version>1.2</version> </dependency> + <!-- plexus --> + <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-utils</artifactId> <version>1.5.15</version> - <!--scope>provided</scope--> </dependency> + <dependency> + <optional>true</optional> + <groupId>org.sonatype.plexus</groupId> + <artifactId>plexus-sec-dispatcher</artifactId> + <version>1.3.1</version> + </dependency> + + <dependency> + <optional>true</optional> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-container-default</artifactId> + <version>1.0-alpha-9-stable-1</version> + </dependency> + + <dependency> + <optional>true</optional> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-api</artifactId> + <version>1.0-alpha-2</version> + <exclusions> + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-container-default</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <optional>true</optional> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-javamail</artifactId> + <version>1.0-alpha-2</version> + <exclusions> + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-container-default</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <optional>true</optional> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-simple</artifactId> + <version>1.0-alpha-2</version> + <exclusions> + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-container-default</artifactId> + </exclusion> + </exclusions> + </dependency> + <!-- provided dependencies --> <dependency> @@ -67,6 +134,17 @@ <artifactId>velocity</artifactId> <version>1.6.2</version> </dependency> + + <!-- forces use of javamail 1.4 since it's the only version available in the repo. We should remove this as soon + as the dependency in plexus-mail-sender-javamail will be updated + --> + <dependency> + <optional>true</optional> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + <version>1.4</version> + </dependency> + <!-- tests dependencies --> @@ -112,8 +190,7 @@ <developer> <name>Eric Chatellier</name> <id>echatellier</id> - <!--<email>chatellier@codelutin.com</email>--> - <email>http://mailhide.recaptcha.net/d?k=01qLvyYlchVJ90Gg2lfYg-5A==&c=8mzC6s-mCjNM1_m1SA7_-of7jSjrc3-gZDy4QhkY2HA=</email> + <email>chatellier@codelutin.com</email> <organization>CodeLutin</organization> <timezone>+2</timezone> <roles> @@ -124,8 +201,7 @@ <developer> <name>Tony Chemit</name> <id>tchemit</id> - <!--<email>chemit@codelutin.com</email>--> - <email>http://mailhide.recaptcha.net/d?k=01qLvyYlchVJ90Gg2lfYg-5A==&c=Dg32g6wafXimR6aZsnwloBZMGm48dAcjxiDYdzUMzc4=</email> + <email>chemit@codelutin.com</email> <organization>CodeLutin</organization> <timezone>+2</timezone> <roles> @@ -524,6 +600,47 @@ </plugins> </build> </profile> + + <!-- do not execute tests (generaly a bad idea...) --> + <profile> + <id>notests</id> + <activation> + <activeByDefault>false</activeByDefault> + </activation> + <properties> + <maven.test.skip>true</maven.test.skip> + </properties> + </profile> + <!-- do not build reports (speedup site generation in dev) --> + <profile> + <id>noreports</id> + <activation> + <activeByDefault>false</activeByDefault> + </activation> + <properties> + <maven.reports.generate>false</maven.reports.generate> + </properties> + </profile> + <!-- do not build dependencies detail in maven-project-info-report (speedup site generation in dev) --> + <profile> + <id>nodepdetails</id> + <activation> + <activeByDefault>false</activeByDefault> + </activation> + <properties> + <maven.reports.dependencyDetailsEnabled>false</maven.reports.dependencyDetailsEnabled> + </properties> + </profile> + <!-- do not build locations of dependencies in maven-project-info-report (speedup site generation in dev) --> + <profile> + <id>nodeplocations</id> + <activation> + <activeByDefault>false</activeByDefault> + </activation> + <properties> + <maven.reports.dependencyLocationsEnabled>false</maven.reports.dependencyLocationsEnabled> + </properties> + </profile> </profiles> </project> Deleted: trunk/src/main/java/org/nuiton/CheckProjectFilesPlugin.java =================================================================== --- trunk/src/main/java/org/nuiton/CheckProjectFilesPlugin.java 2009-09-19 16:19:34 UTC (rev 576) +++ trunk/src/main/java/org/nuiton/CheckProjectFilesPlugin.java 2009-09-19 16:29:35 UTC (rev 577) @@ -1,103 +0,0 @@ -/* - * *##% - * Maven helper plugin - * Copyright (C) 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* - */ -package org.nuiton; - -import java.io.File; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.project.MavenProject; - -/** - * Check that : - * - * 1) the changelog exists on standalone module or root module of a - * multi-module project. - * 2) any project module has a README.txt and LICENSE.txt file - * - * @goal check-project-files - * @requiresProject true - * @phase validate - * @author chemit - * @since 1.0.2 - */ -public class CheckProjectFilesPlugin extends AbstractMojo { - - /** - * Dependance du projet. - * - * @parameter default-value="${project}" - * @required - * @since 1.0.2 - */ - protected MavenProject project; - /** - * Un flag pour activer le mode verbeux. - * - * @parameter expression="${helper.verbose}" default-value="${maven.verbose}" - * @since 1.0.2 - */ - protected boolean verbose; - - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - checkChangelogFile(); - checkReadmeFile(); - checkLicenseFile(); - } - - protected void checkChangelogFile() throws MojoExecutionException { - if (project.isExecutionRoot()) { - File f = new File(project.getBasedir(), "changelog.txt"); - if (!f.exists()) { - throw new MojoExecutionException("the module " + project.getName() + " requires the file " + f.getAbsolutePath()); - } else { - if (verbose) { - getLog().info("changelog file dectected : " + f.getAbsolutePath()); - } - } - } else { - getLog().info("changelog.txt is not required for module " + project.getName() + " (not a root module)"); - } - } - - protected void checkReadmeFile() throws MojoExecutionException { - File f = new File(project.getBasedir(), "README.txt"); - if (!f.exists()) { - throw new MojoExecutionException("the module " + project.getName() + " requires the file " + f.getAbsolutePath()); - } else { - if (verbose) { - getLog().info("readme file dectected : " + f.getAbsolutePath()); - } - } - } - - protected void checkLicenseFile() throws MojoExecutionException { - File f = new File(project.getBasedir(), "LICENSE.txt"); - if (!f.exists()) { - throw new MojoExecutionException("the module " + project.getName() + " requires the file " + f.getAbsolutePath()); - } else { - if (verbose) { - getLog().info("license file dectected : " + f.getAbsolutePath()); - } - } - } -} Added: trunk/src/main/java/org/nuiton/io/rest/DefaultRestClientConfiguration.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/DefaultRestClientConfiguration.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/DefaultRestClientConfiguration.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,79 @@ +package org.nuiton.io.rest; + +import java.net.URL; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +/** + * + * @author chemit + */ +public class DefaultRestClientConfiguration implements RestClientConfiguration { + + URL restUrl; + String restUsername; + String restPassword; + boolean verbose; + String encoding; + + @Override + public String getEncoding() { + return encoding; + } + + @Override + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + @Override + public String getRestPassword() { + return restPassword; + } + + @Override + public void setRestPassword(String restPassword) { + this.restPassword = restPassword; + } + + @Override + public URL getRestUrl() { + return restUrl; + } + + @Override + public void setRestUrl(URL restUrl) { + this.restUrl = restUrl; + } + + @Override + public String getRestUsername() { + return restUsername; + } + + @Override + public void setRestUsername(String restUsername) { + this.restUsername = restUsername; + } + + @Override + public boolean isVerbose() { + return verbose; + } + + @Override + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append("redmineUrl", restUrl); + b.append("redmineUsername", restUsername); + b.append("redminePassword", "***"); + b.append("encoding", encoding); + b.append("verbose", verbose); + return b.toString(); + } +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/DefaultRestClientConfiguration.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/rest/RestClient.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/RestClient.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/RestClient.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,128 @@ +package org.nuiton.io.rest; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.TreeMap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author chemit + */ +public abstract class RestClient { + + private static final Log log = LogFactory.getLog(RestClient.class); + protected final RestClientConfiguration configuration; + protected RestSession session; + protected Map<String, RestRequestBuilder> requestBuilders; + + protected abstract void open(RestSession session) throws IOException; + + protected abstract void close(RestSession session) throws IOException; + + public RestClient(RestClientConfiguration configuration) { + this.configuration = configuration; + this.requestBuilders = new TreeMap<String, RestRequestBuilder>(); + } + + public void addRequestBuilder(RestRequestBuilder builder) { + String name = builder.getName(); + if (requestBuilders.containsKey(name)) { + throw new IllegalArgumentException("a request builder with name " + name + " already exists."); + } + requestBuilders.put(name, builder); + } + + public RestRequest getRequest(String id, Object... args) { + RestRequestBuilder builder = requestBuilders.get(id); + if (builder == null) { + // pas de builder de requete... + return null; + } + RestRequest r = builder.create(args); + return r; + } + + public InputStream askData(RestRequest request) throws RestException { + if (!isOpen()) { + throw new IllegalStateException("the client is not opened"); + } + + try { + InputStream in = session.askData(request); + return in; + } catch (IOException e) { + throw new RestException("could not ask data to server to reason " + e.getMessage(), e); + } + } + + public InputStream sendData(RestRequest request) throws RestException { + if (!isOpen()) { + throw new IllegalStateException("the client is not opened"); + } + + try { + InputStream in = session.sendData(request); + return in; + } catch (IOException e) { + throw new RestException("could not send data to server for reason " + e.getMessage(), e); + } + } + + public void open() throws RestException { + + if (isOpen()) { + return; + } + + try { + + session = new RestSession(configuration); + + open(session); + + session.setOpen(true); + } catch (Exception e) { + if (session != null) { + try { + try { + close(session); + } catch (IOException ex) { + // not important one... + } + } finally { + session = null; + } + } + throw new RestException("could not open rest client for reason " + e.getMessage(), e); + } + } + + public void close() throws RestException { + if (!isOpen()) { + return; + } + + try { + close(session); + } catch (Exception e) { + throw new RestException("could not close client for reason " + e.getMessage(), e); + } finally { + session = null; + } + } + + public boolean isOpen() { + return session != null; + } + + public RestSession getSession() { + return session; + } + + public RestClientConfiguration getConfiguration() { + return configuration; + } +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/RestClient.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/rest/RestClientConfiguration.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/RestClientConfiguration.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/RestClientConfiguration.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,30 @@ +package org.nuiton.io.rest; + +import java.net.URL; + +/** + * + * @author chemit + */ +public interface RestClientConfiguration { + + URL getRestUrl(); + + String getEncoding(); + + String getRestUsername(); + + String getRestPassword(); + + boolean isVerbose(); + + void setRestUrl(URL restUrl); + + void setRestPassword(String restPassword); + + void setRestUsername(String restUsername); + + void setEncoding(String encoding); + + void setVerbose(boolean verbose); +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/RestClientConfiguration.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/rest/RestDataNotFoundException.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/RestDataNotFoundException.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/RestDataNotFoundException.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,29 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.nuiton.io.rest; + +/** + * + * @author chemit + */ +public class RestDataNotFoundException extends RestException { + + private static final long serialVersionUID = 1L; + + public RestDataNotFoundException() { + } + + public RestDataNotFoundException(String message) { + super(message); + } + + public RestDataNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public RestDataNotFoundException(Throwable cause) { + super(cause); + } +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/RestDataNotFoundException.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/rest/RestException.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/RestException.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/RestException.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,27 @@ +package org.nuiton.io.rest; + +/** + * Base exception for any excpeiton in rest service. + * + * @author chemit + * @since 1.0.0 + */ +public class RestException extends Exception { + + private static final long serialVersionUID = 1L; + + public RestException(Throwable cause) { + super(cause); + } + + public RestException(String message, Throwable cause) { + super(message, cause); + } + + public RestException(String message) { + super(message); + } + + public RestException() { + } +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/RestException.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/rest/RestRequest.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/RestRequest.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/RestRequest.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,17 @@ +package org.nuiton.io.rest; + +import java.io.File; +import java.util.Map; + +/** + * + * @author chemit + */ +public interface RestRequest { + + String[] getPath(); + + String[] getParameters(); + + Map<String, File> getAttachments(); +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/RestRequest.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/rest/RestRequestBuilder.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/RestRequestBuilder.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/RestRequestBuilder.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,12 @@ +package org.nuiton.io.rest; + +/** + * + * @author chemit + */ +public interface RestRequestBuilder { + + String getName(); + + RestRequest create(Object... args); +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/RestRequestBuilder.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/rest/RestSession.java =================================================================== --- trunk/src/main/java/org/nuiton/io/rest/RestSession.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/rest/RestSession.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,224 @@ +package org.nuiton.io.rest; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.apache.commons.httpclient.Cookie; +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpConnection; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.StatusLine; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author chemit + */ +public class RestSession { + + protected HttpClient client; + protected static final Log log = LogFactory.getLog(RestSession.class); + protected boolean open; + protected boolean showRequest; + protected RestClientConfiguration configuration; + + RestSession(RestClientConfiguration configuration) { + this.showRequest = configuration.isVerbose(); + this.configuration = configuration; + this.client = new HttpClient(); + HostConfiguration hostConfiguration = new HostConfiguration(); + hostConfiguration.setHost(configuration.getRestUrl().getHost()); + this.client.setHostConfiguration(hostConfiguration); + this.client.setState(new HttpState()); + } + + public InputStream askData(RestRequest request) throws RestException, IOException { + + if (!open) { + throw new IllegalStateException("the session is not opened"); + } + HttpMethod gm; + + gm = doRequest(request); + + StatusLine sl = gm.getStatusLine(); + int statusCode = sl.getStatusCode(); + + if (log.isDebugEnabled()) { + log.debug("status code " + statusCode + " for " + gm.getPath()); + } + + if (statusCode == HttpStatus.SC_NOT_FOUND) { + throw new RestDataNotFoundException("could not retreave some datas : " + gm.getResponseBodyAsString()); + } + + if (statusCode != HttpStatus.SC_OK) { + log.error(gm.getResponseBodyAsString()); + releaseConnection(getConnection()); + throw new RestException("Got error code <" + statusCode + ":" + sl.getReasonPhrase() + "> on " + gm.getPath()); + } + InputStream stream = gm.getResponseBodyAsStream(); + return stream; + } + + public InputStream sendData(RestRequest request) throws RestException, IOException { + + if (!open) { + throw new IllegalStateException("the session is not opened"); + } + + HttpMethod gm = doRequest(request); + + StatusLine sl = gm.getStatusLine(); + int statusCode = sl.getStatusCode(); + + if (log.isDebugEnabled()) { + log.debug("status code " + statusCode + " for " + gm.getPath()); + } + + if (statusCode != HttpStatus.SC_OK) { + log.error(gm.getResponseBodyAsString()); + releaseConnection(getConnection()); + throw new RestException("Got error code <" + statusCode + ":" + sl.getReasonPhrase() + "> on " + gm.getPath()); + } + + InputStream stream = gm.getResponseBodyAsStream(); + return stream; + } + + public void setOpen(boolean open) { + this.open = open; + } + + public void close() throws IOException { + client.getState().clearCookies(); + releaseConnection(getConnection()); + this.open = false; + } + + protected void releaseConnection(HttpConnection connection) { + if (connection != null && connection.isOpen()) { + client.getHttpConnectionManager().releaseConnection(connection); + } + } + + protected HttpConnection getConnection() { + return client.getHttpConnectionManager().getConnection(client.getHostConfiguration()); + } + + protected String getUri(String... paths) { + String uri = client.getHostConfiguration().getHostURL(); + for (String path : paths) { + uri += '/' + path; + } + return uri; + } + + public HttpMethod doRequest(RestRequest request) throws IOException { + + String uri = getUri(request.getPath()); + String[] parameters = request.getParameters(); + Map<String, File> attachments = request.getAttachments(); + + if (showRequest) { + log.info("doRequest " + uri); + } + if (log.isDebugEnabled()) { + log.debug("doRequest with parameters : " + Arrays.toString(parameters)); + } + PostMethod gm = new PostMethod(uri); + if (open) { + Cookie[] cookies = client.getState().getCookies(); + for (Cookie c : cookies) { + if (log.isDebugEnabled()) { + log.debug("push cookie : " + c.getName() + "=" + c.getValue()); + } + gm.addRequestHeader("Cookie", c.toExternalForm()); + } + } + + if (attachments == null) { + + // not a multi-part request + + if (parameters.length > 0) { + + // add parameters + + int nbParams = parameters.length / 2; + for (int i = 0; i < nbParams; i++) { + String key = parameters[2 * i]; + String value = parameters[2 * i + 1]; + if (value == null) { + if (log.isDebugEnabled()) { + log.debug("skip null parameter " + key); + } + continue; + } + gm.addParameter(key, value); + } + } + } else { + + // multi-part request + + List<Part> paramParts = new ArrayList<Part>(); + + if (parameters.length > 0) { + + // add parameters as part of multi-part + + int nbParams = parameters.length / 2; + for (int i = 0; i < nbParams; i++) { + String key = parameters[2 * i]; + String value = parameters[2 * i + 1]; + if (value == null) { + if (log.isDebugEnabled()) { + log.debug("skip null parameter " + key); + } + continue; + } + paramParts.add(new StringPart(key, value)); + } + } + + // add file parts + for (Entry<String, File> entry : attachments.entrySet()) { + String key = entry.getKey(); + File file = entry.getValue(); + paramParts.add(new FilePart(key, file.getName(), file)); + } + + Part[] parts = paramParts.toArray(new Part[paramParts.size()]); + + MultipartRequestEntity entity = new MultipartRequestEntity(parts, gm.getParams()); + gm.setRequestEntity(entity); +// gm.addRequestHeader("content-type", "multipart/form-data"); + gm.addRequestHeader("content-type", entity.getContentType()); + gm.addRequestHeader("content-length", entity.getContentLength() + ""); + if (showRequest) { + log.info("content-type : " + entity.getContentType() + ", content-length : " + entity.getContentLength()); + } + + } + + client.executeMethod(gm); + + return gm; + } +} Property changes on: trunk/src/main/java/org/nuiton/io/rest/RestSession.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/mail/MailSender.java =================================================================== --- trunk/src/main/java/org/nuiton/mail/MailSender.java (rev 0) +++ trunk/src/main/java/org/nuiton/mail/MailSender.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,72 @@ +package org.nuiton.mail; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/** + * Defines the sender of the announcement if the list of developer is empty or + * if the sender is not a member of the development team. + * + * @author Stephane Nicoll + */ +public class MailSender +{ + + private String name; + + private String email; + + + public MailSender() + { + super(); + } + + + public MailSender( String name, String email ) + { + this.name = name; + this.email = email; + } + + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + public String getEmail() + { + return email; + } + + public void setEmail( String email ) + { + this.email = email; + } + + public String toString() + { + return getName() + " (" + getEmail() + ")"; + } +} Property changes on: trunk/src/main/java/org/nuiton/mail/MailSender.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/mail/ProjectJavamailMailSender.java =================================================================== --- trunk/src/main/java/org/nuiton/mail/ProjectJavamailMailSender.java (rev 0) +++ trunk/src/main/java/org/nuiton/mail/ProjectJavamailMailSender.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,200 @@ +package org.nuiton.mail; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +import java.security.Security; +import java.util.Date; +import java.util.Iterator; +import java.util.Properties; + +import javax.mail.Authenticator; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; + +import org.codehaus.plexus.mailsender.AbstractMailSender; +import org.codehaus.plexus.mailsender.MailMessage; +import org.codehaus.plexus.mailsender.MailSenderException; +import org.codehaus.plexus.mailsender.util.DateFormatUtils; +import org.codehaus.plexus.util.StringUtils; + +/** + * Helper class for sending email. + */ +public class ProjectJavamailMailSender + extends AbstractMailSender +{ + private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + private Properties userProperties; + + private Properties props; + + // ---------------------------------------------------------------------- + // Component Lifecycle + // ---------------------------------------------------------------------- + + public void initialize() + { + if ( StringUtils.isEmpty( getSmtpHost() ) ) + { + System.out.println( "Error in configuration: Missing smtpHost." ); + } + + if ( getSmtpPort() == 0 ) + { + setSmtpPort( DEFAULT_SMTP_PORT ); + } + + props = new Properties(); + + props.put( "mail.smtp.host", getSmtpHost() ); + + props.put( "mail.smtp.port", String.valueOf( getSmtpPort() ) ); + + if ( getUsername() != null ) + { + props.put( "mail.smtp.auth", "true" ); + } + + props.put( "mail.debug", String.valueOf( getLogger().isDebugEnabled() ) ); + + if ( isSslMode() ) + { + Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider() ); + + props.put( "mail.smtp.socketFactory.port", String.valueOf( getSmtpPort() ) ); + + props.put( "mail.smtp.socketFactory.class", SSL_FACTORY ); + + props.put( "mail.smtp.socketFactory.fallback", "false" ); + } + + if ( userProperties != null ) + { + for ( Iterator i = userProperties.keySet().iterator(); i.hasNext(); ) + { + String key = (String) i.next(); + + String value = userProperties.getProperty( key ); + + props.put( key, value ); + } + } + } + + // ---------------------------------------------------------------------- + // MailSender Implementation + // ---------------------------------------------------------------------- + + public void send( MailMessage mail ) + throws MailSenderException + { + verify( mail ); + + try + { + Authenticator auth = null; + + if ( getUsername() != null ) + { + auth = new Authenticator() + { + protected PasswordAuthentication getPasswordAuthentication() + { + return new PasswordAuthentication( getUsername(), getPassword() ); + } + }; + } + + Session session = Session.getDefaultInstance( props, auth ); + + session.setDebug( getLogger().isDebugEnabled() ); + + Message msg = new MimeMessage( session ); + InternetAddress addressFrom = new InternetAddress( mail.getFrom().getRfc2822Address() ); + msg.setFrom( addressFrom ); + + if ( mail.getToAddresses().size() > 0 ) + { + InternetAddress[] addressTo = new InternetAddress[mail.getToAddresses().size()]; + int count = 0; + for ( Iterator i = mail.getToAddresses().iterator(); i.hasNext(); ) + { + String address = ( (MailMessage.Address) i.next() ).getRfc2822Address(); + addressTo[count++] = new InternetAddress( address ); + } + msg.setRecipients( Message.RecipientType.TO, addressTo ); + } + + if ( mail.getCcAddresses().size() > 0 ) + { + InternetAddress[] addressCc = new InternetAddress[mail.getCcAddresses().size()]; + int count = 0; + for ( Iterator i = mail.getCcAddresses().iterator(); i.hasNext(); ) + { + String address = ( (MailMessage.Address) i.next() ).getRfc2822Address(); + addressCc[count++] = new InternetAddress( address ); + } + msg.setRecipients( Message.RecipientType.CC, addressCc ); + } + + if ( mail.getBccAddresses().size() > 0 ) + { + InternetAddress[] addressBcc = new InternetAddress[mail.getBccAddresses().size()]; + int count = 0; + for ( Iterator i = mail.getBccAddresses().iterator(); i.hasNext(); ) + { + String address = ( (MailMessage.Address) i.next() ).getRfc2822Address(); + addressBcc[count++] = new InternetAddress( address ); + } + msg.setRecipients( Message.RecipientType.BCC, addressBcc ); + } + + // Setting the Subject and Content Type + msg.setSubject( mail.getSubject() ); + msg.setContent( mail.getContent(), mail.getContentType() == null ? "text/plain" : mail.getContentType() ); + + if ( mail.getSendDate() != null ) + { + msg.setHeader( "Date", DateFormatUtils.getDateHeader( mail.getSendDate() ) ); + } + else + { + msg.setHeader( "Date", DateFormatUtils.getDateHeader( new Date() ) ); + } + + // Send the message + Transport.send( msg ); + } + catch ( MessagingException e ) + { + throw new MailSenderException( "Error while sending mail.", e ); + } + } +} Property changes on: trunk/src/main/java/org/nuiton/mail/ProjectJavamailMailSender.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/mail/plugin/SendEmailMojo.java =================================================================== --- trunk/src/main/java/org/nuiton/mail/plugin/SendEmailMojo.java (rev 0) +++ trunk/src/main/java/org/nuiton/mail/plugin/SendEmailMojo.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,457 @@ +package org.nuiton.mail.plugin; + +import org.nuiton.mail.*; +import org.nuiton.plugin.*; +import org.nuiton.util.PluginHelper; + +import java.io.File; +import java.util.List; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Developer; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.codehaus.plexus.mailsender.MailMessage; +import org.codehaus.plexus.mailsender.MailSenderException; +import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; + +/** + * Send a email. + * + * @goal send-email + * @requiresOnline true + * @requiresProject true + * + * @author tchemit + * @since 1.0.3 + */ +public class SendEmailMojo extends AbstractPlugin { + + /** + * @parameter expression="${session}" + * @required + * @readonly + */ + protected MavenSession mavenSession; + /** + * Dependance du projet. + * + * @parameter default-value="${project}" + * @required + * @readonly + * @since 1.0.0 + */ + protected MavenProject project; + /** + * Dependance du settings. + * + * @parameter default-value="${settings}" + * @required + * @readonly + * @since 1.0.0 + */ + protected Settings settings; + /** + * Un flag pour activer le mode verbeux. + * + * @parameter expression="${helper.verbose}" default-value="${maven.verbose}" + * @since 1.0.0 + */ + protected boolean verbose; + /** + * The Velocity template used to format the email announcement. + * + * @parameter expression="${helper.emailContentFile}" + * @required + * @since 1.0.0 + */ + private File emailContentFile; + /** + * The title of the email to send. + * + * @parameter expression="${helper.emailTitle}" + * @required + * @since 1.0.0 + */ + private String emailTitle; + /** + * Smtp Server. + * + * @parameter expression="${helper.smtpHost}" + * @required + */ + private String smtpHost; + /** + * Port. + * + * @parameter default-value="25" expression="${helper.smtpPort}" + * @required + */ + private int smtpPort; + /** + * The username used to send the email. + * + * @parameter expression="${helper.username}" + */ + private String username; + /** + * The password used to send the email. + * + * @parameter expression="${helper.password}" + */ + private String password; + /** + * Server id to use for authentication (must be defined in your setting + * and use the maven >= 2.1.0 password encryption mecanism). + * <p/> + * + * @parameter expression="${helper.serverId}" + * @since 1.0.0 + */ + protected String serverId; + /** + * If the email should be sent in SSL mode. + * + * @parameter default-value="false" expression="${helper.sslMode}" + */ + private boolean sslMode; + /** + * The id of the developer sending the announcement mail. Only used if the <tt>mailSender</tt> + * attribute is not set. In this case, this should match the id of one of the developers in + * the pom. If a matching developer is not found, then the first developer in the pom will be + * used. + * + * @parameter expression="${helper.fromDeveloperId}" + */ + private String fromDeveloperId; + /** + * Defines the sender of the announcement if the list of developer is empty or + * if the sender is not a member of the development team. + * + * @parameter expression="${helper.mailSender}" + */ + private MailSender mailSender; + /** + * Recipient email address. + * + * @parameter + * @required + */ + private List<String> toAddresses; + /** + * Possible senders. + * + * @parameter expression="${project.developers}" + * @required + * @readonly + */ + private List<Developer> from; + /** + * Mail content type to use. + * @parameter default-value="text/plain" + * @required + * @since 2.1 + */ + private String mailContentType; + /** + * The encoding used to read and write files. + * + * @parameter expression="${helper.encoding}" default-value="${project.build.sourceEncoding}" + * @since 1.0.0 + */ + protected String encoding; + /** + * A flag to skip the goal. + * + * @parameter expression="${helper.skipSendEmail}" default-value="false" + * @since 1.0.0 + */ + private boolean skipSendEmail; + /** + * A flag to test plugin but send nothing to redmine. + * + * @parameter expression="${dryRun}" default-value="false" + * @since 1.0.0 + */ + protected boolean dryRun; + /** + * A flag to restirct only one run in a build (for multi-module context). + * + * @parameter expression="${redmine.runOnce}" default-value="true" + * @since 1.0.0 + */ + private boolean runOnce; + /** + * password decypher + * + * @component roleHint="maven-helper-plugin" + * @since 1.0.0 + */ + protected SecDispatcher sec; + private boolean runOnceDone; + /////////////////////////////////////////////////////////////////////////// + /// Plugin + /////////////////////////////////////////////////////////////////////////// + + @Override + public MavenProject getProject() { + return project; + } + + @Override + public void setProject(MavenProject project) { + this.project = project; + } + + @Override + public boolean isVerbose() { + return verbose; + } + + @Override + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + protected boolean ensurePackaging() { + // accept all project's packaging + return false; + } + + /////////////////////////////////////////////////////////////////////////// + /// AbstractPlugin + /////////////////////////////////////////////////////////////////////////// + protected boolean isGoalSkip() { + return skipSendEmail; + } + + @Override + protected boolean init() throws Exception { + + if (isGoalSkip()) { + return true; + } + + runOnceDone = false; + if (runOnce) { + // check + + if (!isExecutionRoot()) { + getLog().info("runOnce flag is on, will skip the goal"); + runOnceDone = true; + return true; + } + } + + if (!emailContentFile.exists()) { + // no file to publish... + getLog().warn("could not find the template " + emailContentFile); + getLog().warn("will skip send email..."); + return false; + } + + // check server (if used) + + Server server = null; + + if (serverId != null && !serverId.trim().isEmpty()) { + + server = settings.getServer(serverId); + + if (server == null) { + getLog().error("Could not find server with id '" + serverId + "', check your settings.xml file."); + return false; + } + } + + // check authentication configuration is stable + + boolean noUsername = username == null || username.trim().isEmpty(); + boolean noPassword = password == null || password.trim().isEmpty(); + + if (server != null && !noUsername) { + getLog().error("Authentication configuration is wrong :\ncan not use both 'serverId' and 'username' parameters, check your plugin configuration."); + return false; + } + + if (server != null && !noPassword) { + getLog().error("Authentication configuration is wrong :\ncan not use both 'serverId' and 'password' parameters, check your plugin configuration."); + return false; + } + + if ((noUsername && !noPassword) || (!noUsername && noPassword)) { + getLog().error("Authentication configuration is wrong :\nconfiguration is not complete, please fill parameter 'serverId' or 'username' and 'password'."); + return false; + } + + if (server != null) { + // obtain username and password from server + + username = server.getUsername(); + password = sec.decrypt(server.getPassword()); + } + + // check mail sender + + if (mailSender == null) { + + if (from == null || from.isEmpty()) { + getLog().warn("The <developers> section in your pom should not be empty. Add a <developer> entry or set the " + "mailSender parameter."); + getLog().warn("will skip send email..."); + return false; + } + + if (fromDeveloperId == null) { + final Developer dev = from.get(0); + mailSender = new MailSender(dev.getName(), dev.getEmail()); + } else { + for (Developer developer : from) { + if (fromDeveloperId.equals(developer.getId())) { + mailSender = new MailSender(developer.getName(), developer.getEmail()); + break; + } + } + if (mailSender == null) { + getLog().warn("Missing developer with id '" + fromDeveloperId + "' in the <developers> section in your pom."); + getLog().warn("will skip send email..."); + return false; + } + } + } + + String fromAddress = mailSender.getEmail(); + if (fromAddress == null || fromAddress.equals("")) { + getLog().warn("Invalid mail sender: name and email is mandatory (" + mailSender + ")."); + getLog().warn("will skip send email..."); + return false; + } + + return true; + } + + @Override + protected void doAction() throws Exception { + if (runOnce && runOnceDone) { + return; + } + if (isGoalSkip()) { + getLog().info("skipGoal flag is on, the goal is skip."); + return; + } + + if (dryRun) { + getLog().info("\n dryRun flag is on, no mail will be send!\n"); + } + + String newsContent = PluginHelper.readAsString(emailContentFile, encoding); + + MailMessage mailMsg = createMessage(newsContent, mailSender); + + + ProjectJavamailMailSender mailer = createMailer(); + + if (getLog().isDebugEnabled()) { + getLog().debug("fromDeveloperId: " + fromDeveloperId); + } + + if (dryRun) { + getLog().info("Mail title : " + emailTitle); + getLog().info("Mail content :\n" + mailMsg.getContent()); + return; + } + getLog().info("Connecting to Host: " + smtpHost + ":" + smtpPort); + + try { + + mailer.send(mailMsg); + getLog().info("Sent..."); + } catch (MailSenderException e) { + throw new MojoExecutionException("Failed to send email for reason " + e.getMessage(), e); + } + } + + /////////////////////////////////////////////////////////////////////////// + /// Other + /////////////////////////////////////////////////////////////////////////// + protected MailMessage createMessage(String newsContent, MailSender mailSender) throws MailSenderException { + + String fromName = mailSender.getName(); + String fromAddress = mailSender.getEmail(); + + getLog().info("Using this sender for email announcement: " + fromAddress + " < " + fromName + " > "); + + MailMessage mailMsg = new MailMessage(); + mailMsg.setSubject(emailTitle); + if (getLog().isDebugEnabled()) { + getLog().debug("email announcement :\n" + newsContent); + } + mailMsg.setContent(newsContent); + mailMsg.setContentType(mailContentType); + mailMsg.setFrom(fromAddress, fromName); + for (String e : toAddresses) { + getLog().info("Sending mail to " + e + "..."); + mailMsg.addTo(e, ""); + } + return mailMsg; + } + + protected ProjectJavamailMailSender createMailer() { + + ProjectJavamailMailSender mailer = new ProjectJavamailMailSender(); + ConsoleLogger logger = new ConsoleLogger(Logger.LEVEL_INFO, "base"); + if (getLog().isDebugEnabled()) { + logger.setThreshold(Logger.LEVEL_DEBUG); + } + mailer.enableLogging(logger); + mailer.setSmtpHost(smtpHost); + mailer.setSmtpPort(smtpPort); + mailer.setSslMode(sslMode); + if (username != null) { + mailer.setUsername(username); + } + if (password != null) { + mailer.setPassword(password); + } + mailer.initialize(); + return mailer; + } + + public void setMailSender(MailSender sender) { + this.mailSender = sender; + } + + public void setFrom(List<Developer> from) { + this.from = from; + } + + public void setToAddresses(List<String> toAddresses) { + this.toAddresses = toAddresses; + } + + protected boolean isExecutionRoot() { + return project == getExecutionRootProject(); + } + + protected MavenProject getExecutionRootProject() { + MavenProject root = project; + String executionRootDirectory = mavenSession.getExecutionRootDirectory(); + while (root != null) { + File dir = root.getBasedir(); + getLog().debug("Current Folder:" + dir); + boolean result = executionRootDirectory.equalsIgnoreCase(dir.toString()); + if (result) { + break; + } + root = root.getParent(); + } + if (verbose) { + getLog().info("root project " + root); + } + return root; + } +} Property changes on: trunk/src/main/java/org/nuiton/mail/plugin/SendEmailMojo.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Modified: trunk/src/main/java/org/nuiton/plugin/AbstractPlugin.java =================================================================== --- trunk/src/main/java/org/nuiton/plugin/AbstractPlugin.java 2009-09-19 16:19:34 UTC (rev 576) +++ trunk/src/main/java/org/nuiton/plugin/AbstractPlugin.java 2009-09-19 16:29:35 UTC (rev 577) @@ -73,8 +73,15 @@ * @throws Exception if any */ protected abstract void doAction() throws Exception; - protected final String skipAfterInitMessage; + /** + * the message to display when will skip the goal + */ + protected String skipAfterInitMessage; + protected AbstractPlugin() { + this("The goal could not be initialized, will skip the goal"); + } + protected AbstractPlugin(String skipAfterInitMessage) { this.skipAfterInitMessage = skipAfterInitMessage; } @@ -84,14 +91,14 @@ try { if (ensurePackaging()) { - getLog().info("skip goal for packaging " + getProject().getPackaging()); + getLog().warn("The goal is skip due to packaging '" + getProject().getPackaging() + "'"); return; } boolean canContinue = init(); if (!canContinue) { - getLog().info(skipAfterInitMessage); + getLog().warn(skipAfterInitMessage); return; } Copied: trunk/src/main/java/org/nuiton/plugin/CheckProjectFilesPlugin.java (from rev 570, trunk/src/main/java/org/nuiton/CheckProjectFilesPlugin.java) =================================================================== --- trunk/src/main/java/org/nuiton/plugin/CheckProjectFilesPlugin.java (rev 0) +++ trunk/src/main/java/org/nuiton/plugin/CheckProjectFilesPlugin.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,103 @@ +/* + * *##% + * Maven helper plugin + * Copyright (C) 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package org.nuiton.plugin; + +import java.io.File; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.project.MavenProject; + +/** + * Check that : + * + * 1) the changelog exists on standalone module or root module of a + * multi-module project. + * 2) any project module has a README.txt and LICENSE.txt file + * + * @goal check-project-files + * @requiresProject true + * @phase validate + * @author chemit + * @since 1.0.2 + */ +public class CheckProjectFilesPlugin extends AbstractMojo { + + /** + * Dependance du projet. + * + * @parameter default-value="${project}" + * @required + * @since 1.0.2 + */ + protected MavenProject project; + /** + * Un flag pour activer le mode verbeux. + * + * @parameter expression="${helper.verbose}" default-value="${maven.verbose}" + * @since 1.0.2 + */ + protected boolean verbose; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + checkChangelogFile(); + checkReadmeFile(); + checkLicenseFile(); + } + + protected void checkChangelogFile() throws MojoExecutionException { + if (project.isExecutionRoot()) { + File f = new File(project.getBasedir(), "changelog.txt"); + if (!f.exists()) { + throw new MojoExecutionException("the module " + project.getName() + " requires the file " + f.getAbsolutePath()); + } else { + if (verbose) { + getLog().info("changelog file dectected : " + f.getAbsolutePath()); + } + } + } else { + getLog().info("changelog.txt is not required for module " + project.getName() + " (not a root module)"); + } + } + + protected void checkReadmeFile() throws MojoExecutionException { + File f = new File(project.getBasedir(), "README.txt"); + if (!f.exists()) { + throw new MojoExecutionException("the module " + project.getName() + " requires the file " + f.getAbsolutePath()); + } else { + if (verbose) { + getLog().info("readme file dectected : " + f.getAbsolutePath()); + } + } + } + + protected void checkLicenseFile() throws MojoExecutionException { + File f = new File(project.getBasedir(), "LICENSE.txt"); + if (!f.exists()) { + throw new MojoExecutionException("the module " + project.getName() + " requires the file " + f.getAbsolutePath()); + } else { + if (verbose) { + getLog().info("license file dectected : " + f.getAbsolutePath()); + } + } + } +} Added: trunk/src/main/java/org/nuiton/plugin/CollectFilesMojo.java =================================================================== --- trunk/src/main/java/org/nuiton/plugin/CollectFilesMojo.java (rev 0) +++ trunk/src/main/java/org/nuiton/plugin/CollectFilesMojo.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,325 @@ +package org.nuiton.plugin; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.regex.Pattern; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.FileUtils; + +/** + * Collect files some files from a project and copy them into a directory. + * + * @goal collect-files + * @requiresProject true + * + * @author tchemit + * @since 1.0.3 + */ +public class CollectFilesMojo extends AbstractMojo { + + /** + * @parameter expression="${session}" + * @required + * @readonly + */ + private MavenSession mavenSession; + /** + * Dependance du projet. + * + * @parameter default-value="${project}" + * @required + * @readonly + * @since 1.0.3 + */ + protected MavenProject project; + /** + * The artifacts to publish from the project build. + * + * @parameter expression="${project.attachedArtifacts}" + * @required + * @readonly + * @since 1.0.0 + */ + protected List attachedArtifacts; + /** + * User extra files to collect. + * + * Multi values can be used, separated by comma. + * + * @parameter expression="${helper.extraFiles}" + * @since 1.0.0 + */ + protected String extraFiles; + /** + * File name pattern of selected files to publish. + * + * If no Set - no include filter + * + * @parameter expression="${helper.includes}" default-value="" + * @since 1.0.0 + */ + protected String includes; + /** + * File name pattern of selected files to publish. + * + * If no Set - no exclude filter + * + * @parameter expression="${helper.excludes}" default-value="" + * @since 1.0.0 + */ + protected String excludes; + /** + * Directory where to store collected files. + * <p/> + * <b>Note :</b> In a multi-module context, will always use the value of + * the property of the root module, because we need to push collected files + * to only one place. + * + * @parameter expression="${helper.outputDirectory}" default-value="target/collect" + * @since 1.0.0 + */ + protected String outputDirectory; + /** + * Properties file will all files collected indexed by their path. + * <p/> + * <b>Note :</b> If not Set, will not generate the description file. + * + * @parameter expression="${helper.descriptionFile}" + * @since 1.0.0 + */ + protected String descriptionFile; + /** + * Un flag pour collecter aussi les fichiers attaches au projet. + * + * @parameter expression="${helper.includeAttached}" default-value="true" + * @since 1.0.0 + */ + protected boolean includeAttached; + /** + * Un flag pour recopier les fichiers collectés. + * + * @parameter expression="${helper.copyFiles}" default-value="true" + * @since 1.0.0 + */ + protected boolean copyFiles; + /** + * Un flag pour activer le mode verbeux. + * + * @parameter expression="${helper.verbose}" default-value="${maven.verbose}" + * @since 1.0.0 + */ + protected boolean verbose; + /** + * A flag to skip the goal. + * + * @parameter expression="${helper.skip}" default-value="false" + * @since 1.0.0 + */ + protected boolean skip; + /** + * Un flag pour activer le mode verbeux. + * + * @parameter expression="${helper.dryRun}" default-value="false" + * @since 1.0.0 + */ + protected boolean dryRun; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + if (skip) { + getLog().info("Skip flag in on, goal will not be executed"); + } + List<File> files = getFiles(); + if (files.isEmpty()) { + + getLog().warn("No files to collect."); + return; + } + + MavenProject rootProject = getExecutionRootProject(); + + File base = new File(rootProject.getBasedir(), outputDirectory); + + File output = new File(base, project.getGroupId() + "--" + project.getArtifactId()); + + if (rootProject == project || verbose) { + // just print on root + getLog().info("Ouput dir : " + output); + } + + if (dryRun) { + getLog().info("\n dryRun flag is on, no file will be copied!\n"); + } else { + + if (!output.exists()) { + output.mkdirs(); + } + } + + File description = null; + + Properties p = new Properties(); + boolean withDescriptionFile = false; + if (descriptionFile != null && !descriptionFile.trim().isEmpty()) { + + description = new File(rootProject.getBasedir(), descriptionFile); + + withDescriptionFile = true; + + if (description.exists()) { + // reload existing + try { + p.load(new FileInputStream(description)); + getLog().info("Load " + description); + } catch (IOException ex) { + throw new MojoExecutionException("could not load file " + description, ex); + } + } + } + + if (!withDescriptionFile && !copyFiles) { + throw new MojoExecutionException("must use at least one of the parameters 'copyFiles' or 'descriptionFile'"); + } + + String basedir = rootProject.getBasedir().getAbsolutePath(); + int basedirLength = basedir.length(); + for (File f : files) { + String absolutePath = f.getAbsolutePath(); + String path = absolutePath.substring(basedirLength + 1); + File dst = new File(output, f.getName()); + if (withDescriptionFile && copyFiles) { + p.put(path, dst.getAbsolutePath()); + } else { + p.put(path, f.getAbsolutePath()); + } + getLog().info("collected file " + path); + if (!dryRun && copyFiles) { + try { + // copy the collected file + FileUtils.copyFile(f, dst); + } catch (IOException ex) { + throw new MojoExecutionException("could not copy file " + f, ex); + } + } + } + + if (description != null) { + try { + p.store(new FileOutputStream(description), "Generated by " + this.getClass()); + getLog().info("Save " + description); + } catch (IOException ex) { + throw new MojoExecutionException("could not save file " + description, ex); + } + } + } + + protected List<File> getFiles() { + + Pattern includePattern = includes == null || includes.trim().isEmpty() ? null : Pattern.compile(includes.trim()); + Pattern excludePattern = excludes == null || excludes.trim().isEmpty() ? null : Pattern.compile(excludes.trim()); + + List<File> result = new ArrayList<File>(); + + // attach the project mail file + + if (includeAttached) { + + if ("pom".equals(project.getPackaging())) { + addFile(project.getFile(), "adding artifact file : ", result, includePattern, excludePattern); + } else { + Artifact a = project.getArtifact(); + if (a != null) { + addFile(a.getFile(), "adding artifact file : ", result, includePattern, excludePattern); + } + } + } + File file; + + // attach extra files + + if (extraFiles != null && !extraFiles.trim().isEmpty()) { + + for (String path : extraFiles.split(",")) { + + file = new File(path); + addFile(file, "adding user file : ", result, includePattern, excludePattern); + + } + } + + // attach project attached files + + if (includeAttached && attachedArtifacts != null) { + + for (Object o : attachedArtifacts) { + + file = ((Artifact) o).getFile(); + addFile(file, "adding attached artifact file : ", result, includePattern, excludePattern); + } + } + + return result; + } + + protected MavenProject getExecutionRootProject() { + MavenProject root = project; + String executionRootDirectory = mavenSession.getExecutionRootDirectory(); + while (root != null) { + File basedir = root.getBasedir(); + getLog().debug("Current Folder:" + basedir); + boolean result = executionRootDirectory.equalsIgnoreCase(basedir.toString()); + if (result) { + break; + } + root = root.getParent(); + } + if (verbose) { + getLog().info("root project " + root); + } + return root; + } + + protected void addFile(File f, String msg, List<File> files, Pattern includePattern, Pattern excludePattern) { + if (f == null) { + return; + } + if (!f.exists()) { + getLog().warn("skip unexisting file " + f); + return; + } + if (excludePattern != null) { + if (excludePattern.matcher(f.getName()).matches()) { + // skip this file + if (verbose) { + getLog().info("skip " + f + " : in excludes " + excludes); + } + return; + } + } + if (includePattern != null) { + if (!includePattern.matcher(f.getName()).matches()) { + // skip this file + if (verbose) { + getLog().info("skip " + f + " : not in includes " + includes); + } + return; + } + } + if (verbose) { + getLog().info(msg + f); + } + files.add(f); + } +} + Property changes on: trunk/src/main/java/org/nuiton/plugin/CollectFilesMojo.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Modified: trunk/src/main/java/org/nuiton/util/PluginHelper.java =================================================================== --- trunk/src/main/java/org/nuiton/util/PluginHelper.java 2009-09-19 16:19:34 UTC (rev 576) +++ trunk/src/main/java/org/nuiton/util/PluginHelper.java 2009-09-19 16:29:35 UTC (rev 577) @@ -60,6 +60,16 @@ */ public class PluginHelper { + public static final String SNAPSHOT_SUFFIX = "-SNAPSHOT"; + + public static String removeSnapshotSuffix(String versionId) { + if (versionId.endsWith(SNAPSHOT_SUFFIX)) { + // remove snapshot suffix + versionId = versionId.substring(0, versionId.length() - SNAPSHOT_SUFFIX.length()); + } + return versionId; + } + /** * Permet de convertir une liste non typee, en une liste typee. * <p/> @@ -90,7 +100,13 @@ } static final protected double[] timeFactors = {1000000, 1000, 60, 60, 24}; static final protected String[] timeUnites = {"ns", "ms", "s", "m", "h", "d"}; + static final protected double[] memoryFactors = {1024, 1024, 1024, 1024}; + static final protected String[] memoryUnites = {"o", "Ko", "Mo", "Go", "To"}; + static public String convertMemory(long value) { + return convert(value, memoryFactors, memoryUnites); + } + static public String convertTime(long value) { return convert(value, timeFactors, timeUnites); } Added: trunk/src/main/resources/META-INF/plexus/components.xml =================================================================== --- trunk/src/main/resources/META-INF/plexus/components.xml (rev 0) +++ trunk/src/main/resources/META-INF/plexus/components.xml 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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 + + http://www.apache.org/licenses/LICENSE-2.0 + +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. +--> +<component-set> + <components> + <component> + <role>org.sonatype.plexus.components.sec.dispatcher.SecDispatcher</role> + <role-hint>maven-helper-plugin</role-hint> + <implementation>org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher</implementation> + <requirements> + <requirement> + <role>org.sonatype.plexus.components.cipher.PlexusCipher</role> + <field-name>_cipher</field-name> + </requirement> + <requirement> + <role>org.sonatype.plexus.components.sec.dispatcher.PasswordDecryptor</role> + <field-name>_decryptors</field-name> + </requirement> + </requirements> + <configuration> + <_configurationFile>~/.m2/settings-security.xml</_configurationFile> + </configuration> + </component> + <!--component> + <role>org.codehaus.plexus.velocity.VelocityComponent</role> + <role-hint>maven-changes-plugin</role-hint> + <implementation>org.codehaus.plexus.velocity.DefaultVelocityComponent</implementation> + <configuration> + <properties> + <property> + <name>resource.loader</name> + <value>file,class</value> + </property> + <property> + <name>class.resource.loader.class</name> + <value>org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</value> + </property> + <property> + <name>file.resource.loader.class</name> + <value>org.apache.maven.plugin.resource.loader.ProjectResourceLoader</value> + </property> + </properties> + </configuration> + </component--> + </components> +</component-set> \ No newline at end of file Added: trunk/src/test/java/org/nuiton/mail/plugin/SendEmailMojoTest.java =================================================================== --- trunk/src/test/java/org/nuiton/mail/plugin/SendEmailMojoTest.java (rev 0) +++ trunk/src/test/java/org/nuiton/mail/plugin/SendEmailMojoTest.java 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,61 @@ +package org.nuiton.mail.plugin; + +import org.nuiton.mail.MailSender; +import java.io.File; +import java.util.Arrays; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.nuiton.plugin.AbstractMojoTest; + +/** + * @author tchemit + * @since 1.0.0 + */ +public class SendEmailMojoTest extends AbstractMojoTest<SendEmailMojo> { + + protected boolean canContinue; + + @Override + protected String getGoalName(String methodName) { + return "send-email"; + } + + @Override + protected void setUpMojo(SendEmailMojo mojo, File pomFile) throws Exception { + super.setUpMojo(mojo, pomFile); + + // add a mailSender here + MailSender sender = new MailSender(); + sender.setName("Nuiton Release Notification"); + sender.setEmail("test@noway.fr"); + mojo.setMailSender(sender); + + // add a destination + mojo.setToAddresses(Arrays.asList("chemit@codelutin.com")); + + canContinue = mojo.init(); + if (canContinue) { + if (mojo.isVerbose()) { + log.info("setup done for " + mojo.getProject().getFile().getName()); + } + } else { + log.error("setup was not successfull, will skip this test [" + getClass() + "]"); + } + } + + @Test + public void sendEmail() throws Exception { + Assume.assumeTrue(canContinue); + + Assert.assertNotNull(getMojo()); + getMojo().doAction(); + } + + @Test + public void skipSendEmail() throws Exception { + Assume.assumeTrue(canContinue); + Assert.assertNotNull(getMojo()); + getMojo().doAction(); + } +} Property changes on: trunk/src/test/java/org/nuiton/mail/plugin/SendEmailMojoTest.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/mailContentFile.txt =================================================================== --- trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/mailContentFile.txt (rev 0) +++ trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/mailContentFile.txt 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1 @@ +The content of the test email \ No newline at end of file Added: trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/sendEmail.xml =================================================================== --- trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/sendEmail.xml (rev 0) +++ trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/sendEmail.xml 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,42 @@ +<?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/maven-v4_0_0.xsd"> + + <groupId>org.nuiton.test</groupId> + <artifactId>test-send-email</artifactId> + <version>0</version> + + <build> + + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>maven-helper-plugin</artifactId> + <configuration> + <emailContentFile>target/test-classes/org/nuiton/mail/plugin/SendEmailMojoTest/mailContentFile.txt</emailContentFile> + <emailTitle>[ANNOUNCEMENT] - One 1.0.0 released</emailTitle> + <encoding>UTF-8</encoding> + <skipSendEmail>false</skipSendEmail> + <!--<mailSender> + <name>Nuiton Release Notification</name> + <email>noreply@${platform}</email> + </mailSender> + <toAddresses> + <item>chemit@codelutin.com</item> + </toAddresses>--> + <smtpHost>smtp</smtpHost> + <smtpPort>25</smtpPort> + <dryRun>true</dryRun> + </configuration> + <executions> + <execution> + <goals> + <goal>send-email</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Added: trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/skipSendEmail.xml =================================================================== --- trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/skipSendEmail.xml (rev 0) +++ trunk/src/test/resources/org/nuiton/mail/plugin/SendEmailMojoTest/skipSendEmail.xml 2009-09-19 16:29:35 UTC (rev 577) @@ -0,0 +1,33 @@ +<?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/maven-v4_0_0.xsd"> + + + <groupId>org.nuiton.test</groupId> + <artifactId>test-send-email</artifactId> + <version>0</version> + + <build> + + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>maven-helper-plugin</artifactId> + <configuration> + <emailContentFile>target/test-classes/org/nuiton/smail/plugin/SendEmailMojoTest/mailContentFile.txt</emailContentFile> + <emailTitle>[ANNOUNCEMENT] - One 1.0.0 released</emailTitle> + <encoding>UTF-8</encoding> + <skipSendEmail>true</skipSendEmail> + </configuration> + <executions> + <execution> + <goals> + <goal>send-email</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file
participants (1)
-
tchemit@users.nuiton.org