This is an automated email from the ASF dual-hosted git repository.
tallison pushed a commit to branch branch_1x
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/branch_1x by this push:
new 82f7a34 [TIKA-3357] removes ambiguity by choosing handler based on
produce type (#427)
82f7a34 is described below
commit 82f7a34b692706ba3eb55b64453cca29203db3e8
Author: Subhajit Das <[email protected]>
AuthorDate: Mon Apr 19 19:07:56 2021 +0530
[TIKA-3357] removes ambiguity by choosing handler based on produce type
(#427)
* TIKA-3357 removes ambiguity by choosing handler based on produce type
* Removed default compare, as it wil be done by cxf
* Changed priorities
---
.../tika/server/ProduceTypeResourceComparator.java | 145 +++++++++++++++++++++
.../java/org/apache/tika/server/TikaServerCli.java | 1 +
.../java/org/apache/tika/server/CXFTestBase.java | 2 +-
3 files changed, 147 insertions(+), 1 deletion(-)
diff --git
a/tika-server/src/main/java/org/apache/tika/server/ProduceTypeResourceComparator.java
b/tika-server/src/main/java/org/apache/tika/server/ProduceTypeResourceComparator.java
new file mode 100644
index 0000000..495ecf5
--- /dev/null
+++
b/tika-server/src/main/java/org/apache/tika/server/ProduceTypeResourceComparator.java
@@ -0,0 +1,145 @@
+/*
+ * 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.server;
+
+import org.apache.cxf.jaxrs.ext.ResourceComparator;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.message.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MediaType;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Resource comparator based to produce type.
+ * In an ambiguous call, request handler will be chosen based on the type of
data it returns.
+ */
+public class ProduceTypeResourceComparator implements ResourceComparator {
+
+ /**
+ * The logger
+ */
+ private static final Logger LOG =
LoggerFactory.getLogger(ProduceTypeResourceComparator.class);
+
+ /**
+ * The prioritized MediaType list.
+ * The lower in list (higher index value), the higher priority it has.
+ * In case of no matching in this list, it will be treated as media type
all.
+ */
+ public static final List<MediaType> PRIORITIZED_MEDIA_LIST =
+ Arrays.asList(
+ MediaType.TEXT_PLAIN_TYPE,
+ MediaType.APPLICATION_JSON_TYPE,
+ MediaType.TEXT_HTML_TYPE,
+ MediaType.TEXT_XML_TYPE
+ );
+
+ /**
+ * Initiates the comparator.
+ * Currently, no op.
+ */
+ public ProduceTypeResourceComparator() {
+ }
+
+ /**
+ * Compares the class to handle.
+ * Nothing is handled here, and this is handed over to CXF default logic.
+ * @param cri1 the first class resource info.
+ * @param cri2 the second class resource info.
+ * @param message the message, for comparison context.
+ * @return value based on chosen class. (Always 0 is returned)
+ */
+ @Override
+ public int compare(ClassResourceInfo cri1, ClassResourceInfo cri2, Message
message) {
+ return 0;
+ }
+
+ /**
+ * Compares the method to handle.
+ * Gets the maximum priority match for both handlers,
+ * and chooses the handler that has the maximum priority match.
+ * @param oper1 the first resource handler info.
+ * @param oper2 the second resource handler info.
+ * @param message the message, for comparison context.
+ * @return value based on chosen handler. Returns -1 if first, 1 if second
and 0 if no decision.
+ */
+ @Override
+ public int compare(OperationResourceInfo oper1, OperationResourceInfo
oper2, Message message) {
+ // getting all message context data
+ final String httpMethod = (String)
message.get(Message.HTTP_REQUEST_METHOD);
+ final MediaType contentType = JAXRSUtils.toMediaType((String) message
+ .get(Message.CONTENT_TYPE));
+ final List<MediaType> acceptTypes =
JAXRSUtils.parseMediaTypes((String) message.get(
+ Message.ACCEPT_CONTENT_TYPE));
+
+ LOG.debug("Message Method : " + httpMethod + ", ContentType : " +
contentType + ", "
+ + "Accept Types : " + acceptTypes);
+
+ int result = compareProduceTypes(oper1, oper2, acceptTypes);
+
+ String m1Name =
+ oper1.getClassResourceInfo().getServiceClass().getName() + "#"
+ + oper1.getMethodToInvoke().getName();
+ String m2Name =
+ oper2.getClassResourceInfo().getServiceClass().getName() + "#"
+ + oper2.getMethodToInvoke().getName();
+
+ if (result != 0) {
+ String chosen = result == -1 ? m1Name : m2Name;
+ LOG.debug("Between " + m1Name + " and " + m2Name + ", "
+ + chosen + " is chosen for handling the current request");
+ }
+
+ return result;
+ }
+
+ /**
+ * Compares the method to handle.
+ * Gets the maximum priority match for both handlers,
+ * and chooses the handler that has the maximum priority match.
+ * @param oper1 the first resource handler info.
+ * @param oper2 the second resource handler info.
+ * @param acceptTypes the list acceptable response mime type, for the
message.
+ * @return value based on chosen handler. Returns -1 if first, 1 if second
and 0 if no decision.
+ */
+ private int compareProduceTypes(OperationResourceInfo oper1,
OperationResourceInfo oper2,
+ final List<MediaType> acceptTypes) {
+ // getting matched produce type for both handlers.
+ // this is required if a method can produce multiple types.
+ List<MediaType> op1Matched = JAXRSUtils.intersectMimeTypes(acceptTypes,
+ oper1.getProduceTypes(), true);
+ List<MediaType> op2Matched = JAXRSUtils.intersectMimeTypes(acceptTypes,
+ oper2.getProduceTypes(), true);
+
+ // calculate the max priority for both handlers
+ int oper1Priority = op1Matched.stream()
+ .mapToInt(PRIORITIZED_MEDIA_LIST::indexOf)
+ .max().getAsInt();
+ int oper2Priority = op2Matched.stream()
+ .mapToInt(PRIORITIZED_MEDIA_LIST::indexOf)
+ .max().getAsInt();
+
+ // final calculation
+ return oper1Priority == oper2Priority ? 0 : (oper1Priority >
oper2Priority ? -1 : 1);
+ }
+
+}
\ No newline at end of file
diff --git
a/tika-server/src/main/java/org/apache/tika/server/TikaServerCli.java
b/tika-server/src/main/java/org/apache/tika/server/TikaServerCli.java
index 336ffb5..5167b78 100644
--- a/tika-server/src/main/java/org/apache/tika/server/TikaServerCli.java
+++ b/tika-server/src/main/java/org/apache/tika/server/TikaServerCli.java
@@ -359,6 +359,7 @@ public class TikaServerCli {
String url = "http://" + host + ":" + port + "/";
sf.setAddress(url);
+ sf.setResourceComparator(new ProduceTypeResourceComparator());
BindingFactoryManager manager =
sf.getBus().getExtension(BindingFactoryManager.class);
JAXRSBindingFactory factory = new JAXRSBindingFactory();
factory.setBus(sf.getBus());
diff --git a/tika-server/src/test/java/org/apache/tika/server/CXFTestBase.java
b/tika-server/src/test/java/org/apache/tika/server/CXFTestBase.java
index cfbafd0..0801a25 100644
--- a/tika-server/src/test/java/org/apache/tika/server/CXFTestBase.java
+++ b/tika-server/src/test/java/org/apache/tika/server/CXFTestBase.java
@@ -106,7 +106,7 @@ public abstract class CXFTestBase {
setUpResources(sf);
setUpProviders(sf);
sf.setAddress(endPoint + "/");
-
+ sf.setResourceComparator(new ProduceTypeResourceComparator());
BindingFactoryManager manager = sf.getBus().getExtension(
BindingFactoryManager.class
);