Author: krosenvold
Date: Wed Oct 24 10:27:03 2012
New Revision: 1401610
URL: http://svn.apache.org/viewvc?rev=1401610&view=rev
Log:
[MPIR-176] Added support for images/avatars in project team list
Modified:
maven/plugins/trunk/maven-project-info-reports-plugin/src/main/java/org/apache/maven/report/projectinfo/TeamListReport.java
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/AbstractProjectInfoTestCase.java
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/TeamListReportTest.java
Modified:
maven/plugins/trunk/maven-project-info-reports-plugin/src/main/java/org/apache/maven/report/projectinfo/TeamListReport.java
URL:
http://svn.apache.org/viewvc/maven/plugins/trunk/maven-project-info-reports-plugin/src/main/java/org/apache/maven/report/projectinfo/TeamListReport.java?rev=1401610&r1=1401609&r2=1401610&view=diff
==============================================================================
---
maven/plugins/trunk/maven-project-info-reports-plugin/src/main/java/org/apache/maven/report/projectinfo/TeamListReport.java
(original)
+++
maven/plugins/trunk/maven-project-info-reports-plugin/src/main/java/org/apache/maven/report/projectinfo/TeamListReport.java
Wed Oct 24 10:27:03 2012
@@ -19,6 +19,15 @@ package org.apache.maven.report.projecti
* under the License.
*/
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TimeZone;
import org.apache.commons.lang.SystemUtils;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.model.Contributor;
@@ -26,17 +35,11 @@ import org.apache.maven.model.Developer;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.util.StringUtils;
-import org.joda.time.DateTimeZone;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TimeZone;
+import org.joda.time.DateTimeZone;
/**
* Generates the Project Team report.
@@ -49,6 +52,19 @@ import java.util.TimeZone;
public class TeamListReport
extends AbstractProjectInfoReport
{
+ /**
+ * Shows avatar images for team members that have
+ * a) properties/picUrl set
+ * b) An avatar at gravatar.com for their email address
+ * <p/>
+ * Future versions of this plugin may choose to implement different
strategies for resolving
+ * avatar images, possibly using different providers.
+ *
+ * @since 2.6
+ */
+ @Parameter( property = "teamlist.showAvatarImages", defaultValue = "true" )
+ private boolean showAvatarImages;
+
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
@@ -56,12 +72,15 @@ public class TeamListReport
@Override
public void executeReport( Locale locale )
{
- TeamListRenderer r = new TeamListRenderer( getSink(),
project.getModel(), getI18N( locale ), locale, getLog() );
+ TeamListRenderer r = new TeamListRenderer( getSink(),
project.getModel(), getI18N( locale ), locale, getLog(),
+ showAvatarImages );
r.render();
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getOutputName()
{
return "team-list";
@@ -99,20 +118,25 @@ public class TeamListReport
private static final String NAME = "name";
+ private static final String IMAGE = "image";
+
private static final String ID = "id";
private final Model model;
private final Log log;
+ private final boolean showAvatarImages;
+
private static final String[] EMPTY_STRING_ARRAY = new String[0];
- TeamListRenderer( Sink sink, Model model, I18N i18n, Locale locale,
Log log )
+ TeamListRenderer( Sink sink, Model model, I18N i18n, Locale locale,
Log log, boolean showAvatarImages )
{
super( sink, i18n, locale );
this.model = model;
this.log = log;
+ this.showAvatarImages = showAvatarImages;
}
@Override
@@ -134,9 +158,11 @@ public class TeamListReport
javascript.append( " var localOffset =
now.getTimezoneOffset();" ).append( SystemUtils.LINE_SEPARATOR );
javascript.append( " var developerTime = nowTime + ( offset *
60 * 60 * 1000 )"
+ "+ ( localOffset * 60 * 1000 );"
).append( SystemUtils.LINE_SEPARATOR );
- javascript.append( " var developerDate = new
Date(developerTime);" ).append( SystemUtils.LINE_SEPARATOR );
+ javascript.append( " var developerDate = new
Date(developerTime);" ).append(
+ SystemUtils.LINE_SEPARATOR );
javascript.append( SystemUtils.LINE_SEPARATOR );
- javascript.append( " document.getElementById(id).innerHTML =
developerDate;" ).append( SystemUtils.LINE_SEPARATOR );
+ javascript.append( " document.getElementById(id).innerHTML =
developerDate;" ).append(
+ SystemUtils.LINE_SEPARATOR );
javascript.append( "}" ).append( SystemUtils.LINE_SEPARATOR );
javascript.append( SystemUtils.LINE_SEPARATOR );
javascript.append( "function init(){" ).append(
SystemUtils.LINE_SEPARATOR );
@@ -213,8 +239,8 @@ public class TeamListReport
}
// To handle JS
- javascript.append( "}" ).append( SystemUtils.LINE_SEPARATOR
).append( SystemUtils.LINE_SEPARATOR )
- .append( "window.onLoad = init();" ).append(
SystemUtils.LINE_SEPARATOR );
+ javascript.append( "}" ).append( SystemUtils.LINE_SEPARATOR
).append( SystemUtils.LINE_SEPARATOR ).append(
+ "window.onLoad = init();" ).append( SystemUtils.LINE_SEPARATOR
);
javaScript( javascript.toString() );
endSection();
@@ -227,6 +253,20 @@ public class TeamListReport
{
sink.tableRow();
+ if ( headersMap.get( IMAGE ) == Boolean.TRUE && showAvatarImages )
+ {
+ Properties properties = member.getProperties();
+ String picUrl = properties.getProperty( "picUrl" );
+ if ( StringUtils.isEmpty( picUrl ) )
+ {
+ picUrl = getGravatarUrl( member.getEmail() );
+ }
+ sink.tableCell();
+ sink.figure();
+ sink.figureGraphics( picUrl );
+ sink.figure_();
+ sink.tableCell_();
+ }
String type = "contributor";
if ( member instanceof Developer )
{
@@ -280,8 +320,8 @@ public class TeamListReport
{
tableCell( member.getTimezone() );
- if ( StringUtils.isNotEmpty( member.getTimezone() )
- && ( !ProjectInfoReportUtils.isNumber(
member.getTimezone().trim() ) ) )
+ if ( StringUtils.isNotEmpty( member.getTimezone() ) && (
!ProjectInfoReportUtils.isNumber(
+ member.getTimezone().trim() ) ) )
{
String tz = member.getTimezone().trim();
try
@@ -293,7 +333,8 @@ public class TeamListReport
sink.rawText( "<span id=\"" + type + "-" + rowId +
"\">" );
text( tz );
String offSet = String.valueOf( TimeZone.getTimeZone(
tz ).getRawOffset() / 3600000 );
- javascript.append( " offsetDate('" ).append( type
).append( "-" ).append( rowId ).append( "', '" );
+ javascript.append( " offsetDate('" ).append( type
).append( "-" ).append( rowId ).append(
+ "', '" );
javascript.append( offSet ).append( "');" ).append(
SystemUtils.LINE_SEPARATOR );
sink.rawText( "</span>" );
sink.tableCell_();
@@ -301,7 +342,7 @@ public class TeamListReport
catch ( IllegalArgumentException e )
{
log.warn( "The time zone '" + tz + "' for the " + type
+ " '" + member.getName()
- + "' is not a recognised time zone, use a number
in the range -12 and +14 instead of." );
+ + "' is not a recognised time zone, use
a number in the range -12 and +14 instead of." );
sink.tableCell();
sink.rawText( "<span id=\"" + type + "-" + rowId +
"\">" );
@@ -327,14 +368,16 @@ public class TeamListReport
{
text( null );
log.warn( "The time zone '" +
member.getTimezone().trim() + "' for the " + type + " '"
- + member.getName()
- + "' is not a recognised time zone, use a
number in the range -12 to +14 instead of." );
+ + member.getName()
+ + "' is not a recognised time zone,
use a number in the range -12 to +14 instead of." );
}
else
{
text( member.getTimezone().trim() );
- javascript.append( " offsetDate('" ).append(
type ).append( "-" ).append( rowId ).append( "', '" );
- javascript.append( member.getTimezone() ).append(
"');" ).append( SystemUtils.LINE_SEPARATOR );
+ javascript.append( " offsetDate('" ).append(
type ).append( "-" ).append( rowId ).append(
+ "', '" );
+ javascript.append( member.getTimezone() ).append(
"');" ).append(
+ SystemUtils.LINE_SEPARATOR );
}
}
sink.rawText( "</span>" );
@@ -358,6 +401,41 @@ public class TeamListReport
sink.tableRow_();
}
+ private String getGravatarUrl( String email )
+ {
+ if ( email == null )
+ {
+ return null;
+ }
+ StringUtils.trim( email );
+ MessageDigest md;
+ try
+ {
+ md = MessageDigest.getInstance( "MD5" );
+ md.update( email.getBytes() );
+ byte byteData[] = md.digest();
+ StringBuilder sb = new StringBuilder();
+ for ( byte aByteData : byteData )
+ {
+ sb.append( Integer.toString( ( aByteData & 0xff ) + 0x100,
16 ).substring( 1 ) );
+ }
+ return "http://www.gravatar.com/avatar/" + sb.toString() +
"?d=mm";
+ }
+ catch ( NoSuchAlgorithmException e )
+ {
+ return null;
+ }
+ }
+
+ private String img( String src )
+ {
+ if ( src == null )
+ {
+ return "";
+ }
+ return "<img src='" + src + "'/>";
+ }
+
/**
* @param requiredHeaders
* @return
@@ -428,6 +506,10 @@ public class TeamListReport
String email, String url, String
organization, String organizationUrl,
String roles, String timeZone, String
actualTime, String properties )
{
+ if ( requiredHeaders.get( IMAGE ) == Boolean.TRUE )
+ {
+ requiredArray.add( name );
+ }
if ( requiredHeaders.get( NAME ) == Boolean.TRUE )
{
requiredArray.add( name );
@@ -472,6 +554,7 @@ public class TeamListReport
{
Map<String, Boolean> requiredHeaders = new HashMap<String,
Boolean>();
+ requiredHeaders.put( IMAGE, Boolean.FALSE );
requiredHeaders.put( ID, Boolean.FALSE );
requiredHeaders.put( NAME, Boolean.FALSE );
requiredHeaders.put( EMAIL, Boolean.FALSE );
@@ -499,6 +582,7 @@ public class TeamListReport
if ( StringUtils.isNotEmpty( unit.getEmail() ) )
{
requiredHeaders.put( EMAIL, Boolean.TRUE );
+ requiredHeaders.put( IMAGE, Boolean.TRUE );
}
if ( StringUtils.isNotEmpty( unit.getUrl() ) )
{
@@ -521,7 +605,13 @@ public class TeamListReport
requiredHeaders.put( TIME_ZONE, Boolean.TRUE );
}
Properties properties = unit.getProperties();
- if ( null != properties && !properties.isEmpty() )
+ boolean hasPicUrl = properties.contains( "picUrl" );
+ if ( hasPicUrl )
+ {
+ requiredHeaders.put( IMAGE, Boolean.TRUE );
+ }
+ boolean isJustAnImageProperty = properties.size() == 1 &&
hasPicUrl;
+ if ( !isJustAnImageProperty && !properties.isEmpty() )
{
requiredHeaders.put( PROPERTIES, Boolean.TRUE );
}
Modified:
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/AbstractProjectInfoTestCase.java
URL:
http://svn.apache.org/viewvc/maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/AbstractProjectInfoTestCase.java?rev=1401610&r1=1401609&r2=1401610&view=diff
==============================================================================
---
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/AbstractProjectInfoTestCase.java
(original)
+++
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/AbstractProjectInfoTestCase.java
Wed Oct 24 10:27:03 2012
@@ -24,7 +24,6 @@ import org.apache.maven.profiles.Default
import org.apache.maven.profiles.ProfileManager;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
-import org.apache.maven.reporting.MavenReport;
import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.util.StringUtils;
@@ -157,11 +156,23 @@ public abstract class AbstractProjectInf
throws Exception
{
File pluginXmlFile = new File( getBasedir(),
"src/test/resources/plugin-configs/" + pluginXml );
+ AbstractProjectInfoReport mojo = createReportMojo( goal,
pluginXmlFile );
+ return generateReport( mojo, pluginXmlFile);
+ }
+
+ protected AbstractProjectInfoReport createReportMojo( String goal, File
pluginXmlFile )
+ throws Exception
+ {
AbstractProjectInfoReport mojo = (AbstractProjectInfoReport)
lookupMojo( goal, pluginXmlFile );
assertNotNull( "Mojo found.", mojo );
setVariableValueToObject( mojo, "remoteRepositories",
mojo.project.getRemoteArtifactRepositories() );
+ return mojo;
+ }
+ protected File generateReport( AbstractProjectInfoReport mojo, File
pluginXmlFile )
+ throws Exception
+ {
mojo.execute();
MavenProjectBuilder builder = (MavenProjectBuilder) lookup(
MavenProjectBuilder.ROLE );
@@ -169,10 +180,11 @@ public abstract class AbstractProjectInf
testMavenProject = builder.buildWithDependencies( pluginXmlFile,
mojo.localRepository, profileManager );
- MavenReport reportMojo = (MavenReport) mojo;
- File outputDir = reportMojo.getReportOutputDirectory();
- String filename = reportMojo.getOutputName() + ".html";
+ File outputDir = mojo.getReportOutputDirectory();
+ String filename = mojo.getOutputName() + ".html";
return new File( outputDir, filename );
}
+
+
}
Modified:
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/TeamListReportTest.java
URL:
http://svn.apache.org/viewvc/maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/TeamListReportTest.java?rev=1401610&r1=1401609&r2=1401610&view=diff
==============================================================================
---
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/TeamListReportTest.java
(original)
+++
maven/plugins/trunk/maven-project-info-reports-plugin/src/test/java/org/apache/maven/report/projectinfo/TeamListReportTest.java
Wed Oct 24 10:27:03 2012
@@ -19,6 +19,7 @@ package org.apache.maven.report.projecti
* under the License.
*/
+import java.io.File;
import java.net.URL;
import com.meterware.httpunit.GetMethodWebRequest;
@@ -48,7 +49,10 @@ public class TeamListReportTest
public void testReport()
throws Exception
{
- generateReport( "project-team", "project-team-plugin-config.xml" );
+ File pluginXmlFile = new File( getBasedir(),
"src/test/resources/plugin-configs/" + "project-team-plugin-config.xml" );
+ AbstractProjectInfoReport mojo = createReportMojo( "project-team",
pluginXmlFile );
+ setVariableValueToObject( mojo, "showAvatarImages", Boolean.TRUE );
+ generateReport( mojo, pluginXmlFile);
assertTrue( "Test html generated", getGeneratedReport(
"team-list.html" ).exists() );
URL reportURL = getGeneratedReport( "team-list.html" ).toURI().toURL();
@@ -65,6 +69,8 @@ public class TeamListReportTest
// Test the Page title
assertEquals( getString( "report.team-list.title" ),
response.getTitle() );
+ assertTrue( response.getText().contains( "gravatar" ));
+
// Test the texts
TextBlock[] textBlocks = response.getTextBlocks();