diff --git a/.travis.yml b/.travis.yml index 746f0ce..6caa18b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: java -script: mvn -e clean install site jdk: - oraclejdk9 - oraclejdk8 - openjdk7 +install: mvn -B -V -e package -DskipTests +script: mvn -B -e verify site diff --git a/CHANGELOG.md b/CHANGELOG.md index e376a48..a30abef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Directory Content Maven Plugin Changelog +## 2.0.1 +Bugs: +* Fixed XML transformers should be secured ([#15](https://github.com/gabrysbiz/directory-content-maven-plugin/issues/15)) + +[See documentation](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/) + ## 2.0.0 Features: * Set compatibility with Java 6+ diff --git a/Jenkinsfile b/Jenkinsfile index 90bd488..b9502a0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,34 +1,45 @@ -properties([[ - $class: 'BuildDiscarderProperty', - strategy: [ - $class: 'LogRotator', - artifactDaysToKeepStr: '-1', - artifactNumToKeepStr: '10', - daysToKeepStr: '-1', - numToKeepStr: '10' - ] -]]) - -node { - timestamps { - stage('Pre Build Cleanup') { - step($class: 'WsCleanup') - } - stage('Checkout') { - checkout scm - } +pipeline { + agent any + options { + buildDiscarder(logRotator(artifactDaysToKeepStr: '-1', artifactNumToKeepStr: '10', daysToKeepStr: '-1', numToKeepStr: '10')) + timestamps() + } + tools { + // withMaven ignores tools: https://issues.jenkins-ci.org/browse/JENKINS-43651 + maven 'MVN-3' + jdk 'JDK-9' + } + environment { + MAVEN_ARGS = '-e -Dmaven.repo.local=.repository' + } + stages { stage('Build') { - withMaven(maven: 'MVN-3', jdk: 'JDK-9', mavenLocalRepo: '.repository', options: [junitPublisher(disabled: true)]) { - sh 'mvn -e install site -DskipTests' + steps { + withMaven(maven: 'MVN-3', jdk: 'JDK-9', publisherStrategy: 'EXPLICIT', options: [ + artifactsPublisher(disabled: false), dependenciesFingerprintPublisher(disabled: false), openTasksPublisher(disabled: false) + ]) { + sh "mvn ${MAVEN_ARGS} package -DskipTests" + } + } + } + stage('Verify') { + steps { + withMaven(maven: 'MVN-3', jdk: 'JDK-9', publisherStrategy: 'EXPLICIT', options: [junitPublisher(disabled: false)]) { + sh "mvn ${MAVEN_ARGS} verify" + } } } - stage('Test') { - withMaven(maven: 'MVN-3', jdk: 'JDK-9', mavenLocalRepo: '.repository', options: [openTasksPublisher(disabled: true), dependenciesFingerprintPublisher(disabled: true)]) { - sh 'mvn -e test' + stage('Build Docs') { + steps { + withMaven(maven: 'MVN-3', jdk: 'JDK-9', publisherStrategy: 'EXPLICIT') { + sh "mvn ${MAVEN_ARGS} site" + } } } - stage('Post Build Cleanup') { - step($class: 'WsCleanup') + } + post { + always { + cleanWs() } } } diff --git a/README.md b/README.md index 40bf726..ebc7049 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ Provides a collection of tools for working with directories. # Goals Overview -* [directory-content:copy](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/copy-mojo.html) - copies files to directory -* [directory-content:copyFile](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/copyFile-mojo.html) - copies file from source to output directory (allow to change name) -* [directory-content:transformList](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/transformList-mojo.html) - transforms files list to a document using [XSLT](http://www.w3.org/TR/xslt) technology -* [directory-content:transformMetadata](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/transformMetadata-mojo.html) - transforms files metadata to documents using [XSLT](http://www.w3.org/TR/xslt) technology +* [directory-content:copy](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/copy-mojo.html) - copies files to directory +* [directory-content:copyFile](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/copyFile-mojo.html) - copies file from source to output directory (allow to change name) +* [directory-content:transformList](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/transformList-mojo.html) - transforms files list to a document using [XSLT](http://www.w3.org/TR/xslt) technology +* [directory-content:transformMetadata](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/transformMetadata-mojo.html) - transforms files metadata to documents using [XSLT](http://www.w3.org/TR/xslt) technology # Requirements The plugin to run requires: @@ -16,18 +16,18 @@ The plugin to run requires: * Maven 3 or higher # Usage -General instructions on how to use the Directory Content Maven Plugin can be found on the [usage](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/usage.html) page. Some more specific use cases are described in the examples given below. Last but not least, users occasionally contribute additional examples, tips or errata to the plugin's [wiki](https://github.com/gabrysbiz/directory-content-maven-plugin/wiki) page. +General instructions on how to use the Directory Content Maven Plugin can be found on the [usage](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/usage.html) page. Some more specific use cases are described in the examples given below. Last but not least, users occasionally contribute additional examples, tips or errata to the plugin's [wiki](https://github.com/gabrysbiz/directory-content-maven-plugin/wiki) page. -In case you still have questions regarding the plugin's usage, please have a look at the [FAQ](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/faq.html). +In case you still have questions regarding the plugin's usage, please have a look at the [FAQ](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/faq.html). -If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in the [issue tracker](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/issue-tracking.html). When creating a new issue, please provide a comprehensive description of your concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason, entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. Of course, patches are welcome, too. Contributors can check out the project from the [source repository](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/source-repository.html) and will find supplementary information in the [guide to helping with Maven](http://maven.apache.org/guides/development/guide-helping.html). +If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in the [issue tracker](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/issue-tracking.html). When creating a new issue, please provide a comprehensive description of your concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason, entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. Of course, patches are welcome, too. Contributors can check out the project from the [source repository](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/source-repository.html) and will find supplementary information in the [guide to helping with Maven](http://maven.apache.org/guides/development/guide-helping.html). # Examples To provide you with better understanding of some usages of the Directory Content Maven Plugin, you can take a look into the following examples: -* [Using include/exclude patterns](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/examples/patterns.html) -* [Copies files from source to output directory](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/examples/copy.html) -* [Copies file to output directory with a new name](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/examples/copyFile.html) -* [Transform files list to file with JavaScript imports](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/examples/transform-list.html) -* [Transform files metadata to download files](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/examples/transform-metadata.html) +* [Using include/exclude patterns](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/examples/patterns.html) +* [Copies files from source to output directory](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/examples/copy.html) +* [Copies file to output directory with a new name](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/examples/copyFile.html) +* [Transform files list to file with JavaScript imports](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/examples/transform-list.html) +* [Transform files metadata to download files](http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/examples/transform-metadata.html) You can also fetch example projects from [GitHub](https://github.com/gabrysbiz/directory-content-maven-plugin-examples). \ No newline at end of file diff --git a/pom.xml b/pom.xml index a2ff921..5aca178 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,11 @@ biz.gabrys.maven.plugins directory-content-maven-plugin - 2.0.0 + 2.0.1 maven-plugin Directory Content Maven Plugin Provides a collection of tools for working with directories. - http://directory-content-maven-plugin.projects.gabrys.biz/2.0.0/ + http://directory-content-maven-plugin.projects.gabrys.biz/2.0.1/ 2015 @@ -80,7 +80,7 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.5 + 3.5.2 provided @@ -113,7 +113,7 @@ org.mockito mockito-core - 2.13.0 + 2.19.0 test @@ -141,7 +141,7 @@ maven-clean-plugin - 3.0.0 + 3.1.0 maven-compiler-plugin @@ -161,7 +161,7 @@ maven-jar-plugin - 3.0.2 + 3.1.0 maven-jxr-plugin @@ -172,7 +172,7 @@ maven-plugin-plugin - 3.5 + 3.5.2 maven-project-info-reports-plugin @@ -180,11 +180,11 @@ maven-resources-plugin - 3.0.2 + 3.1.0 maven-site-plugin - 3.6 + 3.7.1 maven-source-plugin @@ -192,7 +192,7 @@ maven-surefire-plugin - 2.20.1 + 2.22.0 com.mycila @@ -214,7 +214,7 @@ org.jacoco jacoco-maven-plugin - 0.7.9 + 0.8.1 diff --git a/src/main/java/biz/gabrys/maven/plugins/directory/content/transform/XsltTransformer.java b/src/main/java/biz/gabrys/maven/plugins/directory/content/transform/XsltTransformer.java index 44f467c..4ef8c95 100644 --- a/src/main/java/biz/gabrys/maven/plugins/directory/content/transform/XsltTransformer.java +++ b/src/main/java/biz/gabrys/maven/plugins/directory/content/transform/XsltTransformer.java @@ -16,6 +16,7 @@ import java.io.StringReader; import java.io.StringWriter; +import javax.xml.XMLConstants; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; @@ -38,13 +39,7 @@ public class XsltTransformer { * @since 1.0 */ public String transform(final String xml, final File xslt) throws TransformException { - final TransformerFactory factory = TransformerFactory.newInstance(); - final Transformer transformer; - try { - transformer = factory.newTransformer(new StreamSource(xslt)); - } catch (final TransformerConfigurationException e) { - throw new TransformException(e); - } + final Transformer transformer = createTransformer(createTransformerFactory(), xslt); final StringWriter writer = new StringWriter(); try { transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(writer)); @@ -54,4 +49,22 @@ public String transform(final String xml, final File xslt) throws TransformExcep writer.flush(); return writer.toString(); } + + Transformer createTransformer(final TransformerFactory factory, final File xslt) throws TransformException { + try { + return factory.newTransformer(new StreamSource(xslt)); + } catch (final TransformerConfigurationException e) { + throw new TransformException(e); + } + } + + TransformerFactory createTransformerFactory() throws TransformException { + final TransformerFactory factory = TransformerFactory.newInstance(); + try { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (final TransformerConfigurationException e) { + throw new TransformException(e); + } + return factory; + } } diff --git a/src/site/site.xml b/src/site/site.xml index d591745..233e1f7 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -10,7 +10,7 @@ org.apache.maven.skins maven-fluido-skin - 1.6 + 1.7 diff --git a/src/test/java/biz/gabrys/maven/plugins/directory/content/transform/XsltTransformerTest.java b/src/test/java/biz/gabrys/maven/plugins/directory/content/transform/XsltTransformerTest.java new file mode 100644 index 0000000..0cd7a00 --- /dev/null +++ b/src/test/java/biz/gabrys/maven/plugins/directory/content/transform/XsltTransformerTest.java @@ -0,0 +1,114 @@ +package biz.gabrys.maven.plugins.directory.content.transform; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import java.net.URI; + +import javax.xml.XMLConstants; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +public class XsltTransformerTest { + + @Test(expected = TransformException.class) + public void transform_invalidData_throwsException() throws TransformerException, TransformException { + final XsltTransformer xsltTransformer = spy(new XsltTransformer()); + + final TransformerFactory factory = mock(TransformerFactory.class); + doReturn(factory).when(xsltTransformer).createTransformerFactory(); + final Transformer transformer = mock(Transformer.class); + doReturn(transformer).when(xsltTransformer).createTransformer(eq(factory), any(File.class)); + + doThrow(TransformerException.class).when(transformer).transform(any(StreamSource.class), any(StreamResult.class)); + final String xml = "xml"; + final File xslt = mock(File.class); + + xsltTransformer.transform(xml, xslt); + } + + @Test + public void transform_correctData_returnsTransformedDocument() throws TransformerException, TransformException { + final XsltTransformer xsltTransformer = spy(new XsltTransformer()); + + final TransformerFactory factory = mock(TransformerFactory.class); + doReturn(factory).when(xsltTransformer).createTransformerFactory(); + final Transformer transformer = mock(Transformer.class); + doReturn(transformer).when(xsltTransformer).createTransformer(eq(factory), any(File.class)); + + doAnswer(new Answer() { + + @Override + public Void answer(final InvocationOnMock invocation) throws IOException { + final StreamResult result = (StreamResult) invocation.getArgument(1); + result.getWriter().append("document"); + return null; + } + }).when(transformer).transform(any(StreamSource.class), any(StreamResult.class)); + + final String xml = "xml"; + final File xslt = mock(File.class); + + final String result = xsltTransformer.transform(xml, xslt); + + assertThat(result).isEqualTo("document"); + } + + @Test(expected = TransformException.class) + public void createTransformer_sourceIsInvalid_throwsException() throws TransformerConfigurationException, TransformException { + final TransformerFactory factory = mock(TransformerFactory.class); + when(factory.newTransformer(any(StreamSource.class))).thenThrow(TransformerConfigurationException.class); + + final File xslt = mock(File.class); + when(xslt.toURI()).thenReturn(URI.create("uri")); + + new XsltTransformer().createTransformer(factory, xslt); + } + + @Test + public void createTransformer_sourceIsValid_returnsTransformer() throws TransformerConfigurationException, TransformException { + final TransformerFactory factory = mock(TransformerFactory.class); + final Transformer transformer = mock(Transformer.class); + when(factory.newTransformer(any(StreamSource.class))).thenReturn(transformer); + + final File xslt = mock(File.class); + final String uri = "file.xslt"; + when(xslt.toURI()).thenReturn(URI.create(uri)); + + final Transformer result = new XsltTransformer().createTransformer(factory, xslt); + + assertThat(result).isSameAs(transformer); + final ArgumentCaptor captor = ArgumentCaptor.forClass(StreamSource.class); + verify(factory).newTransformer(captor.capture()); + final StreamSource source = captor.getValue(); + assertThat(source).isNotNull(); + assertThat(source.getSystemId()).isEqualTo(uri); + } + + @Test + public void createTransformerFactory() throws TransformException { + final TransformerFactory result = new XsltTransformer().createTransformerFactory(); + + assertThat(result).isNotNull(); + assertThat(result.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)).isTrue(); + } +} diff --git a/xdocs/changelog.xml b/xdocs/changelog.xml index 461c24c..d888ff4 100644 --- a/xdocs/changelog.xml +++ b/xdocs/changelog.xml @@ -7,6 +7,15 @@ +
+

Bugs:

+
    +
  • + Fixed XML transformers should be secured + (#15) +
  • +
+

Features:

    @@ -21,6 +30,7 @@ to 2.0.0
+

See documentation

Bugs: