Author: tallison
Date: Wed Jun 3 17:55:47 2015
New Revision: 1683398
URL: http://svn.apache.org/r1683398
Log:
TIKA-1646 fix RecursiveParserWrapper to add Metadata object even if an
exception is hit while parsing the container
Added:
tika/trunk/tika-batch/src/test/java/org/apache/tika/batch/RecursiveParserWrapperFSConsumerTest.java
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_then_npe.xml
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_with_npe.xml
tika/trunk/tika-parsers/src/test/resources/test-documents/mock/embedded_then_npe.xml
Modified:
tika/trunk/tika-batch/src/main/java/org/apache/tika/batch/fs/AbstractFSConsumer.java
tika/trunk/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java
tika/trunk/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java
tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java
Modified:
tika/trunk/tika-batch/src/main/java/org/apache/tika/batch/fs/AbstractFSConsumer.java
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-batch/src/main/java/org/apache/tika/batch/fs/AbstractFSConsumer.java?rev=1683398&r1=1683397&r2=1683398&view=diff
==============================================================================
---
tika/trunk/tika-batch/src/main/java/org/apache/tika/batch/fs/AbstractFSConsumer.java
(original)
+++
tika/trunk/tika-batch/src/main/java/org/apache/tika/batch/fs/AbstractFSConsumer.java
Wed Jun 3 17:55:47 2015
@@ -26,10 +26,6 @@ import org.apache.tika.batch.BatchNoRest
import org.apache.tika.batch.FileResource;
import org.apache.tika.batch.FileResourceConsumer;
import org.apache.tika.batch.OutputStreamFactory;
-import org.apache.tika.metadata.Metadata;
-import org.apache.tika.parser.ParseContext;
-import org.apache.tika.parser.Parser;
-import org.xml.sax.ContentHandler;
public abstract class AbstractFSConsumer extends FileResourceConsumer {
Added:
tika/trunk/tika-batch/src/test/java/org/apache/tika/batch/RecursiveParserWrapperFSConsumerTest.java
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-batch/src/test/java/org/apache/tika/batch/RecursiveParserWrapperFSConsumerTest.java?rev=1683398&view=auto
==============================================================================
---
tika/trunk/tika-batch/src/test/java/org/apache/tika/batch/RecursiveParserWrapperFSConsumerTest.java
(added)
+++
tika/trunk/tika-batch/src/test/java/org/apache/tika/batch/RecursiveParserWrapperFSConsumerTest.java
Wed Jun 3 17:55:47 2015
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+package org.apache.tika.batch;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import org.apache.tika.TikaTest;
+import org.apache.tika.batch.fs.RecursiveParserWrapperFSConsumer;
+import org.apache.tika.config.TikaConfig;
+import org.apache.tika.io.IOUtils;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.metadata.serialization.JsonMetadataList;
+import org.apache.tika.parser.RecursiveParserWrapper;
+import org.apache.tika.sax.BasicContentHandlerFactory;
+import org.junit.Test;
+
+public class RecursiveParserWrapperFSConsumerTest extends TikaTest {
+
+
+ @Test
+ public void testEmbeddedWithNPE() throws Exception {
+ final String path = "/test-documents/embedded_with_npe.xml";
+ final Metadata metadata = new Metadata();
+ metadata.add(Metadata.RESOURCE_NAME_KEY, "embedded_with_npe.xml");
+
+ ArrayBlockingQueue<FileResource> queue = new
ArrayBlockingQueue<FileResource>(2);
+ queue.add(new FileResource() {
+
+ @Override
+ public String getResourceId() {
+ return "testFile";
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return metadata;
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ return this.getClass().getResourceAsStream(path);
+ }
+ });
+ queue.add(new PoisonFileResource());
+
+ MockOSFactory mockOSFactory = new MockOSFactory();
+ RecursiveParserWrapperFSConsumer consumer = new
RecursiveParserWrapperFSConsumer(
+ queue, new AutoDetectParserFactory(), new
BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT, -1),
+ mockOSFactory, new TikaConfig());
+
+ IFileProcessorFutureResult result = consumer.call();
+ mockOSFactory.getStreams().get(0).flush();
+ byte[] bytes = mockOSFactory.getStreams().get(0).toByteArray();
+ List<Metadata> results = JsonMetadataList.fromJson(new
InputStreamReader(new ByteArrayInputStream(bytes), IOUtils.UTF_8));
+
+ assertEquals(4, results.size());
+ assertContains("another null pointer",
+ results.get(2).get(RecursiveParserWrapper.EMBEDDED_EXCEPTION));
+
+ assertEquals("Nikolai Lobachevsky", results.get(0).get("author"));
+ for (int i = 1; i < 4; i++) {
+ assertEquals("embeddedAuthor"+i, results.get(i).get("author"));
+ assertContains("some_embedded_content"+i,
results.get(i).get(RecursiveParserWrapper.TIKA_CONTENT));
+ }
+ }
+
+ @Test
+ public void testEmbeddedThenNPE() throws Exception {
+ final String path = "/test-documents/embedded_then_npe.xml";
+ final Metadata metadata = new Metadata();
+ metadata.add(Metadata.RESOURCE_NAME_KEY, "embedded_then_npe.xml");
+
+ ArrayBlockingQueue<FileResource> queue = new
ArrayBlockingQueue<FileResource>(2);
+ queue.add(new FileResource() {
+
+ @Override
+ public String getResourceId() {
+ return "testFile";
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return metadata;
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ return this.getClass().getResourceAsStream(path);
+ }
+ });
+ queue.add(new PoisonFileResource());
+
+ MockOSFactory mockOSFactory = new MockOSFactory();
+ RecursiveParserWrapperFSConsumer consumer = new
RecursiveParserWrapperFSConsumer(
+ queue, new AutoDetectParserFactory(), new
BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT, -1),
+ mockOSFactory, new TikaConfig());
+
+ IFileProcessorFutureResult result = consumer.call();
+ mockOSFactory.getStreams().get(0).flush();
+ byte[] bytes = mockOSFactory.getStreams().get(0).toByteArray();
+ List<Metadata> results = JsonMetadataList.fromJson(new
InputStreamReader(new ByteArrayInputStream(bytes), IOUtils.UTF_8));
+ assertEquals(2, results.size());
+ assertContains("another null pointer",
+
results.get(0).get(TikaCoreProperties.TIKA_META_EXCEPTION_PREFIX + "runtime"));
+ assertEquals("Nikolai Lobachevsky", results.get(0).get("author"));
+ assertEquals("embeddedAuthor", results.get(1).get("author"));
+ assertContains("some_embedded_content",
results.get(1).get(RecursiveParserWrapper.TIKA_CONTENT));
+ }
+
+
+
+ private class MockOSFactory implements OutputStreamFactory {
+ List<ByteArrayOutputStream> streams = new
ArrayList<ByteArrayOutputStream>();
+ @Override
+ public OutputStream getOutputStream(Metadata metadata) throws
IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ streams.add(bos);
+ return bos;
+ }
+ public List<ByteArrayOutputStream> getStreams() {
+ return streams;
+ }
+ }
+}
Added:
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_then_npe.xml
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-batch/src/test/resources/test-documents/embedded_then_npe.xml?rev=1683398&view=auto
==============================================================================
---
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_then_npe.xml
(added)
+++
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_then_npe.xml
Wed Jun 3 17:55:47 2015
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+ 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.
+-->
+
+<mock>
+
+ <metadata action="add" name="author">Nikolai Lobachevsky</metadata>
+ <write element="p">main_content</write>
+ <!-- auto detection wasn't working for some reason; add content-type as
+ is to trigger mock on the embedded -->
+ <embedded filename="embed1.xml" content-type="application/mock+xml">
+ <mock>
+ <metadata action="add"
name="author">embeddedAuthor</metadata>
+ <write element="p">some_embedded_content</write>
+ </mock>
+ </embedded>
+ <throw class="java.lang.NullPointerException">another null pointer
exception</throw>
+
+</mock>
\ No newline at end of file
Added:
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_with_npe.xml
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-batch/src/test/resources/test-documents/embedded_with_npe.xml?rev=1683398&view=auto
==============================================================================
---
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_with_npe.xml
(added)
+++
tika/trunk/tika-batch/src/test/resources/test-documents/embedded_with_npe.xml
Wed Jun 3 17:55:47 2015
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+ 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.
+-->
+
+<mock>
+
+ <metadata action="add" name="author">Nikolai Lobachevsky</metadata>
+ <write element="p">main_content</write>
+ <embedded filename="embed1.xml" content-type="application/mock+xml">
+ <mock>
+ <metadata action="add"
name="author">embeddedAuthor1</metadata>
+ <write element="p">some_embedded_content1</write>
+ </mock>
+ </embedded>
+
+ <embedded filename="embed2_npe.xml" content-type="application/mock+xml">
+ <mock>
+ <metadata action="add"
name="author">embeddedAuthor2</metadata>
+ <write element="p">some_embedded_content2_npe</write>
+ <throw
class="java.lang.NullPointerException">another null pointer
exception</throw>
+ </mock>
+ </embedded>
+ <embedded filename="embed3.xml" content-type="application/mock+xml">
+ <mock>
+ <metadata action="add"
name="author">embeddedAuthor3</metadata>
+ <write element="p">some_embedded_content3</write>
+ </mock>
+ </embedded>
+
+</mock>
\ No newline at end of file
Modified:
tika/trunk/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java?rev=1683398&r1=1683397&r2=1683398&view=diff
==============================================================================
---
tika/trunk/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java
(original)
+++
tika/trunk/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java
Wed Jun 3 17:55:47 2015
@@ -163,15 +163,16 @@ public class RecursiveParserWrapper impl
throw e;
}
metadata.set(WRITE_LIMIT_REACHED, "true");
+ } finally {
+ long elapsedMillis = new Date().getTime() - started;
+ metadata.set(PARSE_TIME_MILLIS, Long.toString(elapsedMillis));
+ addContent(localHandler, metadata);
+
+ if (hitMaxEmbeddedResources) {
+ metadata.set(EMBEDDED_RESOURCE_LIMIT_REACHED, "true");
+ }
+ metadatas.add(0, deepCopy(metadata));
}
- long elapsedMillis = new Date().getTime()-started;
- metadata.set(PARSE_TIME_MILLIS, Long.toString(elapsedMillis));
- addContent(localHandler, metadata);
-
- if (hitMaxEmbeddedResources) {
- metadata.set(EMBEDDED_RESOURCE_LIMIT_REACHED, "true");
- }
- metadatas.add(0, deepCopy(metadata));
}
/**
Modified:
tika/trunk/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java?rev=1683398&r1=1683397&r2=1683398&view=diff
==============================================================================
---
tika/trunk/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java
(original)
+++
tika/trunk/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java
Wed Jun 3 17:55:47 2015
@@ -21,6 +21,7 @@ package org.apache.tika.parser.mock;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
@@ -31,10 +32,16 @@ import java.util.List;
import java.util.Set;
import org.apache.tika.exception.TikaException;
+import org.apache.tika.extractor.EmbeddedDocumentExtractor;
+import org.apache.tika.extractor.ParsingEmbeddedDocumentExtractor;
+import org.apache.tika.io.IOUtils;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaMetadataKeys;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AbstractParser;
import org.apache.tika.parser.ParseContext;
+import org.apache.tika.parser.Parser;
+import org.apache.tika.sax.EmbeddedContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
@@ -87,12 +94,13 @@ public class MockParser extends Abstract
XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
xhtml.startDocument();
for (int i = 0; i < actions.getLength(); i++) {
- executeAction(actions.item(i), metadata, xhtml);
+ executeAction(actions.item(i), metadata, context, xhtml);
}
xhtml.endDocument();
}
- private void executeAction(Node action, Metadata metadata,
XHTMLContentHandler xhtml) throws SAXException,
+ private void executeAction(Node action, Metadata metadata, ParseContext
context,
+ XHTMLContentHandler xhtml) throws SAXException,
IOException, TikaException {
if (action.getNodeType() != 1) {
@@ -112,11 +120,59 @@ public class MockParser extends Abstract
kabOOM();
} else if ("print_out".equals(name) || "print_err".equals(name)){
print(action, name);
+ } else if ("embedded".equals(name)) {
+ handleEmbedded(action, xhtml, context);
} else {
throw new IllegalArgumentException("Didn't recognize mock action:
"+name);
}
}
+ private void handleEmbedded(Node action, XHTMLContentHandler handler,
ParseContext context)
+ throws TikaException, SAXException, IOException {
+ String fileName = "";
+ String contentType = "";
+ NamedNodeMap attrs = action.getAttributes();
+ if (attrs != null) {
+ Node n = attrs.getNamedItem("filename");
+ if (n != null) {
+ fileName = n.getNodeValue();
+ }
+ n = attrs.getNamedItem("content-type");
+ if (n != null) {
+ contentType = n.getNodeValue();
+ }
+ }
+
+ String embeddedText = action.getTextContent();
+ EmbeddedDocumentExtractor extractor =
getEmbeddedDocumentExtractor(context);
+ Metadata m = new Metadata();
+ m.set(TikaMetadataKeys.RESOURCE_NAME_KEY, fileName);
+ if (! "".equals(contentType)) {
+ m.set(Metadata.CONTENT_TYPE, contentType);
+ }
+ InputStream is = new
ByteArrayInputStream(embeddedText.getBytes(IOUtils.UTF_8));
+
+ extractor.parseEmbedded(
+ is,
+ new EmbeddedContentHandler(handler),
+ m, true);
+
+
+ }
+
+ protected EmbeddedDocumentExtractor
getEmbeddedDocumentExtractor(ParseContext context) {
+ EmbeddedDocumentExtractor extractor =
+ context.get(EmbeddedDocumentExtractor.class);
+ if (extractor == null) {
+ Parser p = context.get(Parser.class);
+ if (p == null) {
+ context.set(Parser.class, new MockParser());
+ }
+ extractor = new ParsingEmbeddedDocumentExtractor(context);
+ }
+ return extractor;
+ }
+
private void print(Node action, String name) {
String content = action.getTextContent();
if ("print_out".equals(name)) {
@@ -224,6 +280,7 @@ public class MockParser extends Abstract
try {
Class<?> clazz = Class.forName(className);
Constructor<?> con = clazz.getConstructor(String.class);
+ System.err.println("CON: " + con + " :: " + msg+"<<");
t = (Throwable) con.newInstance(msg);
} catch (Exception e) {
throw new RuntimeException("couldn't create throwable class:"
+ className, e);
@@ -298,4 +355,5 @@ public class MockParser extends Abstract
}
}
}
-}
\ No newline at end of file
+
+}
Modified:
tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java?rev=1683398&r1=1683397&r2=1683398&view=diff
==============================================================================
---
tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java
(original)
+++
tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java
Wed Jun 3 17:55:47 2015
@@ -28,8 +28,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.apache.tika.exception.TikaException;
import org.apache.tika.io.IOUtils;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaMetadataKeys;
import org.apache.tika.sax.BasicContentHandlerFactory;
import org.apache.tika.sax.ContentHandlerFactory;
import org.junit.Test;
@@ -215,6 +217,49 @@ public class RecursiveParserWrapperTest
assertEquals(12, list.size());
}
+ @Test
+ public void testPrimaryExcWEmbedded() throws Exception {
+ //if embedded content is handled and then
+ //the parser hits an exception in the container document,
+ //that the first element of the returned list is the container document
+ //and the second is the embedded content
+ Metadata metadata = new Metadata();
+ metadata.set(Metadata.RESOURCE_NAME_KEY, "embedded_then_npe.xml");
+
+ ParseContext context = new ParseContext();
+ Parser wrapped = new AutoDetectParser();
+ RecursiveParserWrapper wrapper = new RecursiveParserWrapper(wrapped,
+ new
BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT, -1),
true);
+ String path = "/test-documents/mock/embedded_then_npe.xml";
+
+ InputStream stream = null;
+ boolean npe = false;
+ try {
+ stream = RecursiveParserWrapperTest.class.getResourceAsStream(
+ path);
+ wrapper.parse(stream, new DefaultHandler(), metadata, context);
+ } catch (TikaException e) {
+ if (e.getCause().getClass().equals(NullPointerException.class)) {
+ npe = true;
+ }
+ } finally {
+ IOUtils.closeQuietly(stream);
+ }
+ assertTrue("npe", npe);
+
+ List<Metadata> metadataList = wrapper.getMetadata();
+ assertEquals(2, metadataList.size());
+ Metadata outerMetadata = metadataList.get(0);
+ Metadata embeddedMetadata = metadataList.get(1);
+ assertContains("main_content",
outerMetadata.get(RecursiveParserWrapper.TIKA_CONTENT));
+ assertEquals("embedded_then_npe.xml",
outerMetadata.get(TikaMetadataKeys.RESOURCE_NAME_KEY));
+ assertEquals("Nikolai Lobachevsky", outerMetadata.get("author"));
+
+ assertContains("some_embedded_content",
embeddedMetadata.get(RecursiveParserWrapper.TIKA_CONTENT));
+ assertEquals("embed1.xml",
embeddedMetadata.get(TikaMetadataKeys.RESOURCE_NAME_KEY));
+ assertEquals("embeddedAuthor", embeddedMetadata.get("author"));
+ }
+
private List<Metadata> getMetadata(Metadata metadata,
ContentHandlerFactory contentHandlerFactory,
boolean catchEmbeddedExceptions) throws
Exception {
ParseContext context = new ParseContext();
Added:
tika/trunk/tika-parsers/src/test/resources/test-documents/mock/embedded_then_npe.xml
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/mock/embedded_then_npe.xml?rev=1683398&view=auto
==============================================================================
---
tika/trunk/tika-parsers/src/test/resources/test-documents/mock/embedded_then_npe.xml
(added)
+++
tika/trunk/tika-parsers/src/test/resources/test-documents/mock/embedded_then_npe.xml
Wed Jun 3 17:55:47 2015
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+ 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.
+-->
+
+<mock>
+
+ <metadata action="add" name="author">Nikolai Lobachevsky</metadata>
+ <write element="p">main_content</write>
+ <!-- auto detection wasn't working for some reason; add content-type as
+ is to trigger mock on the embedded -->
+ <embedded filename="embed1.xml" content-type="application/mock+xml">
+ <mock>
+ <metadata action="add"
name="author">embeddedAuthor</metadata>
+ <write element="p">some_embedded_content</write>
+ </mock>
+ </embedded>
+ <throw class="java.lang.NullPointerException">another null pointer
exception</throw>
+
+</mock>
\ No newline at end of file