Write errors and warnings to an XML log file
Merge the XML log files when M2 repos are merged
diff --git a/src/main/groovy/m4e/AbstractCommand.groovy b/src/main/groovy/m4e/AbstractCommand.groovy
index d85ef12..21c53a4 100644
--- a/src/main/groovy/m4e/AbstractCommand.groovy
+++ b/src/main/groovy/m4e/AbstractCommand.groovy
@@ -12,14 +12,16 @@
package m4e
import java.io.File;
+import m4e.maven.ErrorLog
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-abstract class AbstractCommand {
+abstract class AbstractCommand implements CommonConstants {
Logger log = LoggerFactory.getLogger( getClass() )
File workDir
+ ErrorLog errorLog
void run( List<String> args ) {
run( args as String[] )
@@ -38,7 +40,17 @@
}
void destroy() {
+ if( errorLog ) {
+ errorLog.close()
+ }
+ }
+
+ void prepareErrorLog( File repo, String command ) {
+ if( errorLog ) {
+ errorLog.close()
+ }
+ errorLog = new ErrorLog( repo: repo, command: command )
}
abstract void doRun( String... args );
@@ -46,14 +58,32 @@
int errorCount = 0
int warningCount = 0
- void warn( Warning warning, String msg ) {
+ void warn( Warning warning, String msg, Map xml = null ) {
warningCount ++
log.warn( msg + '\nFor details, see ' + warning.url() )
+
+ if( errorLog && xml ) {
+ Map map = new LinkedHashMap()
+
+ map['code'] = warning.code()
+ map.putAll( xml )
+
+ errorLog.write().invokeMethod( 'warning', [ map, msg ] )
+ }
}
- void error( Error error, String msg ) {
+ void error( Error error, String msg, Map xml = null ) {
errorCount ++
log.error( msg + '\nFor details, see ' + error.url() )
+
+ if( errorLog && xml ) {
+ Map map = new LinkedHashMap()
+
+ map['code'] = error.code()
+ map.putAll( xml )
+
+ errorLog.write().invokeMethod( 'error', [ map, msg ] )
+ }
}
void mergeCounters( AbstractCommand other ) {
diff --git a/src/main/groovy/m4e/CommonConstants.java b/src/main/groovy/m4e/CommonConstants.java
new file mode 100644
index 0000000..bc175d9
--- /dev/null
+++ b/src/main/groovy/m4e/CommonConstants.java
@@ -0,0 +1,13 @@
+package m4e;
+
+public interface CommonConstants {
+
+ /** Folder name inside of a Maven 2 repository where MT4E will put its files */
+ static final String MT4E_FOLDER = ".mt4e";
+
+ /** File name of the import/export DB in the MT4E folder */
+ static final String IMPORT_EXPORT_DB_FILE = "importExportDB";
+
+ /** UTF-8 encoding/charset */
+ static final String UTF_8 = "UTF-8";
+}
diff --git a/src/main/groovy/m4e/Error.java b/src/main/groovy/m4e/Error.java
index e7e0c6b..60865f0 100644
--- a/src/main/groovy/m4e/Error.java
+++ b/src/main/groovy/m4e/Error.java
@@ -22,7 +22,11 @@
this.id = id;
}
+ public String code() {
+ return String.format( "E%04d", id );
+ }
+
public String url() {
- return Warning.BASE_URL + String.format( "E%04d", id );
+ return Warning.BASE_URL + code();
}
}
diff --git a/src/main/groovy/m4e/InstallCmd.groovy b/src/main/groovy/m4e/InstallCmd.groovy
index 20934c9..5c0f07c 100644
--- a/src/main/groovy/m4e/InstallCmd.groovy
+++ b/src/main/groovy/m4e/InstallCmd.groovy
@@ -35,6 +35,15 @@
}
log.info( "Import complete. Imported ${statistics.bundleCount} Eclipse bundles into ${statistics.pomCount} POMs. There are ${statistics.jarCount} new JARs of which ${statistics.sourceCount} have sources" )
+
+ if( m2repos.size() == 1 ) {
+ log.info( "The new Maven 2 repository is here: ${m2repos[0].absolutePath}" )
+ } else {
+ log.info( "${m2repos.size()} Maven 2 repositories were created:" )
+ m2repos.each {
+ log.info( " ${it.absolutePath}" )
+ }
+ }
}
List<File> m2repos = []
@@ -188,6 +197,8 @@
m2repo = new File( tmpHome, 'm2repo' )
failure = new File( tmpHome, FAILURE_FILE_NAME )
+ installCmd.prepareErrorLog( m2repo, 'install' )
+
log.debug( "Importing plug-ins from ${eclipseFolder} into repo ${m2repo}" )
clean()
@@ -339,7 +350,9 @@
void unpackNestedJar( String nestedJarPath, File jarFile ) {
if( nestedJarPath.contains( ',' ) ) {
- installCmd.warn( Warning.MULTIPLE_NESTED_JARS, "Multiple nested JARs are not supported; just copying the original bundle" )
+ String msg = "Multiple nested JARs are not supported; just copying the original bundle"
+ Map xml = [ jar: jarFile.absolutePath, nestedJarPath: nestedJarPath ]
+ installCmd.warn( Warning.MULTIPLE_NESTED_JARS, msg, xml )
bundle.copy( jarFile )
return
}
@@ -621,7 +634,8 @@
def entry = archive[ 'META-INF/MANIFEST.MF' ]
if( !entry ) {
- installCmd.error( Error.MISSING_MANIFEST, "Can't find manifest in ${file.absolutePath}" )
+ String msg = "Can't find manifest in ${file.absolutePath}"
+ installCmd.error( Error.MISSING_MANIFEST, msg, [ jar: file.absolutePath ] )
return null
}
@@ -696,7 +710,8 @@
Manifest loadManifestFromFile( File file ) {
if( !file.exists() ) {
- installCmd.error( Error.MISSING_MANIFEST, "Can't find manifest ${file.absolutePath}" )
+ String msg = "Can't find manifest ${file.absolutePath}"
+ installCmd.error( Error.MISSING_MANIFEST, msg, [ jar: file.absolutePath ] )
return null
}
diff --git a/src/main/groovy/m4e/MergeCmd.groovy b/src/main/groovy/m4e/MergeCmd.groovy
index b33ce4d..2992b9c 100644
--- a/src/main/groovy/m4e/MergeCmd.groovy
+++ b/src/main/groovy/m4e/MergeCmd.groovy
@@ -12,6 +12,7 @@
package m4e
import java.io.File;
+import de.pdark.decentxml.XMLUtils;
class MergeCmd extends AbstractCommand {
@@ -32,15 +33,44 @@
throw new UserError( "Target repository ${target} already exists. Cowardly refusing to continue." )
}
+ prepareErrorLog( target, 'merge' )
+
+ mt4eFolder = new File( target, '.mt4e' )
+
log.debug( "Sources: ${sources}" )
log.debug( "Target: ${target}" )
for( source in sources ) {
log.info( 'Merging {}', source )
- merge( new File( source ).absoluteFile, target )
+ File file = new File( source ).absoluteFile
+
+ merge( file, target )
+ }
+
+ closeXmlFiles()
+ }
+
+ void closeXmlFiles() {
+ def exc = null
+
+ xmlFiles.values().each {
+ try {
+ it << '</merged>\n'
+ it.close()
+ } catch( Exception e ) {
+ if( !exc ) {
+ exc = e
+ }
+ }
+ }
+
+ if( exc ) {
+ throw e
}
}
+ File mt4eFolder
+
void merge( File source, File target ) {
target.makedirs()
@@ -48,6 +78,11 @@
source.eachFile { File srcPath ->
File targetPath = new File( target, srcPath.name )
+ if( targetPath.equals( mt4eFolder ) ) {
+ mergeMt4eFiles( srcPath, mt4eFolder )
+ return
+ }
+
if( srcPath.isDirectory() ) {
if( targetPath.exists() && !targetPath.isDirectory() ) {
throw new RuntimeException( "${srcPath} is a directory but ${targetPath} is a file" )
@@ -70,6 +105,54 @@
}
}
+ void mergeMt4eFiles( File source, File target ) {
+ source.eachFile { File srcPath ->
+ String name = srcPath.name
+ if( IMPORT_EXPORT_DB_FILE == name ) {
+ return
+ }
+
+ File targetPath = new File( target, name )
+
+ if( srcPath.isDirectory() ) {
+ mergeMt4eFiles( srcPath, targetPath )
+ return
+ }
+
+ if( name.endsWith( '.xml' ) ) {
+ mergeXml( srcPath, targetPath )
+ } else {
+ warn( Warning.UNABLE_TO_MERGE_MT4E_FILE, "Unable to merge ${srcPath.absolutePath}", [ file: srcPath.absolutePath ] )
+ }
+ }
+ }
+
+ Map<String, Writer> xmlFiles = [:]
+
+ void mergeXml( File source, File target ) {
+ def writer = xmlFiles[ target.name ]
+ if( !writer ) {
+ if( target.exists() ) {
+ warn( Warning.UNABLE_TO_MERGE_MT4E_FILE, "Unable to merge ${source.absolutePath}", [ file: source.absolutePath ] )
+ }
+
+ target.parentFile?.makedirs()
+
+ writer = target.newWriter( UTF_8 )
+ xmlFiles[ target.name ] = writer
+
+ writer << '<merged>\n'
+ }
+
+ writer << '<source file="' << XMLUtils.escapeXMLText( source.absolutePath ).replace( '"', '"' ) << '">\n'
+
+ source.withReader( UTF_8 ) {
+ writer << it
+ }
+
+ writer << '\n</source>\n'
+ }
+
boolean filesAreEqual( File source, File target ) {
if( source.size() != target.size() ) {
return false
diff --git a/src/main/groovy/m4e/UpdateImportExportDatabaseCmd.groovy b/src/main/groovy/m4e/UpdateImportExportDatabaseCmd.groovy
index 6047258..b03633d 100644
--- a/src/main/groovy/m4e/UpdateImportExportDatabaseCmd.groovy
+++ b/src/main/groovy/m4e/UpdateImportExportDatabaseCmd.groovy
@@ -24,7 +24,7 @@
public void doRun( String... args ) {
File repo = repoOption( args, 1 )
- File dbPath = new File( repo, '.mt4e/importExportDB' )
+ File dbPath = new File( repo, MT4E_FOLDER + '/' + IMPORT_EXPORT_DB_FILE )
def db = new ImportExportDB( file: dbPath )
diff --git a/src/main/groovy/m4e/Warning.java b/src/main/groovy/m4e/Warning.java
index e63345e..80009d5 100644
--- a/src/main/groovy/m4e/Warning.java
+++ b/src/main/groovy/m4e/Warning.java
@@ -15,7 +15,8 @@
MISSING_BINARY_BUNDLE_FOR_SOURCES( 1 ),
UNEXPECTED_FILE_IN_SOURCE_BUNDLE( 2 ),
BINARY_DIFFERENCE( 3 ),
- MULTIPLE_NESTED_JARS( 4 );
+ MULTIPLE_NESTED_JARS( 4 ),
+ UNABLE_TO_MERGE_MT4E_FILE( 5 );
public final static String BASE_URL = "http://wiki.eclipse.org/MT4E_";
@@ -25,7 +26,11 @@
this.id = id;
}
+ public String code() {
+ return String.format( "W%04d", id );
+ }
+
public String url() {
- return BASE_URL + String.format( "W%04d", id );
+ return BASE_URL + code();
}
}
diff --git a/src/main/groovy/m4e/maven/ErrorLog.groovy b/src/main/groovy/m4e/maven/ErrorLog.groovy
new file mode 100644
index 0000000..8a8b985
--- /dev/null
+++ b/src/main/groovy/m4e/maven/ErrorLog.groovy
@@ -0,0 +1,36 @@
+package m4e.maven;
+
+import groovy.xml.MarkupBuilder
+
+public class ErrorLog {
+
+ File repo
+ String command
+
+ Writer writer
+ MarkupBuilder builder
+
+ MarkupBuilder write() {
+ if( ! builder ) {
+ File file = new File( repo, ".mt4e/logs/${command}.xml" )
+
+ file.parentFile?.makedirs()
+
+ writer = file.newWriter( 'UTF-8' )
+ builder = new MarkupBuilder( writer )
+
+ writer.write( "<mt4e-log command='${command}'>\n" )
+ }
+
+ return builder
+ }
+
+ void close() {
+ if( writer ) {
+ builder.yield( "\n</mt4e-log>", false )
+
+ writer.close()
+ writer = null
+ }
+ }
+}