diff --git a/exist-core/src/main/java/org/exist/xmldb/RemoteCollection.java b/exist-core/src/main/java/org/exist/xmldb/RemoteCollection.java index ba0f47cf9c3..f2a871297f6 100644 --- a/exist-core/src/main/java/org/exist/xmldb/RemoteCollection.java +++ b/exist-core/src/main/java/org/exist/xmldb/RemoteCollection.java @@ -519,6 +519,7 @@ private void store(final RemoteXMLResource res) throws XMLDBException { } catch (final URISyntaxException e) { throw new XMLDBException(ErrorCodes.INVALID_URI, e); } + params.add(res.getMimeType()); params.add(1); if (res.getCreationTime() != null) { params.add(res.getCreationTime()); diff --git a/exist-core/src/main/java/org/exist/xmlrpc/RpcAPI.java b/exist-core/src/main/java/org/exist/xmlrpc/RpcAPI.java index c486274f3f0..c6fe9fd6444 100644 --- a/exist-core/src/main/java/org/exist/xmlrpc/RpcAPI.java +++ b/exist-core/src/main/java/org/exist/xmlrpc/RpcAPI.java @@ -545,18 +545,27 @@ boolean parse(byte[] xmlData, String docName) * * @param xmlData The document data * @param docName The path where the document will be stored + * @param mimeType the mimeType to check for * @param overwrite Overwrite an existing document with the same path? + * @param created Specifies the creattion date + * @param modified Specifies the last modification date * @return true, if the document is valid XML * @throws EXistException If an internal error occurs * @throws PermissionDeniedException If the current user is not allowed to perform this action * @throws URISyntaxException If the URI contains syntax errors */ - boolean parse(byte[] xmlData, String docName, int overwrite) + boolean parse(byte[] xmlData, String docName, String mimeType, int overwrite, Date created, Date modified) throws EXistException, PermissionDeniedException, URISyntaxException; boolean parse(byte[] xmlData, String docName, int overwrite, Date created, Date modified) throws EXistException, PermissionDeniedException, URISyntaxException; + boolean parse(byte[] xmlData, String docName, String mimeType, int overwrite) + throws EXistException, PermissionDeniedException, URISyntaxException; + + boolean parse(byte[] xmlData, String docName, int overwrite) + throws EXistException, PermissionDeniedException, URISyntaxException; + boolean parse(String xml, String docName, int overwrite) throws EXistException, PermissionDeniedException, URISyntaxException; diff --git a/exist-core/src/main/java/org/exist/xmlrpc/RpcConnection.java b/exist-core/src/main/java/org/exist/xmlrpc/RpcConnection.java index 6e3b5b45c9a..e12993f1da3 100644 --- a/exist-core/src/main/java/org/exist/xmlrpc/RpcConnection.java +++ b/exist-core/src/main/java/org/exist/xmlrpc/RpcConnection.java @@ -1336,18 +1336,24 @@ private boolean hasCollection(final XmldbURI collUri) throws EXistException, Per @Override public boolean parse(byte[] xml, String documentPath, int overwrite) throws URISyntaxException, EXistException, PermissionDeniedException { - return parse(xml, documentPath, overwrite, null, null); + return parse(xml, documentPath, null, overwrite, null, null); + } + + @Override + public boolean parse(final byte[] xml, final String documentPath, final String mimeType, final int overwrite) throws URISyntaxException, EXistException, PermissionDeniedException { + return parse(xml, documentPath, mimeType, overwrite, null, null); } @Override public boolean parse(final byte[] xml, final String documentPath, final int overwrite, final Date created, final Date modified) throws URISyntaxException, EXistException, PermissionDeniedException { - return parse(xml, XmldbURI.xmldbUriFor(documentPath), overwrite, created, modified); + return parse(xml, documentPath, null, overwrite, created, modified); } - private boolean parse(final byte[] xml, final XmldbURI docUri, - final int overwrite, @Nullable final Date created, @Nullable final Date modified) throws EXistException, PermissionDeniedException { - + @Override + public boolean parse(final byte[] xml, final String documentPath, @Nullable String mimeType, + final int overwrite, @Nullable final Date created, @Nullable final Date modified) throws URISyntaxException, EXistException, PermissionDeniedException { + final XmldbURI docUri = XmldbURI.xmldbUriFor(documentPath); return this.writeCollection(docUri.removeLastSegment()).apply((collection, broker, transaction) -> { try(final ManagedDocumentLock lockedDocument = broker.getBrokerPool().getLockManager().acquireDocumentWriteLock(docUri)) { @@ -1366,7 +1372,7 @@ private boolean parse(final byte[] xml, final XmldbURI docUri, final long startTime = System.currentTimeMillis(); - final MimeType mime = MimeTable.getInstance().getContentTypeFor(docUri.lastSegment()); + final MimeType mime = lookupMimeType(mimeType, docUri.lastSegment()); broker.storeDocument(transaction, docUri.lastSegment(), source, mime, created, modified, null, null, null, collection); // NOTE: early release of Collection lock inline with Asymmetrical Locking scheme @@ -1379,6 +1385,14 @@ private boolean parse(final byte[] xml, final XmldbURI docUri, }); } + private MimeType lookupMimeType(@Nullable final String mimeType, final XmldbURI fileName) { + final MimeTable mimeTable = MimeTable.getInstance(); + if (mimeType == null) { + return Optional.ofNullable(mimeTable.getContentTypeFor(fileName)).orElse(MimeType.BINARY_TYPE); + } + return Optional.ofNullable(mimeTable.getContentType(mimeType)).orElse(MimeType.BINARY_TYPE); + } + /** * Parse a file previously uploaded with upload. * @@ -1492,7 +1506,7 @@ private boolean parseLocal(final String localFile, final XmldbURI docUri, final // parse the source try (final FileInputSource source = sourceSupplier.get()) { - final MimeType mime = Optional.ofNullable(MimeTable.getInstance().getContentType(mimeType)).orElse(MimeType.BINARY_TYPE); + final MimeType mime = lookupMimeType(mimeType, docUri.lastSegment()); broker.storeDocument(transaction, docUri.lastSegment(), source, mime, created, modified, null, null, null, collection); diff --git a/exist-core/src/test/java/org/exist/xmlrpc/MimeTypeTest.java b/exist-core/src/test/java/org/exist/xmlrpc/MimeTypeTest.java new file mode 100644 index 00000000000..53379338168 --- /dev/null +++ b/exist-core/src/test/java/org/exist/xmlrpc/MimeTypeTest.java @@ -0,0 +1,101 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xmlrpc; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.junit.Assert.assertEquals; + +import org.exist.TestUtils; +import org.exist.test.ExistWebServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.xml.sax.SAXException; +import org.xmldb.api.DatabaseManager; +import org.xmldb.api.base.Collection; +import org.xmldb.api.base.Database; +import org.xmldb.api.base.Resource; +import org.xmldb.api.base.ResourceType; +import org.xmldb.api.base.XMLDBException; +import org.xmldb.api.modules.CollectionManagementService; +import org.xmldb.api.modules.XMLResource; + +public class MimeTypeTest { + + @ClassRule + public final static ExistWebServer existWebServer = new ExistWebServer(true, false, true, true); + + private final static String COLLECTION_NAME = "rpctest"; + private static final String DOCUMENT_NAME = "myxmldoc"; + private final static String XML_CONTENT = """ + + + """; + + private static String getBaseUri() { + return "xmldb:exist://localhost:" + existWebServer.getPort() + "/xmlrpc"; + } + + @Test + public void testXMLMimeType() throws XMLDBException { + // store an XML document without an .xml extension + try(Collection collection = DatabaseManager.getCollection(getBaseUri() + "/db/" + COLLECTION_NAME, TestUtils.ADMIN_DB_USER, TestUtils.ADMIN_DB_PWD)){ + final Class xmlResourceType = XMLResource.class; + final XMLResource resource = (XMLResource)collection.createResource(DOCUMENT_NAME, xmlResourceType); + resource.setContent(XML_CONTENT); + collection.storeResource(resource); + assertEquals(ResourceType.XML_RESOURCE, resource.getResourceType()); + } + + // retrieve the document and verify its resource type + try(Collection collection = DatabaseManager.getCollection(getBaseUri() + "/db/" + COLLECTION_NAME, TestUtils.ADMIN_DB_USER, TestUtils.ADMIN_DB_PWD)){ + Resource resource = collection.getResource(DOCUMENT_NAME); + assertEquals(ResourceType.XML_RESOURCE, resource.getResourceType()); + } + } + + @BeforeClass + public static void startServer() throws ClassNotFoundException, IllegalAccessException, InstantiationException, XMLDBException, SAXException { + // initialize XML:DB driver + Class cl = Class.forName("org.exist.xmldb.DatabaseImpl"); + Database database = (Database) cl.newInstance(); + DatabaseManager.registerDatabase(database); + + Collection root = DatabaseManager.getCollection(getBaseUri() + "/db", TestUtils.ADMIN_DB_USER, TestUtils.ADMIN_DB_PWD); + + CollectionManagementService mgmt = root.getService(CollectionManagementService.class); + assertThatNoException().isThrownBy(() -> mgmt.createCollection(COLLECTION_NAME)); + } + + @AfterClass + public static void stopServer() throws XMLDBException { + Collection root = DatabaseManager.getCollection(getBaseUri() + "/db", TestUtils.ADMIN_DB_USER, TestUtils.ADMIN_DB_PWD); + CollectionManagementService mgmt = + root.getService(CollectionManagementService.class); + mgmt.removeCollection(COLLECTION_NAME); + + Collection config = DatabaseManager.getCollection(getBaseUri() + "/db/system/config/db", "admin", ""); + mgmt = config.getService(CollectionManagementService.class); + mgmt.removeCollection(COLLECTION_NAME); + } +}