1919import static java .nio .charset .StandardCharsets .UTF_8 ;
2020import static org .junit .jupiter .api .Assertions .assertEquals ;
2121import static org .junit .jupiter .api .Assertions .assertNotNull ;
22+ import static org .junit .jupiter .api .Assertions .assertNull ;
2223
2324import java .io .InputStream ;
2425import java .io .InputStreamReader ;
4647import org .apache .tika .metadata .Metadata ;
4748import org .apache .tika .metadata .TikaCoreProperties ;
4849import org .apache .tika .serialization .JsonMetadata ;
50+ import org .apache .tika .serialization .JsonMetadataList ;
4951import org .apache .tika .server .core .CXFTestBase ;
5052import org .apache .tika .server .core .TikaServerParseExceptionMapper ;
5153import org .apache .tika .server .core .resource .MetadataResource ;
54+ import org .apache .tika .server .core .resource .RecursiveMetadataResource ;
5255import org .apache .tika .server .core .writer .CSVMessageBodyWriter ;
5356import org .apache .tika .server .core .writer .JSONMessageBodyWriter ;
57+ import org .apache .tika .server .core .writer .MetadataListMessageBodyWriter ;
5458import org .apache .tika .server .core .writer .TextMessageBodyWriter ;
5559import org .apache .tika .server .standard .resource .XMPMetadataResource ;
5660import org .apache .tika .server .standard .writer .XMPMessageBodyWriter ;
5761
5862public class MetadataResourceTest extends CXFTestBase {
5963
6064 private static final String META_PATH = "/meta" ;
65+ private static final String TEST_RECURSIVE_DOC = "test-documents/test_recursive_embedded.docx" ;
6166
6267 @ Override
6368 protected boolean isAllowPerRequestConfig () {
@@ -66,9 +71,12 @@ protected boolean isAllowPerRequestConfig() {
6671
6772 @ Override
6873 protected void setUpResources (JAXRSServerFactoryBean sf ) {
69- sf .setResourceClasses (MetadataResource .class , XMPMetadataResource .class );
74+ sf .setResourceClasses (MetadataResource .class , XMPMetadataResource .class ,
75+ RecursiveMetadataResource .class );
7076 sf .setResourceProvider (MetadataResource .class , new SingletonResourceProvider (new MetadataResource (tikaResource )));
7177 sf .setResourceProvider (XMPMetadataResource .class , new SingletonResourceProvider (new XMPMetadataResource (tikaResource )));
78+ sf .setResourceProvider (RecursiveMetadataResource .class ,
79+ new SingletonResourceProvider (new RecursiveMetadataResource (tikaResource )));
7280 }
7381
7482 @ Override
@@ -78,6 +86,7 @@ protected void setUpProviders(JAXRSServerFactoryBean sf) {
7886 providers .add (new TikaServerParseExceptionMapper (false ));
7987 providers .add (new JSONMessageBodyWriter ());
8088 providers .add (new CSVMessageBodyWriter ());
89+ providers .add (new MetadataListMessageBodyWriter ());
8190 providers .add (new XMPMessageBodyWriter ());
8291 providers .add (new TextMessageBodyWriter ());
8392 sf .setProviders (providers );
@@ -282,4 +291,43 @@ public void testGetField_Author_XMP_Partial_Found() throws Exception {
282291 }
283292
284293
294+ /**
295+ * /meta and /rmeta[0] describe the same container document, so their metadata must
296+ * agree. /meta reaches it by a different route (embedded parsing suppressed, content
297+ * capture off), and every /meta defect this release -- a dropped field, a spurious
298+ * exception flag, a Content-Type taken from the multipart envelope -- was a silent
299+ * divergence between the two that no test compared.
300+ */
301+ @ Test
302+ public void testMetaAgreesWithRmeta () throws Exception {
303+ Metadata meta = JsonMetadata .fromJson (new InputStreamReader (
304+ (InputStream ) WebClient .create (endPoint + META_PATH ).accept ("application/json" )
305+ .put (ClassLoader .getSystemResourceAsStream (TEST_RECURSIVE_DOC ))
306+ .getEntity (), UTF_8 ));
307+
308+ List <Metadata > rmeta = JsonMetadataList .fromJson (new InputStreamReader (
309+ (InputStream ) WebClient .create (endPoint + "/rmeta/ignore" ).accept ("application/json" )
310+ .put (ClassLoader .getSystemResourceAsStream (TEST_RECURSIVE_DOC ))
311+ .getEntity (), UTF_8 ));
312+ Metadata container = rmeta .get (0 );
313+
314+ for (String name : container .names ()) {
315+ // tk:content is absent from both (ignore handler); embedded-only bookkeeping
316+ // legitimately differs because /meta stops at the container.
317+ // tk:content is absent from both (ignore handler). tk:resource-name and
318+ // tk:source-path currently carry the server's per-request spool filename, so
319+ // they differ by construction until that is fixed.
320+ if (name .startsWith ("X-TIKA:EXCEPTION" ) || name .equals ("tk:content" )
321+ || name .startsWith ("tk:parsed-by-full-set" )
322+ || name .equals ("tk:resource-name" ) || name .equals ("tk:source-path" )
323+ || name .equals ("tk:parse-time-millis" )) {
324+ continue ;
325+ }
326+ assertEquals (container .get (name ), meta .get (name ),
327+ "/meta and /rmeta[0] disagree on '" + name + "'" );
328+ }
329+ assertNull (meta .get ("tk:exception:embedded-depth-limit-reached" ),
330+ "/meta suppresses embedded docs; that is not a limit the caller hit" );
331+ }
332+
285333}
0 commit comments