You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by re...@apache.org on 2010/08/02 00:39:52 UTC

svn commit: r981338 - in /incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs: ./ util/

Author: reto
Date: Sun Aug  1 22:39:52 2010
New Revision: 981338

URL: http://svn.apache.org/viewvc?rev=981338&view=rev
Log:
CLEREZZA-266: comnparing concreteness of matching writer annotation selecting between of accept-headers of same relative preference

Added:
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java
Modified:
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java

Modified: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java?rev=981338&r1=981337&r2=981338&view=diff
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java (original)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/ResponseProcessor.java Sun Aug  1 22:39:52 2010
@@ -34,6 +34,7 @@ import java.security.PrivilegedException
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -61,6 +62,7 @@ import org.apache.clerezza.triaxrs.util.
 import org.apache.clerezza.triaxrs.util.FirstByteActionOutputStream;
 import org.apache.clerezza.triaxrs.util.MediaTypeComparator;
 import org.apache.clerezza.triaxrs.util.BodyStoringResponse;
+import org.apache.clerezza.triaxrs.util.InconsistentMediaTypeComparator;
 import org.wymiwyg.wrhapi.HandlerException;
 import org.wymiwyg.wrhapi.HeaderName;
 import org.wymiwyg.wrhapi.MessageBody;
@@ -139,26 +141,37 @@ class ResponseProcessor {
 		}
 		final List<MediaType> expandedMethodProducibleMediaTypesList = expandListWithConcreterTypesFromAccept(methodProducibleMediaTypesList, acceptHeader);
 		MessageBodyWriter<Object> writer = null;
-		Collections.sort(expandedMethodProducibleMediaTypesList,
-				new MediaTypeComparator(acceptHeader));
+		List<Set<MediaType>> expandedMethodProducibleMediaTypeClasses
+				= getSortedClasses(expandedMethodProducibleMediaTypesList,
+				new InconsistentMediaTypeComparator(acceptHeader));
 		Collections.sort(methodProducibleMediaTypesList,
 				new MediaTypeComparator(acceptHeader));
 		MediaType relevantMethodProducibleType = null;
 
