You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by sk...@apache.org on 2018/02/06 13:26:43 UTC
syncope git commit: [SYNCOPE-1267] New binary Schema validator to
check MIME types
Repository: syncope
Updated Branches:
refs/heads/2_0_X b8993d236 -> 8ebb5013b
[SYNCOPE-1267] New binary Schema validator to check MIME types
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/8ebb5013
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/8ebb5013
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/8ebb5013
Branch: refs/heads/2_0_X
Commit: 8ebb5013bd644a733a505b42d7b217faa9193150
Parents: b8993d2
Author: skylark17 <ma...@tirasa.net>
Authored: Tue Feb 6 14:22:41 2018 +0100
Committer: skylark17 <ma...@tirasa.net>
Committed: Tue Feb 6 14:25:23 2018 +0100
----------------------------------------------------------------------
.../console/panels/PlainSchemaDetails.java | 17 +++-
core/persistence-jpa/pom.xml | 5 +
.../attrvalue/validation/BinaryValidator.java | 84 ++++++++++++++++
.../java/data/AbstractAnyDataBinder.java | 7 +-
.../core/reference/ITImplementationLookup.java | 2 +
.../syncope/fit/core/PlainSchemaITCase.java | 95 +++++++++++++++++++
fit/core-reference/src/test/resources/test.html | 30 ++++++
fit/core-reference/src/test/resources/test.json | 3 +
fit/core-reference/src/test/resources/test.pdf | Bin 0 -> 8603 bytes
fit/core-reference/src/test/resources/test.xml | 24 +++++
pom.xml | 8 ++
11 files changed, 272 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
index 4cd80b7..686b1bd 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
@@ -62,6 +62,8 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
private final MultiFieldPanel<String> enumerationKeys;
+ private final AjaxDropDownChoicePanel<String> validatorClass;
+
public PlainSchemaDetails(
final String id,
final PageReference pageReference,
@@ -228,6 +230,7 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
binaryParams, mimeType);
target.add(conversionParams);
target.add(typeParams);
+ target.add(validatorClass);
}
}
);
@@ -241,8 +244,9 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
return new ArrayList<>(SyncopeConsoleSession.get().getPlatformInfo().getValidators());
}
};
- final AjaxDropDownChoicePanel<String> validatorClass = new AjaxDropDownChoicePanel<>("validatorClass",
+ validatorClass = new AjaxDropDownChoicePanel<>("validatorClass",
getString("validatorClass"), new PropertyModel<String>(schemaTO, "validatorClass"));
+ validatorClass.setOutputMarkupId(true);
((DropDownChoice) validatorClass.getField()).setNullValid(true);
validatorClass.setChoices(validatorsList.getObject());
schemaForm.add(validatorClass);
@@ -324,6 +328,8 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
binaryParams.setVisible(false);
mimeType.setModelObject(null);
mimeType.setChoices(null);
+
+ PlainSchemaTO.class.cast(schema).setValidatorClass(null);
} else if (AttrSchemaType.Enum.ordinal() == typeOrdinal) {
conversionParams.setVisible(false);
conversionPattern.setModelObject(null);
@@ -350,6 +356,8 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
binaryParams.setVisible(false);
mimeType.setModelObject(null);
mimeType.setChoices(null);
+
+ PlainSchemaTO.class.cast(schema).setValidatorClass(null);
} else if (AttrSchemaType.Encrypted.ordinal() == typeOrdinal) {
conversionParams.setVisible(false);
conversionPattern.setModelObject(null);
@@ -372,6 +380,8 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
binaryParams.setVisible(false);
mimeType.setModelObject(null);
mimeType.setChoices(null);
+
+ PlainSchemaTO.class.cast(schema).setValidatorClass(null);
} else if (AttrSchemaType.Binary.ordinal() == typeOrdinal) {
conversionParams.setVisible(false);
conversionPattern.setModelObject(null);
@@ -395,6 +405,9 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
binaryParams.setVisible(true);
mimeType.setChoices(MIME_TYPES_LOADER.getMimeTypes());
+
+ PlainSchemaTO.class.cast(schema).
+ setValidatorClass("org.apache.syncope.core.persistence.jpa.attrvalue.validation.BinaryValidator");
} else {
conversionParams.setVisible(false);
conversionPattern.setModelObject(null);
@@ -419,6 +432,8 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
binaryParams.setVisible(false);
mimeType.setModelObject(null);
mimeType.setChoices(null);
+
+ PlainSchemaTO.class.cast(schema).setValidatorClass(null);
}
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/core/persistence-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/pom.xml b/core/persistence-jpa/pom.xml
index 8fe5e49..b197eb2 100644
--- a/core/persistence-jpa/pom.xml
+++ b/core/persistence-jpa/pom.xml
@@ -107,6 +107,11 @@ under the License.
<artifactId>syncope-core-spring</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-core</artifactId>
+ </dependency>
<!-- TEST -->
<dependency>
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java
new file mode 100644
index 0000000..cd0510c
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java
@@ -0,0 +1,84 @@
+/*
+ * 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.syncope.core.persistence.jpa.attrvalue.validation;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.tika.Tika;
+
+public class BinaryValidator extends AbstractValidator {
+
+ private static final long serialVersionUID = 1344152444666540361L;
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ public BinaryValidator(final PlainSchema schema) {
+ super(schema);
+ }
+
+ @Override
+ protected void doValidate(final PlainAttrValue attrValue) {
+ // check Binary schemas MIME Type mismatches
+ if (attrValue.getBinaryValue() != null) {
+ PlainSchema currentSchema = attrValue.getAttr().getSchema();
+ byte[] binaryValue = attrValue.getBinaryValue();
+ String mimeType = detectSchemaMimeType(binaryValue);
+ boolean valid = true;
+ if (!mimeType.equals(currentSchema.getMimeType())) {
+ if (mimeType.equals("text/plain")
+ && currentSchema.getMimeType().equals("application/json")) {
+ String decoded = new String(binaryValue).trim();
+ valid = (decoded.startsWith("{") && decoded.endsWith("}"))
+ || (decoded.startsWith("[") && decoded.endsWith("]"))
+ && isValidJSON(decoded);
+ } else {
+ valid = false;
+ }
+ }
+ if (!valid) {
+ throw new InvalidPlainAttrValueException(
+ "Found MIME type: '"
+ + mimeType
+ + "', expecting: '"
+ + currentSchema.getMimeType()
+ + "'");
+ }
+ }
+ }
+
+ private String detectSchemaMimeType(final byte[] value) {
+ Tika tika = new Tika();
+ tika.setMaxStringLength(-1);
+ return tika.detect(value);
+ }
+
+ private boolean isValidJSON(final String value) {
+ try {
+ final JsonParser parser = MAPPER.getFactory().createParser(value);
+ while (parser.nextToken() != null) {
+ }
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index 8e2b83c..9740c53 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -190,9 +190,12 @@ abstract class AbstractAnyDataBinder {
try {
attr.add(value, anyUtils);
} catch (InvalidPlainAttrValueException e) {
- LOG.warn("Invalid value for attribute " + schema.getKey() + ": " + value, e);
+ String valueToPrint = value.length() > 40
+ ? value.substring(0, 20) + "..."
+ : value;
+ LOG.warn("Invalid value for attribute " + schema.getKey() + ": " + valueToPrint, e);
- invalidValues.getElements().add(schema.getKey() + ": " + value + " - " + e.getMessage());
+ invalidValues.getElements().add(schema.getKey() + ": " + valueToPrint + " - " + e.getMessage());
}
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
index 4209734..6f552da 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
@@ -49,6 +49,7 @@ import org.apache.syncope.core.persistence.api.dao.PasswordRule;
import org.apache.syncope.core.persistence.api.dao.Reportlet;
import org.apache.syncope.core.persistence.jpa.attrvalue.validation.AlwaysTrueValidator;
import org.apache.syncope.core.persistence.jpa.attrvalue.validation.BasicValidator;
+import org.apache.syncope.core.persistence.jpa.attrvalue.validation.BinaryValidator;
import org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator;
import org.apache.syncope.core.persistence.jpa.dao.DefaultAccountRule;
import org.apache.syncope.core.persistence.jpa.dao.DefaultPasswordRule;
@@ -141,6 +142,7 @@ public class ITImplementationLookup implements ImplementationLookup {
classNames.add(BasicValidator.class.getName());
classNames.add(EmailAddressValidator.class.getName());
classNames.add(AlwaysTrueValidator.class.getName());
+ classNames.add(BinaryValidator.class.getName());
put(Type.VALIDATOR, classNames);
classNames = new HashSet<>();
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
index 8841851..e36c8e5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
@@ -25,13 +25,18 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.IOException;
import java.util.List;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.SerializationUtils;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.helpers.IOUtils;
import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.patch.AttrPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
import org.apache.syncope.common.lib.to.AnyTypeClassTO;
import org.apache.syncope.common.lib.to.MembershipTO;
import org.apache.syncope.common.lib.to.PlainSchemaTO;
@@ -41,6 +46,7 @@ import org.apache.syncope.common.lib.types.AttrSchemaType;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.rest.api.beans.SchemaQuery;
import org.apache.syncope.fit.AbstractITCase;
@@ -144,6 +150,95 @@ public class PlainSchemaITCase extends AbstractITCase {
}
@Test
+ public void testBinaryValidation() throws IOException {
+ // pdf - with validator
+ PlainSchemaTO schemaTOpdf = new PlainSchemaTO();
+ schemaTOpdf.setKey("BinaryPDF");
+ schemaTOpdf.setType(AttrSchemaType.Binary);
+ schemaTOpdf.setMimeType("application/pdf");
+ schemaTOpdf.setValidatorClass("org.apache.syncope.core.persistence.jpa.attrvalue.validation.BinaryValidator");
+ schemaTOpdf.setAnyTypeClass("minimal user");
+
+ createSchema(SchemaType.PLAIN, schemaTOpdf);
+
+ // json - with validator
+ PlainSchemaTO schemaTOjson = new PlainSchemaTO();
+ schemaTOjson.setKey("BinaryJSON");
+ schemaTOjson.setType(AttrSchemaType.Binary);
+ schemaTOjson.setMimeType("application/json");
+ schemaTOjson.setValidatorClass("org.apache.syncope.core.persistence.jpa.attrvalue.validation.BinaryValidator");
+ schemaTOjson.setAnyTypeClass("minimal user");
+
+ createSchema(SchemaType.PLAIN, schemaTOjson);
+
+ // json - no validator
+ PlainSchemaTO schemaTOjson2 = new PlainSchemaTO();
+ schemaTOjson2.setKey("BinaryJSON2");
+ schemaTOjson2.setType(AttrSchemaType.Binary);
+ schemaTOjson2.setMimeType("application/json");
+ schemaTOjson2.setAnyTypeClass("minimal user");
+
+ createSchema(SchemaType.PLAIN, schemaTOjson2);
+
+ UserTO userTO = UserITCase.getUniqueSampleTO("test@syncope.apache.org");
+
+ userTO = createUser(userTO).getEntity();
+ assertNotNull(userTO);
+
+ UserPatch userPatch = new UserPatch();
+ userPatch.setKey(userTO.getKey());
+ // validation OK - application/pdf -> application/pdf
+ userPatch.getPlainAttrs().add(new AttrPatch.Builder().operation(PatchOperation.ADD_REPLACE).
+ attrTO(attrTO("BinaryPDF",
+ Base64Utility.encode(
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.pdf"))))).
+ build());
+
+ updateUser(userPatch);
+ assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryPDF"));
+
+ userPatch = new UserPatch();
+ userPatch.setKey(userTO.getKey());
+ // validation KO - text/html -> application/pdf
+ try {
+ userPatch.getPlainAttrs().add(new AttrPatch.Builder().operation(PatchOperation.ADD_REPLACE).
+ attrTO(attrTO("BinaryPDF",
+ Base64Utility.encode(
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.html"))))).
+ build());
+
+ updateUser(userPatch);
+ fail("This should not be reacheable");
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.InvalidValues, e.getType());
+ }
+
+ userPatch = new UserPatch();
+ userPatch.setKey(userTO.getKey());
+ // validation ok - application/json -> application/json
+ userPatch.getPlainAttrs().add(new AttrPatch.Builder().operation(PatchOperation.ADD_REPLACE).
+ attrTO(attrTO("BinaryJSON",
+ Base64Utility.encode(
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.json"))))).
+ build());
+
+ updateUser(userPatch);
+ assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryJSON"));
+
+ userPatch = new UserPatch();
+ userPatch.setKey(userTO.getKey());
+ // no validation - application/xml -> application/json
+ userPatch.getPlainAttrs().add(new AttrPatch.Builder().operation(PatchOperation.ADD_REPLACE).
+ attrTO(attrTO("BinaryJSON2",
+ Base64Utility.encode(
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.xml"))))).
+ build());
+
+ updateUser(userPatch);
+ assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryJSON2"));
+ }
+
+ @Test
public void delete() {
PlainSchemaTO schemaTO = buildPlainSchemaTO("todelete", AttrSchemaType.String);
schemaTO.setMandatoryCondition("false");
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/fit/core-reference/src/test/resources/test.html
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/test.html b/fit/core-reference/src/test/resources/test.html
new file mode 100644
index 0000000..d55d628
--- /dev/null
+++ b/fit/core-reference/src/test/resources/test.html
@@ -0,0 +1,30 @@
+<!--
+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.
+-->
+<!doctype html>
+
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="description" content="">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+ <p> Syncope is Magic </p>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/fit/core-reference/src/test/resources/test.json
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/test.json b/fit/core-reference/src/test/resources/test.json
new file mode 100644
index 0000000..fd88c8d
--- /dev/null
+++ b/fit/core-reference/src/test/resources/test.json
@@ -0,0 +1,3 @@
+{
+ "message": "Syncope is Magic"
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/fit/core-reference/src/test/resources/test.pdf
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/test.pdf b/fit/core-reference/src/test/resources/test.pdf
new file mode 100644
index 0000000..bed69a7
Binary files /dev/null and b/fit/core-reference/src/test/resources/test.pdf differ
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/fit/core-reference/src/test/resources/test.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/test.xml b/fit/core-reference/src/test/resources/test.xml
new file mode 100644
index 0000000..66cad36
--- /dev/null
+++ b/fit/core-reference/src/test/resources/test.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<Tests xmlns="http://www.test.com">
+ <Test>
+ <Name>Syncope is Magic</Name>
+ </Test>
+</Tests>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/8ebb5013/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 339dcc2..7af96f0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -405,6 +405,8 @@ under the License.
<commons-text.version>1.2</commons-text.version>
<commons-collection.version>4.1</commons-collection.version>
<commons-logging.version>1.1.3</commons-logging.version>
+
+ <tika.version>1.17</tika.version>
<joda.version>2.9.9</joda.version>
@@ -1578,6 +1580,12 @@ under the License.
<artifactId>httpmime</artifactId>
<version>${httpclient.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-core</artifactId>
+ <version>${tika.version}</version>
+ </dependency>
<dependency>
<groupId>org.netbeans.api</groupId>