blob: 8f6e5a1b34e693df04d19840966fe48beb88b212 [file] [log] [blame]
package org.apache.maven.dist.tools.pgp;
/*
* 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.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.net.URL;
import java.util.Iterator;
import java.util.Locale;
import org.apache.commons.io.IOUtils;
import org.apache.maven.dist.tools.AbstractDistCheckReport;
import org.apache.maven.dist.tools.ConfigurationLineInfo;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.reporting.MavenReportException;
/**
* Check PGP KEYS files.
*/
@Mojo( name = "check-pgp-keys", requiresProject = false )
public class CheckPgpKeysReport
extends AbstractDistCheckReport
{
public static final String FAILURES_FILENAME = "check-pgp-keys.log";
public static final String PROJECT_KEYS_URL = "https://svn.apache.org/repos/asf/maven/project/KEYS";
public static final String DIST_KEYS_URL = "https://dist.apache.org/repos/dist/release/maven/KEYS";
@Override
protected String getFailuresFilename()
{
return FAILURES_FILENAME;
}
@Override
public String getName( Locale locale )
{
return "Dist Tool> Check PGP KEYS";
}
@Override
public String getDescription( Locale locale )
{
return "Verification of PGP KEYS files";
}
@Override
protected boolean isIndexPageCheck()
{
return false;
}
@Override
protected void executeReport( Locale locale )
throws MavenReportException
{
String projectKeys = fetchUrl( PROJECT_KEYS_URL );
String distKeys = fetchUrl( DIST_KEYS_URL );
if ( !projectKeys.equals( distKeys ) )
{
File failure = new File( failuresDirectory, FAILURES_FILENAME );
try ( PrintWriter output = new PrintWriter( new FileWriter( failure ) ) )
{
output.println( "PGP KEYS files content is different: " + DIST_KEYS_URL + " vs " + PROJECT_KEYS_URL );
}
catch ( Exception e )
{
getLog().error( "Cannot append to " + getFailuresFilename() );
}
}
Sink sink = getSink();
sink.head();
sink.title();
sink.text( "Check PGP KEYS files" );
sink.title_();
sink.head_();
sink.body();
sink.section1();
sink.paragraph();
sink.rawText( "Check that:" );
sink.paragraph_();
sink.list();
sink.listItem();
sink.rawText( "official Maven PGP KEYS file from distribution area (<b>PMC write only</b>) " );
sink.link( DIST_KEYS_URL );
sink.rawText( DIST_KEYS_URL );
sink.link_();
sink.listItem_();
sink.listItem();
sink.rawText( "intermediate <b>committer write</b> one in Maven Subversion tree " );
sink.link( PROJECT_KEYS_URL );
sink.rawText( PROJECT_KEYS_URL );
sink.link_();
sink.listItem_();
sink.list_();
sink.paragraph();
sink.rawText( "Committers are supposed to write to project's KEYS then ask PMC for sync, but sometimes PMC"
+ " members directly add in distribution area, then future sync is not trivial any more." );
sink.paragraph_();
sink.paragraph();
sink.rawText( "match: " );
if ( projectKeys.equals( distKeys ) )
{
iconSuccess( sink );
}
else
{
iconError( sink );
}
sink.paragraph_();
sink.numberedList( 0 );
KeysIterator distIterator = new KeysIterator( distKeys );
KeysIterator projectIterator = new KeysIterator( projectKeys );
while ( distIterator.hasNext() || projectIterator.hasNext() )
{
String distKey = distIterator.hasNext() ? distIterator.next() : "";
String projectKey = projectIterator.hasNext() ? projectIterator.next() : "";
sink.numberedListItem();
sink.verbatim( true );
sink.rawText( distKey );
sink.verbatim_();
if ( !projectKey.equals( distKey ) )
{
sink.rawText( "dist target (PMC) " );
iconError( sink );
sink.rawText( " project (committers)" );
sink.verbatim( true );
sink.rawText( projectKey );
sink.verbatim_();
}
sink.numberedListItem_();
}
sink.numberedList_();
sink.section1_();
sink.body_();
sink.close();
}
@Override
protected void checkArtifact( ConfigurationLineInfo request, String repoBase )
throws MojoExecutionException
{
}
private String fetchUrl( String url )
throws MavenReportException
{
try ( InputStream in = new URL( url ).openStream();
Reader reader = new InputStreamReader( in, "UTF-8" );
StringWriter writer = new StringWriter() )
{
IOUtils.copy( reader, writer );
return writer.toString();
}
catch ( IOException ioe )
{
throw new MavenReportException( "cannot fetch " + url, ioe );
}
}
private static class KeysIterator
implements Iterator<String>
{
private static final String BEGIN = "-----BEGIN PGP PUBLIC KEY BLOCK-----";
private static final String END = "-----END PGP PUBLIC KEY BLOCK-----";
private String content;
KeysIterator( String content )
{
this.content = content.substring( content.indexOf( "---" ) + 3 );
}
@Override
public boolean hasNext()
{
return content.length() > 0;
}
@Override
public String next()
{
String id = content.substring( 0, content.indexOf( BEGIN ) ).trim();
content = content.substring( content.indexOf( END ) + END.length() ).trim();
return id;
}
}
}