-		for (MediaType mediaType : expandedMethodProducibleMediaTypesList) {
-			writer = (MessageBodyWriter<Object>) JaxRsHandler.providers.getMessageBodyWriter(entity.getClass(), entityType,
-					annotations, mediaType);
-			if (writer != null) {
-				for (MediaType methodMediaType : methodProducibleMediaTypesList) {
-					if (methodMediaType.isCompatible(mediaType)) {
-						relevantMethodProducibleType = methodMediaType;
-						break;
+		for (Set<MediaType> preferenceClass : expandedMethodProducibleMediaTypeClasses) {
+			int lastWriterConcreteness = -1;
+			for (MediaType mediaType : preferenceClass) {
+				MessageBodyWriter<Object> currentWriter = (MessageBodyWriter<Object>) JaxRsHandler.providers.getMessageBodyWriter(entity.getClass(), entityType,
+						annotations, mediaType);
+				if (currentWriter != null) {
+					int writerConcreteness = getWriterConcreteness(currentWriter, mediaType);
+					if (writerConcreteness > lastWriterConcreteness) {
+						for (MediaType methodMediaType : methodProducibleMediaTypesList) {
+							if (methodMediaType.isCompatible(mediaType)) {
+								relevantMethodProducibleType = methodMediaType;
+								break;
+							}
+						}
+						writer = currentWriter;
 					}
 				}
+			}
+			if (writer != null) {
 				break;
 			}
 		}
 
+
 		if (writer == null) {
 			for (MediaType mediaType : expandedMethodProducibleMediaTypesList) {
 				try {
@@ -229,7 +242,7 @@ class ResponseProcessor {
 			}
 		}
 
-		if (acceptHeader.getAcceptingMediaType(mediaType) == null) {
+		if (acceptHeader.getAcceptingMediaType(mediaType).isEmpty()) {
 			if (!mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
 				throw new WebApplicationException(406);
 			}
@@ -356,11 +369,10 @@ class ResponseProcessor {
 	private static List<MediaType> expandListWithConcreterTypesFromAccept(List<MediaType> mediaTypesList, AcceptHeader acceptHeader) {
 		Collection<MediaType> addition = new HashSet<MediaType>();
 		for (MediaType mediaType : mediaTypesList) {
-			MediaType acceptingType = acceptHeader.getAcceptingMediaType(mediaType);
-
-			if ((acceptingType != null) && 
-					(MediaTypeComparator.compareByWildCardCount(acceptingType, mediaType) == -1)) {
-				addition.add(acceptingType);
+			for (MediaType acceptingType : acceptHeader.getAcceptingMediaType(mediaType)) {
+				if (MediaTypeComparator.compareByWildCardCount(acceptingType, mediaType) == -1) {
+					addition.add(acceptingType);
+				}
 			}
 		}
 		final List<MediaType> result = new ArrayList<MediaType>();
@@ -478,4 +490,67 @@ class ResponseProcessor {
 		return new MediaType(mediaType.getType(), mediaType.getSubtype(),
 				resultParams);
 	}
+
+	/**
+	 *
+	 * @param <T>
+	 * @param collection
+	 * @param comparator
+	 * @return a list containing sets of instances for which the comparator returns 0
+	 * in oder
+	 */
+	private static <T> List<Set<T>> getSortedClasses(Collection<T> collection,
+			Comparator<T> comparator) {
+		List<Set<T>> result = new ArrayList<Set<T>>();
+		if (collection.size() > 0) {
+			Set<T> pivotSet = new HashSet<T>();
+			Collection<T> before = new ArrayList<T>();
+			Collection<T> after = new ArrayList<T>();
+			Iterator<T> iterator = collection.iterator();
+			T pivot = iterator.next();
+			pivotSet.add(pivot);
+			while (iterator.hasNext()) {
+				T next = iterator.next();
+				int comparison = comparator.compare(next, pivot);
+				if (comparison > 0) {
+					after.add(next);
+				} else {
+					if (comparison < 0) {
+						before.add(next);
+					} else {
+						pivotSet.add(next);
+					}
+				}
+			}
+			result.addAll(getSortedClasses(before, comparator));
+			result.add(pivotSet);
+			result.addAll(getSortedClasses(after, comparator));
+		}
+		return result;
+
+	}
+
+	/**
+	 * 
+	 * @param writer
+	 * @param mediaType
+	 * @return 0 is mediaType ismatched only by wildcard in the @Produces of writer,
+	 *	 1, if the supertype is concrete, 2 if the subtype is concrete too
+	 */
+	private static int getWriterConcreteness(MessageBodyWriter<Object> writer, MediaType mediaType) {
+		Produces produces = writer.getClass().getAnnotation(Produces.class);
+		int result = 0;
+		if (produces != null) {
+			for (String producedValue : produces.value()) {
+				MediaType producesType = MediaType.valueOf(producedValue);
+				if (producesType.isCompatible(mediaType)) {
+					int concreteness = 2 - MediaTypeComparator.countWildChars(producesType);
+					if (concreteness > result) {
+						result = concreteness;
+					}
+				}
+			}
+		}
+		return result;
+	}
 }

Modified: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java?rev=981338&r1=981337&r2=981338&view=diff
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java (original)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/AcceptHeader.java Sun Aug  1 22:39:52 2010
@@ -19,7 +19,9 @@
 package org.apache.clerezza.triaxrs.util;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -123,13 +125,27 @@ public class AcceptHeader {
 		return 0;
 	}
 
-	public MediaType getAcceptingMediaType(MediaType type) {
+	/**
+	 *
+	 * @param type
+	 * @return the media-types in the accept header that are would best accept
+	 * type, i.e. all pattern with the highest same q-value accepting type are
+	 * returned
+	 */
+	public Set<MediaType> getAcceptingMediaType(MediaType type) {
+		Set<MediaType> result = new HashSet<MediaType>();
+		double currentQValue = 0;
 		for (AcceptHeaderEntry acceptHeaderEntry : entries) {
 			if (acceptHeaderEntry.mediaType.isCompatible(type)) {
-				return acceptHeaderEntry.mediaType;
+				if (acceptHeaderEntry.quality >= currentQValue) {
+					currentQValue = acceptHeaderEntry.quality;
+					result.add(acceptHeaderEntry.mediaType);
+				} else {
+					break;
+				}
 			}
 		}
-		return null;
+		return result;
 	}
 
 	/**

Added: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java?rev=981338&view=auto
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java (added)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/InconsistentMediaTypeComparator.java Sun Aug  1 22:39:52 2010
@@ -0,0 +1,60 @@
+/*
+ * 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.clerezza.triaxrs.util;
+
+import java.util.Comparator;
+
+import javax.ws.rs.core.MediaType;
+
+/**
+ * Sorts media types in accordance with an accept-header inconsistently
+ *
+ * This comparator is not consistent with equals
+ *
+ * @author reto
+ */
+public class InconsistentMediaTypeComparator implements Comparator<MediaType> {
+
+	private AcceptHeader acceptHeader;
+
+	public InconsistentMediaTypeComparator() {
+	}
+
+	public InconsistentMediaTypeComparator(AcceptHeader acceptHeader) {
+		this.acceptHeader = acceptHeader;
+	}
+
+
+	
+	@Override
+	public int compare(MediaType o1, MediaType o2) {
+		if (o1.equals(o2)) return 0;
+		if (acceptHeader != null) {
+			if (acceptHeader.getAcceptedQuality(o1) > acceptHeader.getAcceptedQuality(o2)) {
+				return -1;
+			}
+			if (acceptHeader.getAcceptedQuality(o1) < acceptHeader.getAcceptedQuality(o2)) {
+				return 1;
+			}
+		}
+		return MediaTypeComparator.inconsistentCompare(o1, o2);
+		
+	}
+
+}

Modified: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java?rev=981338&r1=981337&r2=981338&view=diff
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java (original)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.triaxrs/org.apache.clerezza.triaxrs/src/main/java/org/apache/clerezza/triaxrs/util/MediaTypeComparator.java Sun Aug  1 22:39:52 2010
@@ -23,8 +23,10 @@ import java.util.Comparator;
 import javax.ws.rs.core.MediaType;
 
 /**
- * Uses wirldcard as firts key and q-value as second key (for selecting 
- * server-side entities as jax-rs spec ignores q-value in annotations.
+ * Sorts media types in accordance with an accept-header, falling back to literal
+ * sorting to guarantee constistency.
+ *
+ * Also provides static Utility methods for Media Type comparison.
  *
  * @author reto
  */