diff --git a/src/it/download-licenses-failFast/invoker.properties b/src/it/download-licenses-failFast/invoker.properties
new file mode 100644
index 000000000..d1b5ad3fd
--- /dev/null
+++ b/src/it/download-licenses-failFast/invoker.properties
@@ -0,0 +1,2 @@
+invoker.goals = clean license:download-licenses -Dlicense.errorRemedy=failFast
+invoker.buildResult=failure
diff --git a/src/it/download-licenses-failFast/pom.xml b/src/it/download-licenses-failFast/pom.xml
new file mode 100644
index 000000000..43cf72e70
--- /dev/null
+++ b/src/it/download-licenses-failFast/pom.xml
@@ -0,0 +1,45 @@
+
+
+ 4.0.0
+
+ org.codehaus.mojo.license
+ download-licenses-failFast
+ 1.0-SNAPSHOT
+ Integration Test
+ http://maven.apache.org
+
+ Check -Dlicense.errorRemedy=failFast
+
+
+
+
+ commons-logging
+ commons-logging
+ 1.0
+
+
+ groovy
+ groovy-all
+ 1.0-jsr-04
+
+
+
+
+
+
+ org.codehaus.mojo
+ license-maven-plugin
+ @pom.version@
+
+
+
+ download-licenses
+
+
+
+
+
+
+
diff --git a/src/it/download-licenses-failFast/postbuild.groovy b/src/it/download-licenses-failFast/postbuild.groovy
new file mode 100644
index 000000000..e69a6940f
--- /dev/null
+++ b/src/it/download-licenses-failFast/postbuild.groovy
@@ -0,0 +1,30 @@
+/*
+ * #%L
+ * License Maven Plugin
+ * %%
+ * Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit, Tony chemit
+ * %%
+ * 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
+ * .
+ * #L%
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Files;
+
+final Path basePath = basedir.toPath()
+
+final Path log = basePath.resolve('build.log')
+assert Files.exists(log)
+assert log.text.contains('No license information available for: groovy:groovy-all')
diff --git a/src/it/download-licenses-failFast/src/license/licenses.xml b/src/it/download-licenses-failFast/src/license/licenses.xml
new file mode 100644
index 000000000..0c3d63fa2
--- /dev/null
+++ b/src/it/download-licenses-failFast/src/license/licenses.xml
@@ -0,0 +1,14 @@
+
+
+
+ commons-logging
+ commons-logging
+
+
+ Apache License 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
\ No newline at end of file
diff --git a/src/it/download-licenses-failFast/src/main/java/org/codehaus/mojo/HelloWorld.java b/src/it/download-licenses-failFast/src/main/java/org/codehaus/mojo/HelloWorld.java
new file mode 100644
index 000000000..16aaa7fed
--- /dev/null
+++ b/src/it/download-licenses-failFast/src/main/java/org/codehaus/mojo/HelloWorld.java
@@ -0,0 +1,15 @@
+package org.codehaus.mojo;
+
+public class HelloWorld
+{
+
+ /**
+ * @param args
+ */
+ public static void main( String[] args )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/it/download-licenses-force/invoker.properties b/src/it/download-licenses-force/invoker.properties
new file mode 100644
index 000000000..2d950418f
--- /dev/null
+++ b/src/it/download-licenses-force/invoker.properties
@@ -0,0 +1 @@
+invoker.goals = clean license:download-licenses -Dlicense.forceDownload=true -Dlicense.errorRemedy=xmlOutput
diff --git a/src/it/download-licenses-force/licenses-errors.expected.xml b/src/it/download-licenses-force/licenses-errors.expected.xml
new file mode 100644
index 000000000..eeae85b50
--- /dev/null
+++ b/src/it/download-licenses-force/licenses-errors.expected.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ groovy
+ groovy-all
+ 1.0-jsr-04
+
+
+
+
+ No license information available for: groovy:groovy-all
+
+
+
+
diff --git a/src/it/download-licenses-force/licenses.expected.xml b/src/it/download-licenses-force/licenses.expected.xml
new file mode 100644
index 000000000..fc69a29a5
--- /dev/null
+++ b/src/it/download-licenses-force/licenses.expected.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ commons-logging
+ commons-logging
+ 1.0
+
+
+ Apache License 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ apache license 2.0 - license-2.0.txt
+
+
+
+
+
diff --git a/src/it/download-licenses-force/pom.xml b/src/it/download-licenses-force/pom.xml
new file mode 100644
index 000000000..4422e9c19
--- /dev/null
+++ b/src/it/download-licenses-force/pom.xml
@@ -0,0 +1,45 @@
+
+
+ 4.0.0
+
+ org.codehaus.mojo.license
+ download-licenses-force
+ 1.0-SNAPSHOT
+ Integration Test
+ http://maven.apache.org
+
+ Check -Dlicense.forceDownload=true -Dlicense.errorRemedy=xmlOutput
+
+
+
+
+ commons-logging
+ commons-logging
+ 1.0
+
+
+ groovy
+ groovy-all
+ 1.0-jsr-04
+
+
+
+
+
+
+ org.codehaus.mojo
+ license-maven-plugin
+ @pom.version@
+
+
+
+ download-licenses
+
+
+
+
+
+
+
diff --git a/src/it/download-licenses-force/postbuild.groovy b/src/it/download-licenses-force/postbuild.groovy
new file mode 100644
index 000000000..4b79c1207
--- /dev/null
+++ b/src/it/download-licenses-force/postbuild.groovy
@@ -0,0 +1,39 @@
+/*
+ * #%L
+ * License Maven Plugin
+ * %%
+ * Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit, Tony chemit
+ * %%
+ * 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
+ * .
+ * #L%
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Files;
+
+final Path basePath = basedir.toPath()
+
+final Path asl2 = basePath.resolve('target/generated-resources/licenses/apache license 2.0 - license-2.0.txt')
+assert Files.exists(asl2)
+assert !asl2.text.contains('This content is fake.')
+assert asl2.text.contains('Version 2.0, January 2004')
+
+final Path expectedLicensesXml = basePath.resolve('licenses.expected.xml')
+final Path licensesXml = basePath.resolve('target/generated-resources/licenses.xml')
+assert expectedLicensesXml.text.equals(licensesXml.text)
+
+final Path expectedLicensesErrorsXml = basePath.resolve('licenses-errors.expected.xml')
+final Path licensesErrorsXml = basePath.resolve('target/generated-resources/licenses-errors.xml')
+assert expectedLicensesErrorsXml.text.equals(licensesErrorsXml.text)
diff --git a/src/it/download-licenses-force/prebuild.groovy b/src/it/download-licenses-force/prebuild.groovy
new file mode 100644
index 000000000..21ea1a3c4
--- /dev/null
+++ b/src/it/download-licenses-force/prebuild.groovy
@@ -0,0 +1,32 @@
+/*
+ * #%L
+ * License Maven Plugin
+ * %%
+ * Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit, Tony chemit
+ * %%
+ * 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
+ * .
+ * #L%
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Files;
+
+Path basePath = basedir.toPath()
+
+Files.move(basePath.resolve('target-initial'), basePath.resolve('target'))
+
+Path asl2 = basePath.resolve('target/generated-resources/licenses/apache license 2.0 - license-2.0.txt')
+assert Files.exists(asl2)
+assert asl2.text.contains('This content is fake.')
\ No newline at end of file
diff --git a/src/it/download-licenses-force/src/license/licenses.xml b/src/it/download-licenses-force/src/license/licenses.xml
new file mode 100644
index 000000000..0c3d63fa2
--- /dev/null
+++ b/src/it/download-licenses-force/src/license/licenses.xml
@@ -0,0 +1,14 @@
+
+
+
+ commons-logging
+ commons-logging
+
+
+ Apache License 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
\ No newline at end of file
diff --git a/src/it/download-licenses-force/src/main/java/org/codehaus/mojo/HelloWorld.java b/src/it/download-licenses-force/src/main/java/org/codehaus/mojo/HelloWorld.java
new file mode 100644
index 000000000..16aaa7fed
--- /dev/null
+++ b/src/it/download-licenses-force/src/main/java/org/codehaus/mojo/HelloWorld.java
@@ -0,0 +1,15 @@
+package org.codehaus.mojo;
+
+public class HelloWorld
+{
+
+ /**
+ * @param args
+ */
+ public static void main( String[] args )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/it/download-licenses-force/target-initial/generated-resources/licenses.xml b/src/it/download-licenses-force/target-initial/generated-resources/licenses.xml
new file mode 100644
index 000000000..fc69a29a5
--- /dev/null
+++ b/src/it/download-licenses-force/target-initial/generated-resources/licenses.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ commons-logging
+ commons-logging
+ 1.0
+
+
+ Apache License 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ apache license 2.0 - license-2.0.txt
+
+
+
+
+
diff --git a/src/it/download-licenses-force/target-initial/generated-resources/licenses/apache license 2.0 - license-2.0.txt b/src/it/download-licenses-force/target-initial/generated-resources/licenses/apache license 2.0 - license-2.0.txt
new file mode 100644
index 000000000..5289398cd
--- /dev/null
+++ b/src/it/download-licenses-force/target-initial/generated-resources/licenses/apache license 2.0 - license-2.0.txt
@@ -0,0 +1,2 @@
+This content is fake.
+-Dlicense.forceDownload should cause the plugin to overwrite this file.
\ No newline at end of file
diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java
index 890e4ca2c..b0139b6b9 100644
--- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java
+++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java
@@ -27,6 +27,7 @@
import org.apache.maven.model.License;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
@@ -54,6 +55,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -142,6 +144,17 @@ public abstract class AbstractDownloadLicensesMojo
@Parameter( property = "licensesOutputFileEncoding", defaultValue = "${project.build.sourceEncoding}" )
private String licensesOutputFileEncoding;
+ /**
+ * A file containing dependencies whose licenses could not be downloaded for some reason. The format is similar to
+ * {@link #licensesOutputFile} but the entries in {@link #licensesErrorsFile} have {@code }
+ * elements attached to them. Those should explain what kind of error happened during the processing of the given
+ * dependency.
+ *
+ * @since 1.18
+ */
+ @Parameter( property = "license.licensesErrorsFile",
+ defaultValue = "${project.build.directory}/generated-resources/licenses-errors.xml" )
+ private File licensesErrorsFile;
/**
* A filter to exclude some scopes.
@@ -184,13 +197,50 @@ public abstract class AbstractDownloadLicensesMojo
private boolean offline;
/**
- * Don't show warnings about bad or missing license files.
+ * Before 1.18, {@link #quiet} having value {@code false} suppressed any license download related warnings in the
+ * log. After 1.18 (incl.), the behavior depends on the value of {@link #errorRemedy}:
+ *
+ * quiet | errorRemedy | effective errorRemedy |
---|
+ *
true | warn | ignore |
+ *
false | warn | warn |
+ *
true or false | ignore | ignore |
+ *
true or false | failFast | failFast |
+ *
true or false | xmlOutput | xmlOutput |
+ *
*
* @since 1.0
+ * @deprecated Use {@link #errorRemedy} instead
*/
@Parameter( defaultValue = "false" )
private boolean quiet;
+ /**
+ * What to do on any license download related error. The possible values are:
+ *
+ * {@link ErrorRemedy#ignore}: all errors are ignored
+ * {@link ErrorRemedy#warn}: all errors are output to the log as warnings
+ * {@link ErrorRemedy#failFast}: a {@link MojoFailureException} is thrown on the first download related
+ * error
+ * {@link ErrorRemedy#xmlOutput}: error messages are added as {@code } to
+ * {@link AbstractDownloadLicensesMojo#licensesErrorsFile}
+ *
+ * @since 1.18
+ */
+ @Parameter( property = "license.errorRemedy", defaultValue = "warn" )
+ private ErrorRemedy errorRemedy;
+
+ /**
+ * If {@code true}, all encountered dependency license URLs are downloaded, no matter what is there in
+ * {@link #licensesConfigFile} and {@link #licensesOutputFile}; otherwise {@link #licensesConfigFile},
+ * {@link #licensesOutputFile} (eventually persisted from a previous build) and the content of
+ * {@link #licensesOutputDirectory} are considered sources of valid information - i.e. only URLs that do not appear
+ * to have been downloaded in the past will be downloaded.
+ *
+ * @since 1.18
+ */
+ @Parameter( property = "license.forceDownload", defaultValue = "false" )
+ private boolean forceDownload;
+
/**
* Include transitive dependencies when downloading license files.
*
@@ -369,9 +419,10 @@ protected void restoreProperties()
/**
* {@inheritDoc}
+ * @throws MojoFailureException
*/
public void execute()
- throws MojoExecutionException
+ throws MojoExecutionException, MojoFailureException
{
if ( isSkip() )
@@ -380,6 +431,8 @@ public void execute()
return;
}
+ this.errorRemedy = getEffectiveErrorRemedy( this.quiet, this.errorRemedy );
+
initDirectories();
try
@@ -391,7 +444,7 @@ public void execute()
// License info from previous build
if ( licensesOutputFile.exists() )
{
- loadLicenseInfo( configuredDepLicensesMap, licensesOutputFile, true );
+ loadLicenseInfo( configuredDepLicensesMap, licensesOutputFile, !forceDownload );
}
// Manually configured license info, loaded second to override previously loaded info
@@ -449,8 +502,14 @@ public void execute()
licensesOutputFileEol = Eol.autodetect( autodetectFromFile, charset );
}
- LicenseSummaryWriter.writeLicenseSummary( depProjectLicenses, licensesOutputFile,
- charset, licensesOutputFileEol );
+ List depProjectLicensesWithErrors = filterErrors( depProjectLicenses );
+ LicenseSummaryWriter.writeLicenseSummary( depProjectLicenses, licensesOutputFile, charset,
+ licensesOutputFileEol );
+ if ( depProjectLicensesWithErrors != null && !depProjectLicensesWithErrors.isEmpty() )
+ {
+ LicenseSummaryWriter.writeLicenseSummary( depProjectLicensesWithErrors, licensesErrorsFile, charset,
+ licensesOutputFileEol );
+ }
}
catch ( Exception e )
{
@@ -464,6 +523,42 @@ public void execute()
}
}
+ /**
+ * Removes from the given {@code depProjectLicenses} those elements which have non-empty
+ * {@link ProjectLicenseInfo#getDownloaderMessages()} and adds those to the resulting {@link List}.
+ *
+ * @param depProjectLicenses the list of {@link ProjectLicenseInfo}s to filter
+ * @return a new {@link List} of {@link ProjectLicenseInfo}s containing only elements with non-empty
+ * {@link ProjectLicenseInfo#getDownloaderMessages()}
+ */
+ private List filterErrors( List depProjectLicenses )
+ {
+ final List result = new ArrayList<>();
+ final Iterator it = depProjectLicenses.iterator();
+ while ( it.hasNext() )
+ {
+ final ProjectLicenseInfo dep = it.next();
+ final List messages = dep.getDownloaderMessages();
+ if ( messages != null && !messages.isEmpty() )
+ {
+ it.remove();
+ result.add( dep );
+ }
+ }
+ return result;
+ }
+
+ private static ErrorRemedy getEffectiveErrorRemedy( boolean quiet, ErrorRemedy errorRemedy )
+ {
+ switch ( errorRemedy )
+ {
+ case warn:
+ return quiet ? ErrorRemedy.ignore : ErrorRemedy.warn;
+ default:
+ return errorRemedy;
+ }
+ }
+
private List sortByGroupIdAndArtifactId( List depProjectLicenses )
{
List sorted = new ArrayList<>( depProjectLicenses );
@@ -768,8 +863,9 @@ private String getLicenseFileName( ProjectLicenseInfo depProject, final URL lice
* Download the licenses associated with this project
*
* @param depProject The project which generated the dependency
+ * @throws MojoFailureException
*/
- private void downloadLicenses( ProjectLicenseInfo depProject )
+ private void downloadLicenses( ProjectLicenseInfo depProject ) throws MojoFailureException
{
getLog().debug( "Downloading license(s) for project " + depProject );
@@ -777,10 +873,7 @@ private void downloadLicenses( ProjectLicenseInfo depProject )
if ( depProject.getLicenses() == null || depProject.getLicenses().isEmpty() )
{
- if ( !quiet )
- {
- getLog().warn( "No license information available for: " + depProject );
- }
+ handleError( depProject, "No license information available for: " + depProject );
return;
}
@@ -807,7 +900,7 @@ private void downloadLicenses( ProjectLicenseInfo depProject )
licenseOutputFile = new File( licensesOutputDirectory, licenseFileName );
}
- if ( !licenseOutputFile.exists() )
+ if ( !licenseOutputFile.exists() || forceDownload )
{
if ( !downloadedLicenseURLs.containsKey( licenseUrl ) || organizeLicensesByDependencies )
{
@@ -825,31 +918,45 @@ private void downloadLicenses( ProjectLicenseInfo depProject )
}
catch ( MalformedURLException e )
{
- if ( !quiet )
- {
- getLog().warn( "POM for dependency " + depProject.toString() + " has an invalid license URL: "
+ handleError( depProject, "POM for dependency " + depProject.toString() + " has an invalid license URL: "
+ licenseUrl );
- }
}
catch ( FileNotFoundException e )
{
- if ( !quiet )
- {
- getLog().warn( "POM for dependency " + depProject.toString()
+ handleError( depProject, "POM for dependency " + depProject.toString()
+ " has a license URL that returns file not found: " + licenseUrl );
- }
}
catch ( IOException e )
{
- getLog().warn( "Unable to retrieve license for dependency: " + depProject.toString() );
- getLog().warn( licenseUrl );
- getLog().warn( e.getMessage() );
+ handleError( depProject, "Unable to retrieve license from URL '" + licenseUrl + "' for dependency '"
+ + depProject.toString() + "': " + e.getMessage() );
}
}
}
+ private void handleError( ProjectLicenseInfo depProject, String msg ) throws MojoFailureException
+ {
+ switch ( errorRemedy )
+ {
+ case ignore:
+ /* do nothing */
+ break;
+ case warn:
+ getLog().warn( msg );
+ break;
+ case failFast:
+ throw new MojoFailureException( msg );
+ case xmlOutput:
+ depProject.addDownloaderMessage( msg );
+ break;
+ default:
+ throw new IllegalStateException( "Unexpected value of " + ErrorRemedy.class.getName() + ": "
+ + errorRemedy );
+ }
+ }
+
private String rewriteLicenseUrlIfNecessary( final String originalLicenseUrl )
{
String resultUrl = originalLicenseUrl;
@@ -872,4 +979,23 @@ private String rewriteLicenseUrlIfNecessary( final String originalLicenseUrl )
}
return resultUrl;
}
+
+ /**
+ * What to do in case of a license download error.
+ *
+ * @since 1.18
+ */
+ public static enum ErrorRemedy
+ {
+ /** All errors are ignored */
+ ignore,
+ /** All errors are output to the log as warnings */
+ warn,
+ /** The first encountered error is logged and a {@link MojoFailureException} is
+ * thrown */
+ failFast,
+ /** Error messages are added as {@code } to
+ * {@link AbstractDownloadLicensesMojo#licensesErrorsFile} */
+ xmlOutput
+ }
}
diff --git a/src/main/java/org/codehaus/mojo/license/model/ProjectLicenseInfo.java b/src/main/java/org/codehaus/mojo/license/model/ProjectLicenseInfo.java
index 7dc649584..56b66b442 100644
--- a/src/main/java/org/codehaus/mojo/license/model/ProjectLicenseInfo.java
+++ b/src/main/java/org/codehaus/mojo/license/model/ProjectLicenseInfo.java
@@ -43,17 +43,7 @@ public class ProjectLicenseInfo
private List licenses = new ArrayList<>();
- private String licenseResolutionResult;
-
- public String getLicenseResolutionResult()
- {
- return licenseResolutionResult;
- }
-
- public void setLicenseResolutionResult( String licenseResolutionResult )
- {
- this.licenseResolutionResult = licenseResolutionResult;
- }
+ private List downloaderMessages = new ArrayList<>();
/**
* Default constructor.
@@ -125,6 +115,16 @@ public String getId()
return groupId + ":" + artifactId;
}
+ public List getDownloaderMessages()
+ {
+ return downloaderMessages;
+ }
+
+ public void addDownloaderMessage( String message )
+ {
+ downloaderMessages.add( message );
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/main/java/org/codehaus/mojo/license/utils/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/utils/LicenseSummaryWriter.java
index 28260c873..d3704ad7d 100644
--- a/src/main/java/org/codehaus/mojo/license/utils/LicenseSummaryWriter.java
+++ b/src/main/java/org/codehaus/mojo/license/utils/LicenseSummaryWriter.java
@@ -116,6 +116,20 @@ public static Node createDependencyNode( Document doc, ProjectLicenseInfo dep )
}
}
depNode.appendChild( licensesNode );
+
+ final List messages = dep.getDownloaderMessages();
+ if ( messages != null && !messages.isEmpty() )
+ {
+ final Node downloaderMessagesNode = doc.createElement( "downloaderMessages" );
+ for ( String msg : messages )
+ {
+ final Node downloaderMessageNode = doc.createElement( "downloaderMessage" );
+ downloaderMessageNode.appendChild( doc.createTextNode( msg ) );
+ downloaderMessagesNode.appendChild( downloaderMessageNode );
+ }
+ depNode.appendChild( downloaderMessagesNode );
+ }
+
return depNode;
}