diff --git a/codec/src/main/java/io/netty/handler/codec/xml/XmlFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/xml/XmlFrameDecoder.java
new file mode 100644
index 0000000000..b3d5e2fb3e
--- /dev/null
+++ b/codec/src/main/java/io/netty/handler/codec/xml/XmlFrameDecoder.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project 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.
+ */
+package io.netty.handler.codec.xml;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+import io.netty.handler.codec.CorruptedFrameException;
+import io.netty.handler.codec.TooLongFrameException;
+import io.netty.util.CharsetUtil;
+
+import java.util.List;
+
+/**
+ * A frame decoder for single separate XML based message streams.
+ *
+ * A couple examples will better help illustrate
+ * what this decoder actually does.
+ *
+ * Given an input array of bytes split over 3 frames like this:
+ *
+ * +-----+-----+-----------+
+ * | <an | Xml | Element/> |
+ * +-----+-----+-----------+
+ *
+ *
+ * this decoder would output a single frame:
+ *
+ *
+ * +-----------------+
+ * | <anXmlElement/> |
+ * +-----------------+
+ *
+ *
+ * Given an input array of bytes split over 5 frames like this:
+ *
+ * +-----+-----+-----------+-----+----------------------------------+
+ * | <an | Xml | Element/> | <ro | ot><child>content</child></root> |
+ * +-----+-----+-----------+-----+----------------------------------+
+ *
+ *
+ * this decoder would output two frames:
+ *
+ *
+ * +-----------------+-------------------------------------+
+ * | <anXmlElement/> | <root><child>content</child></root> |
+ * +-----------------+-------------------------------------+
+ *
+ *
+ * Please note that this decoder is not suitable for
+ * xml streaming protocols such as
+ * XMPP ,
+ * where an initial xml element opens the stream and only
+ * gets closed at the end of the session, although this class
+ * could probably allow for such type of message flow with
+ * minor modifications.
+ */
+public class XmlFrameDecoder extends ByteToMessageDecoder {
+
+ private final int maxFrameLength;
+
+ public XmlFrameDecoder(int maxFrameLength) {
+ if (maxFrameLength < 1) {
+ throw new IllegalArgumentException("maxFrameLength must be a positive int");
+ }
+ this.maxFrameLength = maxFrameLength;
+ }
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {
+ boolean openingBracketFound = false;
+ boolean atLeastOneXmlElementFound = false;
+ long openBracketsCount = 0;
+ int length = 0;
+ int leadingWhiteSpaceCount = 0;
+ final int bufferLength = in.writerIndex();
+
+ if (bufferLength > maxFrameLength) {
+ // bufferLength exceeded maxFrameLength; dropping frame
+ fail(ctx, bufferLength);
+ in.skipBytes(in.readableBytes());
+ return;
+ }
+
+ for (int i = in.readerIndex(); i < bufferLength; i++) {
+ final byte readByte = in.getByte(i);
+ if (!openingBracketFound && Character.isWhitespace(readByte)) {
+ // xml has not started and whitespace char found
+ leadingWhiteSpaceCount ++;
+ } else if (!openingBracketFound && readByte != '<') {
+ // garbage found before xml start
+ fail(ctx);
+ in.skipBytes(in.readableBytes());
+ return;
+ } else if (readByte == '<') {
+ openingBracketFound = true;
+
+ if (i < bufferLength - 1) {
+ final byte peekAheadByte = in.getByte(i + 1);
+ if (peekAheadByte == '/') {
+ // found , decrementing openBracketsCount
+ openBracketsCount--;
+ } else if (isValidStartCharForXmlElement(peekAheadByte)) {
+ atLeastOneXmlElementFound = true;
+ // char after < is a valid xml element start char,
+ // incrementing openBracketsCount
+ openBracketsCount++;
+ } else if (peekAheadByte == '!' && i < bufferLength - 3
+ && in.getByte(i + 2) == '-'
+ && in.getByte(i + 3) == '-') {
+ // start found
+ openBracketsCount++;
+ } else if (peekAheadByte == '?') {
+ // start found
+ openBracketsCount++;
+ }
+ }
+ } else if (readByte == '/') {
+ if (i < bufferLength - 1 && in.getByte(i + 1) == '>') {
+ // found />, decrementing openBracketsCount
+ openBracketsCount--;
+ }
+ } else if (readByte == '>') {
+ length = i + 1;
+
+ if (i - 1 > -1) {
+ final byte peekBehindByte = in.getByte(i - 1);
+
+ if (peekBehindByte == '?') {
+ // an tag was closed
+ openBracketsCount--;
+ } else if (peekBehindByte == '-' && i - 2 > -1 && in.getByte(i - 2) == '-') {
+ // a was closed
+ openBracketsCount--;
+ }
+ }
+
+ if (openingBracketFound && atLeastOneXmlElementFound && openBracketsCount == 0) {
+ // xml is balanced, bailing out
+ break;
+ }
+ }
+ }
+
+ final int readerIndex = in.readerIndex();
+
+ if (openBracketsCount == 0 && length > 0) {
+ final ByteBuf frame =
+ extractFrame(in, readerIndex + leadingWhiteSpaceCount, length - leadingWhiteSpaceCount);
+ System.err.println(in + ", " + frame + ", " + frame.toString(CharsetUtil.UTF_8));
+ in.skipBytes(length);
+ out.add(frame);
+ }
+ }
+
+ private void fail(ChannelHandlerContext ctx, long frameLength) {
+ if (frameLength > 0) {
+ ctx.fireExceptionCaught(
+ new TooLongFrameException(
+ "frame length exceeds " + maxFrameLength + ": " + frameLength + " - discarded"));
+ } else {
+ ctx.fireExceptionCaught(
+ new TooLongFrameException(
+ "frame length exceeds " + maxFrameLength + " - discarding"));
+ }
+ }
+
+ private static void fail(ChannelHandlerContext ctx) {
+ ctx.fireExceptionCaught(new CorruptedFrameException("frame contains content before the xml starts"));
+ }
+
+ private static ByteBuf extractFrame(ByteBuf buffer, int index, int length) {
+ return buffer.copy(index, length);
+ }
+
+ /**
+ * Asks whether the given byte is a valid
+ * start char for an xml element name.
+ *
+ * Please refer to the
+ * NameStartChar
+ * formal definition in the W3C XML spec for further info.
+ *
+ * @param b the input char
+ * @return true if the char is a valid start char
+ */
+ private static boolean isValidStartCharForXmlElement(final byte b) {
+ return b >= 'a' && b <= 'z' || b >= 'A' && b <= 'Z' || b == ':' || b == '_';
+ }
+}
diff --git a/codec/src/test/java/io/netty/handler/codec/xml/XmlFrameDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/xml/XmlFrameDecoderTest.java
new file mode 100644
index 0000000000..835213ca0e
--- /dev/null
+++ b/codec/src/test/java/io/netty/handler/codec/xml/XmlFrameDecoderTest.java
@@ -0,0 +1,785 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project 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.
+ */
+
+package io.netty.handler.codec.xml;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.embedded.EmbeddedChannel;
+import io.netty.handler.codec.CorruptedFrameException;
+import io.netty.handler.codec.TooLongFrameException;
+import io.netty.util.CharsetUtil;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
+public class XmlFrameDecoderTest {
+
+ private final List xmlSamples =
+ Arrays.asList(SAMPLE_01, SAMPLE_02, SAMPLE_03, SAMPLE_04);
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConstructorWithIllegalArgs01() {
+ new XmlFrameDecoder(0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConstructorWithIllegalArgs02() {
+ new XmlFrameDecoder(-23);
+ }
+
+ @Test(expected = TooLongFrameException.class)
+ public void testDecodeWithFrameExceedingMaxLength() {
+ XmlFrameDecoder decoder = new XmlFrameDecoder(3);
+ EmbeddedChannel ch = new EmbeddedChannel(decoder);
+ ch.writeInbound(Unpooled.copiedBuffer(" ", CharsetUtil.UTF_8));
+ }
+
+ @Test(expected = CorruptedFrameException.class)
+ public void testDecodeWithInvalidInput() {
+ XmlFrameDecoder decoder = new XmlFrameDecoder(1048576);
+ EmbeddedChannel ch = new EmbeddedChannel(decoder);
+ ch.writeInbound(Unpooled.copiedBuffer("invalid XML", CharsetUtil.UTF_8));
+ }
+
+ @Test(expected = CorruptedFrameException.class)
+ public void testDecodeWithInvalidContentBeforeXml() {
+ XmlFrameDecoder decoder = new XmlFrameDecoder(1048576);
+ EmbeddedChannel ch = new EmbeddedChannel(decoder);
+ ch.writeInbound(Unpooled.copiedBuffer("invalid XML ", CharsetUtil.UTF_8));
+ }
+
+ @Test
+ public void testDecodeShortValidXml() {
+ testDecodeWithXml(" ", " ");
+ }
+
+ @Test
+ public void testDecodeShortValidXmlWithLeadingWhitespace01() {
+ testDecodeWithXml(" ", " ");
+ }
+
+ @Test
+ public void testDecodeShortValidXmlWithLeadingWhitespace02() {
+ testDecodeWithXml(" \n\r \t \t", " ");
+ }
+
+ @Test
+ public void testDecodeShortValidXmlWithLeadingWhitespace02AndTrailingGarbage() {
+ testDecodeWithXml(" \n\r \t \ttrash", " ", CorruptedFrameException.class);
+ }
+
+ @Test
+ public void testDecodeWithTwoMessages() {
+ testDecodeWithXml(
+ "\n" +
+ '\n' +
+ "\n" +
+ "\n" +
+ " ",
+ "",
+ "\n" +
+ "\n" +
+ " "
+ );
+ }
+
+ @Test
+ public void testDecodeWithSampleXml() {
+ for (final String xmlSample : xmlSamples) {
+ testDecodeWithXml(xmlSample, xmlSample);
+ }
+ }
+
+ private static void testDecodeWithXml(String xml, Object... expected) {
+ EmbeddedChannel ch = new EmbeddedChannel(new XmlFrameDecoder(1048576));
+ Exception cause = null;
+ try {
+ ch.writeInbound(Unpooled.copiedBuffer(xml, CharsetUtil.UTF_8));
+ } catch (Exception e) {
+ cause = e;
+ e.printStackTrace();
+ }
+ List actual = new ArrayList();
+ for (;;) {
+ ByteBuf buf = (ByteBuf) ch.readInbound();
+ if (buf == null) {
+ break;
+ }
+ actual.add(buf.toString(CharsetUtil.UTF_8));
+ }
+
+ if (cause != null) {
+ actual.add(cause.getClass());
+ }
+
+ List expectedList = new ArrayList();
+ Collections.addAll(expectedList, expected);
+ assertThat(actual, is(expectedList));
+ }
+
+ private static final String SAMPLE_01 = "";
+
+ private static final String SAMPLE_02 = "\n" +
+ "\n" +
+ " ";
+
+ private static final String SAMPLE_03 = "\n" +
+ "\n" +
+ "\n" +
+ '\n' +
+ " 4.0.0 \n" +
+ " \n" +
+ " org.sonatype.oss \n" +
+ " oss-parent \n" +
+ " 7 \n" +
+ " \n" +
+ '\n' +
+ " io.netty \n" +
+ " netty-parent \n" +
+ " pom \n" +
+ " 4.0.0.Beta3-SNAPSHOT \n" +
+ '\n' +
+ " Netty \n" +
+ " http://netty.io/ \n" +
+ " \n" +
+ " Netty is an asynchronous event-driven network application framework for \n" +
+ " rapid development of maintainable high performance protocol servers and\n" +
+ " clients.\n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " The Netty Project \n" +
+ " http://netty.io/ \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " Apache License, Version 2.0 \n" +
+ " http://www.apache.org/licenses/LICENSE-2.0 \n" +
+ " \n" +
+ " \n" +
+ " 2008 \n" +
+ '\n' +
+ " \n" +
+ " https://github.com/netty/netty \n" +
+ " scm:git:git://github.com/netty/netty.git \n" +
+ " scm:git:ssh://git@github.com/netty/netty.git \n" +
+ " HEAD \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " netty.io \n" +
+ " The Netty Project Contributors \n" +
+ " netty@googlegroups.com \n" +
+ " http://netty.io/ \n" +
+ " The Netty Project \n" +
+ " http://netty.io/ \n" +
+ " \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " UTF-8 \n" +
+ " UTF-8 \n" +
+ " 1.3.14.GA \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " common \n" +
+ " buffer \n" +
+ " codec \n" +
+ " codec-http \n" +
+ " codec-socks \n" +
+ " transport \n" +
+ " transport-rxtx \n" +
+ " transport-sctp \n" +
+ " transport-udt \n" +
+ " handler \n" +
+ " example \n" +
+ " testsuite \n" +
+ " testsuite-osgi \n" +
+ " microbench \n" +
+ " all \n" +
+ " tarball \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.jboss.marshalling \n" +
+ " jboss-marshalling \n" +
+ " ${jboss.marshalling.version} \n" +
+ " compile \n" +
+ " true \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " com.google.protobuf \n" +
+ " protobuf-java \n" +
+ " 2.4.1 \n" +
+ " \n" +
+ " \n" +
+ " com.jcraft \n" +
+ " jzlib \n" +
+ " 1.1.2 \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " org.rxtx \n" +
+ " rxtx \n" +
+ " 2.1.7 \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " com.barchart.udt \n" +
+ " barchart-udt-bundle \n" +
+ " 2.2.2 \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " javax.servlet \n" +
+ " servlet-api \n" +
+ " 2.5 \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " org.slf4j \n" +
+ " slf4j-api \n" +
+ " 1.7.2 \n" +
+ " \n" +
+ " \n" +
+ " commons-logging \n" +
+ " commons-logging \n" +
+ " 1.1.1 \n" +
+ " \n" +
+ " \n" +
+ " log4j \n" +
+ " log4j \n" +
+ " 1.2.17 \n" +
+ " \n" +
+ " \n" +
+ " mail \n" +
+ " javax.mail \n" +
+ " \n" +
+ " \n" +
+ " jms \n" +
+ " javax.jms \n" +
+ " \n" +
+ " \n" +
+ " jmxtools \n" +
+ " com.sun.jdmk \n" +
+ " \n" +
+ " \n" +
+ " jmxri \n" +
+ " com.sun.jmx \n" +
+ " \n" +
+ " \n" +
+ " true \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " com.yammer.metrics \n" +
+ " metrics-core \n" +
+ " 2.2.0 \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.jboss.marshalling \n" +
+ " jboss-marshalling-serial \n" +
+ " ${jboss.marshalling.version} \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ " org.jboss.marshalling \n" +
+ " jboss-marshalling-river \n" +
+ " ${jboss.marshalling.version} \n" +
+ " test \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " com.google.caliper \n" +
+ " caliper \n" +
+ " 0.5-rc1 \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.javassist \n" +
+ " javassist \n" +
+ " 3.17.1-GA \n" +
+ " compile \n" +
+ " true \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " junit \n" +
+ " junit \n" +
+ " 4.10 \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.hamcrest \n" +
+ " hamcrest-core \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.hamcrest \n" +
+ " hamcrest-library \n" +
+ " 1.3 \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ " org.easymock \n" +
+ " easymock \n" +
+ " 3.1 \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ " org.easymock \n" +
+ " easymockclassextension \n" +
+ " 3.1 \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ " org.jmock \n" +
+ " jmock-junit4 \n" +
+ " 2.5.1 \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ " ch.qos.logback \n" +
+ " logback-classic \n" +
+ " 1.0.9 \n" +
+ " test \n" +
+ " \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-enforcer-plugin \n" +
+ " 1.1 \n" +
+ " \n" +
+ " \n" +
+ " enforce-tools \n" +
+ " \n" +
+ " enforce \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " [1.7.0,) \n" +
+ " \n" +
+ " \n" +
+ " [3.0.5,) \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-compiler-plugin \n" +
+ " 2.5.1 \n" +
+ " \n" +
+ " 1.7 \n" +
+ " true \n" +
+ " 1.6 \n" +
+ " 1.6 \n" +
+ " true \n" +
+ " true \n" +
+ " true \n" +
+ " true \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.codehaus.mojo \n" +
+ " animal-sniffer-maven-plugin \n" +
+ " 1.8 \n" +
+ " \n" +
+ " \n" +
+ " org.codehaus.mojo.signature \n" +
+ " java16 \n" +
+ " 1.0 \n" +
+ " \n" +
+ " \n" +
+ " sun.misc.Unsafe \n" +
+ " sun.misc.Cleaner \n" +
+ '\n' +
+ " java.util.zip.Deflater \n" +
+ '\n' +
+ " \n" +
+ " java.nio.channels.DatagramChannel \n" +
+ " java.nio.channels.MembershipKey \n" +
+ " java.net.StandardProtocolFamily \n" +
+ '\n' +
+ " \n" +
+ " java.nio.channels.AsynchronousChannel \n" +
+ " java.nio.channels.AsynchronousSocketChannel \n" +
+ " java.nio.channels.AsynchronousServerSocketChannel \n" +
+ " java.nio.channels.AsynchronousChannelGroup \n" +
+ " java.nio.channels.NetworkChannel \n" +
+ " java.nio.channels.InterruptedByTimeoutException \n" +
+ " java.net.StandardSocketOptions \n" +
+ " java.net.SocketOption \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " process-classes \n" +
+ " \n" +
+ " check \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-checkstyle-plugin \n" +
+ " 2.9.1 \n" +
+ " \n" +
+ " \n" +
+ " check-style \n" +
+ " \n" +
+ " check \n" +
+ " \n" +
+ " validate \n" +
+ " \n" +
+ " true \n" +
+ " true \n" +
+ " true \n" +
+ " true \n" +
+ " io/netty/checkstyle.xml \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ${project.groupId} \n" +
+ " netty-build \n" +
+ " 17 \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-surefire-plugin \n" +
+ " \n" +
+ " \n" +
+ " **/*Test*.java \n" +
+ " **/*Benchmark*.java \n" +
+ " \n" +
+ " \n" +
+ " **/Abstract* \n" +
+ " **/TestUtil* \n" +
+ " \n" +
+ " random \n" +
+ " \n" +
+ " -server \n" +
+ " -Dio.netty.resourceLeakDetection\n" +
+ " -dsa -da -ea:io.netty...\n" +
+ " -XX:+AggressiveOpts\n" +
+ " -XX:+TieredCompilation\n" +
+ " -XX:+UseBiasedLocking\n" +
+ " -XX:+UseFastAccessorMethods\n" +
+ " -XX:+UseStringCache\n" +
+ " -XX:+OptimizeStringConcat\n" +
+ " -XX:+HeapDumpOnOutOfMemoryError\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.apache.felix \n" +
+ " maven-bundle-plugin \n" +
+ " 2.3.7 \n" +
+ " true \n" +
+ " \n" +
+ " \n" +
+ " maven-source-plugin \n" +
+ " 2.1.2 \n" +
+ " \n" +
+ " \n" +
+ " attach-sources \n" +
+ " \n" +
+ " jar \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-javadoc-plugin \n" +
+ " 2.8.1 \n" +
+ " \n" +
+ " false \n" +
+ " true \n" +
+ " false \n" +
+ " false \n" +
+ " true \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-deploy-plugin \n" +
+ " 2.7 \n" +
+ " \n" +
+ " 10 \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-release-plugin \n" +
+ " 2.3.2 \n" +
+ " \n" +
+ " false \n" +
+ " -P release,sonatype-oss-release,full \n" +
+ " true \n" +
+ " true \n" +
+ " netty-@{project.version} \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-surefire-plugin \n" +
+ " 2.12 \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " maven-failsafe-plugin \n" +
+ " 2.12 \n" +
+ " \n" +
+ " \n" +
+ " maven-clean-plugin \n" +
+ " 2.5 \n" +
+ " \n" +
+ " \n" +
+ " maven-resources-plugin \n" +
+ " 2.5 \n" +
+ " \n" +
+ " \n" +
+ " maven-jar-plugin \n" +
+ " 2.4 \n" +
+ " \n" +
+ " \n" +
+ " maven-dependency-plugin \n" +
+ " 2.4 \n" +
+ " \n" +
+ " \n" +
+ " maven-assembly-plugin \n" +
+ " 2.3 \n" +
+ " \n" +
+ " \n" +
+ " maven-jxr-plugin \n" +
+ " 2.2 \n" +
+ " \n" +
+ " \n" +
+ " maven-antrun-plugin \n" +
+ " 1.7 \n" +
+ " \n" +
+ " \n" +
+ " ant-contrib \n" +
+ " ant-contrib \n" +
+ " 1.0b3 \n" +
+ " \n" +
+ " \n" +
+ " ant \n" +
+ " ant \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.codehaus.mojo \n" +
+ " build-helper-maven-plugin \n" +
+ " 1.7 \n" +
+ " \n" +
+ '\n' +
+ " \n" +
+ " \n" +
+ " org.eclipse.m2e \n" +
+ " lifecycle-mapping \n" +
+ " 1.0.0 \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.apache.maven.plugins \n" +
+ " maven-checkstyle-plugin \n" +
+ " [1.0,) \n" +
+ " \n" +
+ " check \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " false \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.apache.maven.plugins \n" +
+ " maven-enforcer-plugin \n" +
+ " [1.0,) \n" +
+ " \n" +
+ " enforce \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " false \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " org.apache.maven.plugins \n" +
+ " maven-clean-plugin \n" +
+ " [1.0,) \n" +
+ " \n" +
+ " clean \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " false \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ private static final String SAMPLE_04 = "\n" +
+ "\n" +
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+}