incubator-wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ngalla...@apache.org
Subject svn commit: r787557 [12/12] - in /incubator/wink/contrib/ibm-jaxrs: ./ lib/ src/ src/com/ src/com/ibm/ src/com/ibm/ws/ src/com/ibm/ws/jaxrs/ src/com/ibm/ws/jaxrs/annotations/ src/com/ibm/ws/jaxrs/context/ src/com/ibm/ws/jaxrs/core/ src/com/ibm/ws/jaxrs...
Date Tue, 23 Jun 2009 05:41:55 GMT
Added: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=787557&view=auto
==============================================================================
--- incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (added)
+++ incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Tue Jun 23 05:41:49 2009
@@ -0,0 +1,1506 @@
+/*
+ * 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.cxf.jaxrs.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.activation.CommandMap;
+import javax.activation.DataContentHandler;
+import javax.activation.DataHandler;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.PathSegment;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Providers;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfoComparator;
+import org.apache.cxf.jaxrs.model.ProviderInfo;
+import org.apache.cxf.jaxrs.model.URITemplate;
+import org.apache.cxf.jaxrs.provider.ProviderFactory;
+
+import com.ibm.ws.jaxrs.context.ContextConstants;
+import com.ibm.ws.jaxrs.context.RESTContext;
+import com.ibm.ws.jaxrs.core.HttpHeadersImpl;
+import com.ibm.ws.jaxrs.core.RequestImpl;
+import com.ibm.ws.jaxrs.core.SecurityContextImpl;
+import com.ibm.ws.jaxrs.core.UriInfoImpl;
+import com.ibm.ws.jaxrs.ext.ProvidersImpl;
+import com.ibm.ws.jaxrs.i18n.Messages;
+import com.ibm.ws.jaxrs.integration.DefaultResponseWriter;
+import com.ibm.ws.jaxrs.integration.IntegrationRegistry;
+import com.ibm.ws.jaxrs.integration.OptionsResponseProvider;
+import com.ibm.ws.jaxrs.integration.ResponseWriter;
+import com.ibm.ws.jaxrs.io.ContentMonitor;
+import com.ibm.ws.jaxrs.io.LogInputStream;
+import com.ibm.ws.jaxrs.provider.RESTDataSource;
+
+public final class JAXRSUtils {
+
+    private static Log log = LogFactory.getLog(JAXRSUtils.class);
+
+    // private static final ResourceBundle BUNDLE =
+    // BundleUtils.getBundle(JAXRSUtils.class);
+
+    private JAXRSUtils() {
+    }
+
+    public static List<PathSegment> getPathSegments(String thePath, boolean decode) {
+        List<PathSegment> theList = new ArrayList<PathSegment>();
+        if (thePath != null && thePath.equals("/")) {
+            theList.add(new PathSegmentImpl(thePath, decode));
+        } else if (thePath != null) {
+            String[] segments = thePath.split("/");
+            for (String path : segments) {
+                if (!StringUtils.isEmpty(path)) {
+                    theList.add(new PathSegmentImpl(path, decode));
+                }
+            }
+        }
+        return theList;
+    }
+
+    public static List<MediaType> getMediaTypes(String[] values) {
+        if (values == null) {
+            return Collections.singletonList(MediaType.WILDCARD_TYPE);
+        }
+        List<MediaType> supportedMimeTypes = new ArrayList<MediaType>(
+                values.length);
+        for (int i = 0; i < values.length; i++) {
+            supportedMimeTypes.add(MediaType.valueOf(values[i]));
+        }
+        return supportedMimeTypes;
+    }
+
+    public static ClassResourceInfo findSubResourceClass(ClassResourceInfo resource, Class subResourceClassType) {
+        for (ClassResourceInfo subCri : resource.getSubClassResourceInfo()) {
+            if (subCri.getResourceClass()
+                    .isAssignableFrom(subResourceClassType)) {
+                return subCri;
+            }
+        }
+        return null;
+    }
+
+    public static ClassResourceInfo selectResourceClass(List<ClassResourceInfo> resources, String path, MultivaluedMap<String, String> values) {
+
+        if (resources.size() == 1) {
+            return resources.get(0).getURITemplate().match(path, values) ? resources
+                    .get(0)
+                    : null;
+        }
+
+        SortedMap<ClassResourceInfo, MultivaluedMap<String, String>> candidateList = new TreeMap<ClassResourceInfo, MultivaluedMap<String, String>>(
+                new Comparator<ClassResourceInfo>() {
+
+                    public int compare(ClassResourceInfo cr1, ClassResourceInfo cr2) {
+
+                        String l1 = cr1.getURITemplate().getLiteralChars();
+                        String l2 = cr2.getURITemplate().getLiteralChars();
+                        if (!l1.equals(l2)) {
+                            // descending order
+                            return l1.length() < l2.length() ? 1 : -1;
+                        }
+
+                        int g1 = cr1.getURITemplate().getNumberOfGroups();
+                        int g2 = cr2.getURITemplate().getNumberOfGroups();
+                        // descending order
+                        return g1 < g2 ? 1 : g1 > g2 ? -1 : 0;
+                    }
+
+                });
+
+        for (ClassResourceInfo resource : resources) {
+            MultivaluedMap<String, String> map = new MetadataMap<String, String>();
+            if (resource.getURITemplate().match(path, map)) {
+                candidateList.put(resource, map);
+            }
+        }
+
+        if (!candidateList.isEmpty()) {
+            Map.Entry<ClassResourceInfo, MultivaluedMap<String, String>> firstEntry = candidateList
+                    .entrySet().iterator().next();
+            values.putAll(firstEntry.getValue());
+            return firstEntry.getKey();
+        }
+
+        return null;
+    }
+
+    /**
+     * Method to select a ClassResourceInfo based on its @Alias annotation(s) value.
+     */
+    public static ClassResourceInfo selectResourceClassFromAliases(List<ClassResourceInfo> resources, String path, MultivaluedMap<String, String> values, RESTContext context) {
+
+        // keep mapping of URITemplates to the ClassResourceInfo they were constructed from
+        Map<URITemplate, ClassResourceInfo> templateMapping = new HashMap<URITemplate, ClassResourceInfo>();
+
+        // sorted map for all URITemplates
+        SortedMap<URITemplate, MultivaluedMap<String, String>> candidateList = new TreeMap<URITemplate, MultivaluedMap<String, String>>(
+                new Comparator<URITemplate>() {
+
+                    public int compare(URITemplate cr1, URITemplate cr2) {
+
+                        String l1 = cr1.getLiteralChars();
+                        String l2 = cr2.getLiteralChars();
+                        if (!l1.equals(l2)) {
+                            // descending order
+                            return l1.length() < l2.length() ? 1 : -1;
+                        }
+
+                        int g1 = cr1.getNumberOfGroups();
+                        int g2 = cr2.getNumberOfGroups();
+                        // descending order
+                        return g1 < g2 ? 1 : g1 > g2 ? -1 : 0;
+                    }
+
+                });
+
+        // remove any matrix parameters
+        String matrixFreePath = path;
+        if (matrixFreePath.contains(";")) {
+            matrixFreePath = matrixFreePath.substring(0, matrixFreePath
+                    .indexOf(";"));
+        }
+
+        for (ClassResourceInfo resource : resources) {
+            MultivaluedMap<String, String> map = new MetadataMap<String, String>();
+            List<URITemplate> templates = resource.getURIAliasTemplates();
+            if (templates != null) {
+                for (URITemplate template : templates) {
+
+                    // if we have a match, store the URITemplate and values map,
+                    // also store mapping of URITemplate to ClassResourceInfo
+                    if (template.match(matrixFreePath, map)) {
+                        candidateList.put(template, map);
+                        templateMapping.put(template, resource);
+                    }
+                }
+            }
+        }
+
+        // if we have a list, get the first entry and store the matched alias
+        // path on the provided RESTContext
+        if (!candidateList.isEmpty()) {
+            Map.Entry<URITemplate, MultivaluedMap<String, String>> firstEntry = candidateList
+                    .entrySet().iterator().next();
+            values.putAll(firstEntry.getValue());
+            context.setProperty(ContextConstants.MATCHED_ALIAS_PATH, firstEntry
+                    .getKey().getValue());
+            return templateMapping.get(firstEntry.getKey());
+        }
+
+        return null;
+    }
+
+    public static OperationResourceInfo findTargetMethod(ClassResourceInfo resource, String path, String httpMethod, MultivaluedMap<String, String> values, String requestContentType, List<MediaType> acceptContentTypes) {
+        SortedMap<OperationResourceInfo, MultivaluedMap<String, String>> candidateList = new TreeMap<OperationResourceInfo, MultivaluedMap<String, String>>(
+                new OperationResourceInfoComparator());
+        MediaType requestType = requestContentType == null ? null : MediaType
+                .valueOf(requestContentType);
+        boolean didMatchRequestType = false;
+        boolean didMatchMethodType = false;
+        boolean didMatchResource = false;
+        Set<String> possibleMethodOperations = new HashSet<String>();
+        if (resource.getMethodDispatcher().getOperationResourceInfos() == null
+                || resource.getMethodDispatcher().getOperationResourceInfos()
+                        .isEmpty()) {
+            if (StringUtils.isEmpty(path) || "/".equals(path)) {
+                // no operations exist at this level, fast fail
+                if (log.isErrorEnabled()) {
+                    log.error(Messages.getMessage("resourceNotFound00",
+                            resource.getResourceClass().getName(), httpMethod,
+                            path, (requestContentType == null) ? "UNKNOWN"
+                                    : requestContentType));
+                }
+                throw new WebApplicationException(405);
+            }
+            // did not match the final group yet so there didn't exist a subresource to match
+            throw new WebApplicationException(Response.Status.NOT_FOUND);
+        }
+        for (MediaType acceptType : acceptContentTypes) {
+            // used to save off possible GET match for a HEAD request
+            for (OperationResourceInfo ori : resource.getMethodDispatcher()
+                    .getOperationResourceInfos()) {
+                URITemplate uriTemplate = ori.getURITemplate();
+
+                MultivaluedMap<String, String> map = cloneMap(values);
+                if (uriTemplate != null && uriTemplate.match(path, map)) {
+                    String finalGroup = map
+                            .getFirst(URITemplate.FINAL_MATCH_GROUP);
+                    if (ori.isSubResourceLocator()) {
+                        candidateList.put(ori, map);
+                    } else if (finalGroup == null
+                            || StringUtils.isEmpty(finalGroup)
+                            || finalGroup.equals("/")) {
+                        didMatchResource = true;
+
+                        possibleMethodOperations.add(ori.getHttpMethod()
+                                .toUpperCase());
+                        if (ori.getHttpMethod().equalsIgnoreCase(httpMethod)) {
+                            didMatchMethodType = true;
+                            if (matchContentMediaMimeTypes(ori.getConsumes(),
+                                    requestType)) {
+                                didMatchRequestType = true;
+                                if (matchContentMediaMimeTypes(ori
+                                        .getProduces(), acceptType)) {
+                                    if (log.isDebugEnabled()) {
+                                        log
+                                                .debug("Added the "
+                                                        + ori
+                                                                .getMethodToInvoke()
+                                                                .getName()
+                                                        + " method to the candidate list for the request with path: "
+                                                        + path
+                                                        + " HTTP method: "
+                                                        + httpMethod
+                                                        + " Consumes: "
+                                                        + typesAsString(ori
+                                                                .getConsumes())
+                                                        + " Produces: "
+                                                        + typesAsString(ori
+                                                                .getProduces()));
+                                    }
+                                    candidateList.put(ori, map);
+                                }
+                            }
+                        } else if (httpMethod.equalsIgnoreCase("HEAD")
+                                && ori.getHttpMethod().equalsIgnoreCase("GET")
+                                && matchContentMediaMimeTypes(
+                                        ori.getConsumes(), requestType)
+                                && matchContentMediaMimeTypes(
+                                        ori.getProduces(), acceptType)) {
+                            candidateList.put(ori, map);
+                        }
+                    }
+                }
+            }
+            if (!candidateList.isEmpty()) {
+                Map.Entry<OperationResourceInfo, MultivaluedMap<String, String>> firstEntry = candidateList
+                        .entrySet().iterator().next();
+                values.clear();
+                values.putAll(firstEntry.getValue());
+                OperationResourceInfo ori = firstEntry.getKey();
+                if (log.isDebugEnabled()) {
+                    log.debug("Found the " + ori.getMethodToInvoke().getName()
+                            + " method for the " + "request with path: " + path
+                            + " and HTTP method: " + httpMethod);
+                }
+                return ori;
+            }
+        }
+
+        if (httpMethod.equalsIgnoreCase("OPTIONS")) {
+            // check to see if there is an OPTIONS method, but the request
+            // did not match
+            if (resource.getMethodDispatcher().getOperationResourceInfos() != null) {
+                for (OperationResourceInfo opInfo : resource
+                        .getMethodDispatcher().getOperationResourceInfos()) {
+
+                    // if we find an @OPTIONS annotated method, but it did not match the request,
+                    // it is time to return a 406
+                    if ("OPTIONS".equalsIgnoreCase(opInfo.getHttpMethod())) {
+                        throw new WebApplicationException(
+                                Response.Status.NOT_ACCEPTABLE);
+                    }
+                }
+            }
+            // return null for options support later in the runtime
+            return null;
+        }
+
+        if (didMatchRequestType) {
+            // but did not match accept type
+            throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE);
+        }
+
+        if (didMatchMethodType) {
+            // but did not match request type
+            throw new WebApplicationException(
+                    Response.Status.UNSUPPORTED_MEDIA_TYPE);
+        }
+
+        if (didMatchResource) {
+            // but did not match request httpmethod
+            possibleMethodOperations.add("HEAD");
+            possibleMethodOperations.add("OPTIONS");
+            ResponseBuilder respBuilder = Response.status(405);
+            for (String s : possibleMethodOperations) {
+                respBuilder.header("Allow", s);
+            }
+            throw new WebApplicationException(respBuilder.build());
+        }
+
+        // did not match a URI template, so throw 404 (the original class resource exists but no subclass)
+        throw new WebApplicationException(Response.Status.NOT_FOUND);
+    }
+
+    static String typesAsString(List<MediaType> types) {
+        StringBuffer sb = new StringBuffer();
+        String result = "";
+        if (types != null) {
+            for (MediaType type : types) {
+                sb.append(type.toString() + " ");
+            }
+            result = sb.toString().trim();
+        }
+        return result;
+    }
+
+    public static List<MediaType> getConsumeTypes(Consumes cm) {
+        return cm == null ? Collections.singletonList(MediaType.WILDCARD_TYPE)
+                : getMediaTypes(cm.value());
+    }
+
+    public static List<MediaType> getProduceTypes(Produces pm) {
+        return pm == null ? Collections.singletonList(MediaType.WILDCARD_TYPE)
+                : getMediaTypes(pm.value());
+    }
+
+    public static int compareMediaTypesQValue(MediaType mt1, MediaType mt2) {
+        float q1 = getMediaTypeQualityFactor(mt1.getParameters().get("q"));
+        float q2 = getMediaTypeQualityFactor(mt2.getParameters().get("q"));
+        int result = Float.compare(q1, q2);
+        return (result == 0 ? result : -result);
+    }
+
+    public static int compareMediaTypes(MediaType mt1, MediaType mt2) {
+
+        if ((!mt1.isWildcardSubtype() && !mt1.isWildcardType()
+                && !mt2.isWildcardSubtype() && !mt2.isWildcardType())
+                || (mt1.isWildcardSubtype() && mt1.isWildcardType()
+                        && mt2.isWildcardSubtype() && mt2.isWildcardType())) {
+
+            float q1 = getMediaTypeQualityFactor(mt1.getParameters().get("q"));
+            float q2 = getMediaTypeQualityFactor(mt2.getParameters().get("q"));
+            int result = Float.compare(q1, q2);
+            if (result == 0) {
+                int mt1pSize = mt1.getParameters().size();
+                int mt2pSize = mt2.getParameters().size();
+                if (mt1pSize > mt2pSize) {
+                    return -1;
+                } else if (mt1pSize < mt2pSize) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+            return -result;
+        }
+
+        if (mt1.isWildcardType() && !mt2.isWildcardType()) {
+            return 1;
+        }
+        if (!mt1.isWildcardType() && mt2.isWildcardType()) {
+            return -1;
+        }
+
+        if (mt1.getType().equals(mt2.getType())) {
+            if (mt1.isWildcardSubtype() && !mt2.isWildcardSubtype()) {
+                return 1;
+            }
+            if (!mt1.isWildcardSubtype() && mt2.isWildcardSubtype()) {
+                return -1;
+            }
+        }
+        return mt1.toString().compareTo(mt2.toString());
+
+    }
+
+    public static float getMediaTypeQualityFactor(final String q) {
+        if (q == null) {
+            return 1;
+        }
+        String qualityFactor = q;
+        if (qualityFactor.charAt(0) == '.') {
+            qualityFactor = '0' + qualityFactor;
+        }
+        try {
+            return Float.parseFloat(qualityFactor);
+        } catch (NumberFormatException ex) {
+            // default value will do
+        }
+        return 1;
+    }
+
+    //Message contains following information: PATH, HTTP_REQUEST_METHOD,CONTENT_TYPE, InputStream.
+    public static List<Object> processParameters(OperationResourceInfo ori, RESTContext context)
+            throws Exception {
+        Method method = ori.getAnnotatedMethod();
+        Class[] parameterTypes = method.getParameterTypes();
+        Type[] genericParameterTypes = method.getGenericParameterTypes();
+        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+
+        List<Object> params = new ArrayList<Object>(parameterTypes.length);
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            Object param = processParameter(parameterTypes[i],
+                    genericParameterTypes[i], parameterAnnotations[i], context,
+                    ori);
+            params.add(param);
+        }
+
+        return params;
+    }
+
+    private static Object processParameter(Class<?> parameterClass, Type parameterType, Annotation[] parameterAnns, RESTContext context, OperationResourceInfo ori)
+            throws Exception {
+        InputStream is = (InputStream) context
+                .getProperty(ContextConstants.REQUEST_INPUT_STREAM);
+
+        MultivaluedMap<String, String> values = (MultivaluedMap<String, String>) context
+                .getProperty(ContextConstants.TEMPLATE_VALUES);
+
+        String path = (String) context
+                .getProperty(ContextConstants.HTTP_PATH_INFO);
+
+        boolean isJAXRSParamAnnotationsFound = false;
+        if (parameterAnns != null && parameterAnns.length > 0) {
+            for (Annotation ann : parameterAnns) {
+                if (AnnotationUtils
+                        .isParamAnnotationClass(ann.annotationType())) {
+                    isJAXRSParamAnnotationsFound = true;
+                    break;
+                }
+            }
+        }
+
+        if (isJAXRSParamAnnotationsFound) {
+
+            for (Annotation ann : parameterAnns) {
+                if (ann.annotationType().equals(Context.class)) {
+                    return createContextValue(context, parameterType,
+                            parameterClass);
+                }
+            }
+
+            return createHttpParameterValue(parameterAnns, parameterClass,
+                    parameterType, context, values, path, ori);
+        }
+
+        // we can't really limit it to just PUT and POST
+        if (log.isDebugEnabled()) {
+            log.debug("No parameter annotations found.");
+        }
+
+        String contentType = (String) context
+                .getProperty(ContextConstants.CONTENT_TYPE);
+        if (contentType == null) {
+            contentType = MediaType.APPLICATION_OCTET_STREAM;
+        }
+
+        if (ori.isFormParamFound()) {
+            return new MetadataMap<String, String>(
+                    (Map<String, List<String>>) context
+                            .getProperty(ContextConstants.FORM_VALUES));
+        }
+
+        return readFromMessageBody(parameterClass, parameterType,
+                parameterAnns, is, MediaType.valueOf(contentType), ori, context);
+    }
+
+    private static Object createHttpParameterValue(Annotation[] anns, Class<?> parameterClass, Type genericParam, RESTContext context, MultivaluedMap<String, String> values, String path, OperationResourceInfo ori)
+            throws Exception {
+        return InjectionUtils.handleNonContextParam(parameterClass,
+                genericParam, context, anns);
+    }
+
+    public static MultivaluedMap<String, String> getMatrixParams(String path, boolean decode) {
+        int index = path.indexOf(';');
+        MultivaluedMap<String, String> matrixParams = index == -1 ? new MetadataMap<String, String>()
+                : JAXRSUtils.getStructuredParams(path.substring(index + 1),
+                        ";", decode);
+        formatMatrixParams(matrixParams);
+        return matrixParams;
+    }
+
+    /**
+     * This method is a convenience method to ensure any embedded matrix parameters
+     * are correctly formatted. We should remove the trailing part off of any embedded
+     * matrix parameter value.
+     */
+    static void formatMatrixParams(MultivaluedMap<String, String> matrixParams) {
+        if (matrixParams != null && !matrixParams.isEmpty()) {
+            Collection<List<String>> valueColl = matrixParams.values();
+            for (List<String> values : valueColl) {
+                if (values != null && !values.isEmpty()) {
+                    int i = 0;
+                    for (String value : values) {
+
+                        // if we find a '/' and it is not the end of the string,
+                        // we'll take it off and replace it with the value before
+                        // the '/'
+                        if (value.indexOf("/") != -1
+                                && value.indexOf("/") != value.length() - 1) {
+                            value = values.remove(i);
+                            value = value.substring(0, value.indexOf("/"));
+                            values.add(i, value);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public static Object createContextValue(RESTContext context, Type genericType, Class<?> clazz) {
+
+        Object o = null;
+        if (UriInfo.class.equals(clazz)) {
+            o = new UriInfoImpl(context);
+        } else if (HttpHeaders.class.equals(clazz)) {
+            o = new HttpHeadersImpl(context);
+        } else if (Request.class.equals(clazz)) {
+            o = new RequestImpl(context);
+        } else if (SecurityContext.class.equals(clazz)) {
+            o = new SecurityContextImpl(context);
+        } else if (ContextResolver.class.equals(clazz)) {
+            o = createContextResolver(genericType, context);
+        } else if (Providers.class.equals(clazz)) {
+            o = new ProvidersImpl(context);
+        }
+
+        return o == null ? createServletResourceValue(context, clazz) : o;
+    }
+
+    public static ContextResolver<?> createContextResolver(Type genericType, RESTContext context) {
+        if (genericType instanceof ParameterizedType) {
+            return ProviderFactory
+                    .getInstance(context)
+                    .createContextResolver(
+                            ((ParameterizedType) genericType)
+                                    .getActualTypeArguments()[0], null, context);
+        }
+        return null;
+    }
+
+    public static Object createServletResourceValue(RESTContext context, Class<?> clazz) {
+        if (HttpServletRequest.class.equals(clazz)) {
+            return context.getProperty(ContextConstants.SERVLET_REQUEST);
+        }
+        if (HttpServletResponse.class.equals(clazz)) {
+            return context.getProperty(ContextConstants.SERVLET_RESPONSE);
+        }
+        if (ServletContext.class.equals(clazz)) {
+            return context.getProperty(ContextConstants.SERVLET_CONTEXT);
+        }
+        if (ServletConfig.class.equals(clazz)) {
+            return context.getProperty(ContextConstants.SERVLET_CONFIG);
+        }
+
+        return null;
+    }
+
+    /**
+     * Retrieve map of query parameters from the passed in message
+     *
+     * @param message
+     * @return a Map of query parameters.
+     */
+
+    public static MultivaluedMap<String, String> getStructuredParams(String query, String sep, boolean decode) {
+        MultivaluedMap<String, String> queries = new MetadataMap<String, String>(
+                new LinkedHashMap<String, List<String>>());
+
+        if (!StringUtils.isEmpty(query)) {
+            List<String> parts = Arrays.asList(query.split(sep));
+            for (String part : parts) {
+                String[] values = part.split("=");
+                queries.add(decode ? uriDecode(values[0]) : values[0],
+                        values.length == 1 ? "" : decode ? uriDecode(values[1])
+                                : values[1]);
+            }
+        }
+        return queries;
+    }
+
+    /**
+     * This method will accept an array of Objects and return a List that
+     * contains the result of calling 'toString' on each of the Objects.
+     *
+     */
+
+    public static List<String> convertToStringList(Object... values) {
+        List<String> stringList = new ArrayList<String>();
+        for (Object value : values) {
+            stringList.add(value.toString());
+        }
+        return stringList;
+    }
+
+    public static String uriDecode(String query) {
+        try {
+            return URLDecoder.decode(query, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            // Swallow unsupported decoding exception
+        }
+        return query;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Object readFromMessageBody(Class<T> targetTypeClass, Type parameterType, Annotation[] parameterAnnotations, InputStream is, MediaType contentType, OperationResourceInfo ori, final RESTContext context)
+            throws IOException {
+
+        // OperationResourceInfo is passed for error logging reasons.  We only use the consumesTypes for real function:
+        List<MediaType> consumeTypes = ori.getConsumes();
+
+        List<MediaType> types = JAXRSUtils.intersectMimeTypes(consumeTypes,
+                contentType);
+        MessageBodyReader provider = null;
+        for (MediaType type : types) {
+            provider = ProviderFactory.getInstance(context)
+                    .createMessageBodyReader(targetTypeClass, parameterType,
+                            parameterAnnotations, type, context);
+
+            // TODO : make the exceptions
+            if (provider != null) {
+                break;
+            }
+        }
+        MultivaluedMap<String, String> headers = new MultivaluedMap<String, String>() {
+
+            private MultivaluedMap<String, String> delegate = (MultivaluedMap<String, String>) context
+                    .getProperty(ContextConstants.HTTP_HEADER_VALUES);
+
+            public void add(String arg0, String arg1) {
+                throw new UnsupportedOperationException();
+            }
+
+            public String getFirst(String arg0) {
+                return delegate.getFirst(arg0.toLowerCase());
+            }
+
+            public void putSingle(String arg0, String arg1) {
+                throw new UnsupportedOperationException();
+            }
+
+            public void clear() {
+                throw new UnsupportedOperationException();
+            }
+
+            public boolean containsKey(Object key) {
+                if (key instanceof String) {
+                    return delegate.containsKey(((String) key).toLowerCase());
+                }
+                return delegate.containsKey(key);
+            }
+
+            public boolean containsValue(Object value) {
+                return delegate.containsValue(value);
+            }
+
+            public Set<java.util.Map.Entry<String, List<String>>> entrySet() {
+                Set<java.util.Map.Entry<String, List<String>>> ret = delegate
+                        .entrySet();
+                if (ret == null) {
+                    return null;
+                }
+                return Collections.unmodifiableSet(ret);
+            }
+
+            public List<String> get(Object key) {
+                List<String> ret = null;
+                if (key instanceof String) {
+                    ret = delegate.get(((String) key).toLowerCase());
+                } else {
+                    ret = delegate.get(key);
+                }
+
+                if (ret != null) {
+                    return Collections.unmodifiableList(ret);
+                }
+                return ret;
+            }
+
+            public boolean isEmpty() {
+                return delegate.isEmpty();
+            }
+
+            public Set<String> keySet() {
+                return delegate.keySet();
+            }
+
+            public List<String> put(String key, List<String> value) {
+                throw new UnsupportedOperationException();
+            }
+
+            public void putAll(Map<? extends String, ? extends List<String>> map) {
+                throw new UnsupportedOperationException();
+            }
+
+            public List<String> remove(Object key) {
+                throw new UnsupportedOperationException();
+            }
+
+            public int size() {
+                return delegate.size();
+            }
+
+            public Collection<List<String>> values() {
+                return delegate.values();
+            }
+
+        };
+
+        if (provider != null) {
+            if (log.isDebugEnabled()) {
+                log.debug("Attempting to use MessageBodyReader: " + provider
+                        + " to read from message");
+            }
+            try {
+                Object obj = provider.readFrom(targetTypeClass, parameterType,
+                        parameterAnnotations, contentType, headers, is);
+                return obj;
+            } finally {
+                // log the input if logging enabled
+                if (log.isDebugEnabled()) {
+                    logInput(context);
+                }
+            }
+        }
+
+        // if we could not find a MessageBodyReader to handle the type, let's look
+        // for a DataHandler via the JAF
+        if (log.isDebugEnabled()) {
+            log.debug("Attempting to use DataHandler to read from message");
+        }
+
+        byte[] bytes = getBytesFromStream(is);
+        RESTDataSource source = new RESTDataSource(bytes, null, contentType
+                .toString());
+        DataHandler handler = new DataHandler(source);
+        Object obj = handler.getContent();
+
+        // if there was no DataHandler for the Object type, the InputStream
+        // will
+        // simply be returned
+        if (!(obj instanceof InputStream)) {
+            if (log.isDebugEnabled()) {
+                log
+                        .debug("Successfully read message with DataHandler for mimeType: "
+                                + contentType.toString());
+                logInput(context);
+            }
+            return obj;
+        }
+
+        // at this point, no reader or data handler was found for the method parameter.  Log it and throw 415
+        if (log.isErrorEnabled()) {
+            log.error(Messages.getMessage("readerOrHandlerNotFound",
+                    (String) context.getProperty(ContextConstants.HTTP_METHOD),
+                    (String) context
+                            .getProperty(ContextConstants.HTTP_REQUEST_URL),
+                    ori.getClassResourceInfo().getResourceClass().getName()
+                            + "." + ori.getMethodToInvoke().getName(),
+                    parameterType.toString(), contentType.toString()));
+        }
+        throw new WebApplicationException(415);
+
+    }
+
+    /**
+     * Convenience method to log the contents of the request InputStream. This
+     * method should only be called when logging is enabled.
+     */
+    static void logInput(RESTContext context) {
+        InputStream is = (InputStream) context
+                .getProperty(ContextConstants.REQUEST_INPUT_STREAM);
+        if (is instanceof LogInputStream) {
+            ((LogInputStream) is).logBytes();
+        }
+    }
+
+    /**
+     * This method will be used to get an array of bytes from an InputStream.
+     */
+    static byte[] getBytesFromStream(InputStream inputStream)
+            throws IOException {
+        byte[] inputBytes = new byte[inputStream.available()];
+        int next = inputStream.read();
+        int i = 0;
+        while (next != -1) {
+            if (i == inputBytes.length) {
+                int size = i == 0 ? 1 : i;
+                byte[] inputCopy = new byte[2 * size];
+                System
+                        .arraycopy(inputBytes, 0, inputCopy, 0,
+                                inputBytes.length);
+                inputBytes = inputCopy;
+            }
+            inputBytes[i] = (byte) next;
+            next = inputStream.read();
+            i++;
+        }
+        return inputBytes;
+    }
+
+    public static boolean matchContentMediaMimeTypes(List<MediaType> oriMediaTypes, MediaType contentType) {
+        if (contentType == null) {
+            if (oriMediaTypes == null
+                    || (oriMediaTypes.isEmpty() || oriMediaTypes
+                            .contains(MediaType.WILDCARD_TYPE))) {
+                return true;
+            }
+            return false;
+        }
+        return intersectMimeTypes(oriMediaTypes, contentType).size() != 0;
+    }
+
+    public static List<MediaType> parseMediaTypes(String types) {
+        List<MediaType> acceptValues = new ArrayList<MediaType>();
+
+        if (types != null) {
+            String parsedTypes = types;
+            while (parsedTypes.length() > 0) {
+                String tp = parsedTypes;
+                int index = parsedTypes.indexOf(',');
+                if (index != -1) {
+                    tp = parsedTypes.substring(0, index);
+                    parsedTypes = parsedTypes.substring(index + 1).trim();
+                } else {
+                    parsedTypes = "";
+                }
+                acceptValues.add(MediaType.valueOf(tp));
+            }
+        } else {
+            acceptValues.add(MediaType.WILDCARD_TYPE);
+        }
+
+        return acceptValues;
+    }
+
+    /**
+     * Intersect two mime types lists, preferring to keep the media type parameters on the second list of media types.
+     *
+     * @param requiredMediaTypes
+     * @param userMediaTypes
+     * @return return a list of intersected mime types but which has no sorted order
+     */
+    public static List<MediaType> intersectMimeTypes(List<MediaType> requiredMediaTypes, List<MediaType> userMediaTypes) {
+        Set<MediaType> supportedMimeTypeList = new LinkedHashSet<MediaType>();
+
+        for (MediaType requiredType : requiredMediaTypes) {
+            for (MediaType userType : userMediaTypes) {
+                if (requiredType.isCompatible(userType)) {
+                    /*
+                     * TODO: should not add types where the quality parameter is 0.0
+                     */
+                    String type = requiredType.getType().equals(
+                            MediaType.MEDIA_TYPE_WILDCARD) ? userType.getType()
+                            : requiredType.getType();
+                    String subtype = requiredType.getSubtype().equals(
+                            MediaType.MEDIA_TYPE_WILDCARD) ? userType
+                            .getSubtype() : requiredType.getSubtype();
+
+                    /*
+                     * go ahead and add in the userType parameters but go back
+                     * and add in any requiredType's parameters that do not
+                     * conflict
+                     */
+                    Map<String, String> typeParams = new HashMap<String, String>(
+                            userType.getParameters());
+                    Map<String, String> requiredTypeParameters = requiredType
+                            .getParameters();
+                    for (String key : requiredTypeParameters.keySet()) {
+                        if (!typeParams.containsKey(key)) {
+                            typeParams
+                                    .put(key, requiredTypeParameters.get(key));
+                        }
+                    }
+
+                    supportedMimeTypeList.add(new MediaType(type, subtype,
+                            typeParams));
+                }
+            }
+        }
+
+        return new ArrayList<MediaType>(supportedMimeTypeList);
+    }
+
+    public static List<MediaType> intersectMimeTypes(List<MediaType> mimeTypesA, MediaType mimeTypeB) {
+        return intersectMimeTypes(mimeTypesA, Collections
+                .singletonList(mimeTypeB));
+    }
+
+    public static List<MediaType> intersectMimeTypes(String mimeTypesA, String mimeTypesB) {
+        return intersectMimeTypes(parseMediaTypes(mimeTypesA),
+                parseMediaTypes(mimeTypesB));
+    }
+
+    public static List<MediaType> sortMediaTypes(String mediaTypes) {
+        return sortMediaTypes(JAXRSUtils.parseMediaTypes(mediaTypes));
+    }
+
+    public static List<MediaType> sortMediaTypesQValue(String mediaTypes) {
+        return sortMediaTypesQValue(JAXRSUtils.parseMediaTypes(mediaTypes));
+    }
+
+    public static List<MediaType> sortMediaTypes(List<MediaType> types) {
+        if (types.size() > 1) {
+            Collections.sort(types, new Comparator<MediaType>() {
+
+                public int compare(MediaType mt1, MediaType mt2) {
+                    return JAXRSUtils.compareMediaTypes(mt1, mt2);
+                }
+
+            });
+        }
+        return types;
+    }
+
+    public static List<MediaType> sortMediaTypesQValue(List<MediaType> types) {
+        if (types.size() > 1) {
+            Collections.sort(types, new Comparator<MediaType>() {
+
+                public int compare(MediaType mt1, MediaType mt2) {
+                    return JAXRSUtils.compareMediaTypesQValue(mt1, mt2);
+                }
+
+            });
+        }
+        return types;
+    }
+
+    private static <K, V> MultivaluedMap<K, V> cloneMap(MultivaluedMap<K, V> map1) {
+
+        MultivaluedMap<K, V> map2 = new MetadataMap<K, V>();
+        for (Map.Entry<K, List<V>> entry : map1.entrySet()) {
+            map2.put(entry.getKey(), new ArrayList<V>(entry.getValue()));
+        }
+        return map2;
+    }
+
+    /**
+      * This utility method will drive the processing of a response to a
+      * request sent to our REST runtime.
+      *
+      */
+    public static void processResponse(RESTContext context) throws Exception {
+        // if servlet response is already committed, break out
+        HttpServletResponse servletResponse = (HttpServletResponse) context
+                .getProperty(ContextConstants.SERVLET_RESPONSE);
+        if (servletResponse != null && servletResponse.isCommitted()) {
+            // don't process the response any further
+            // but flush the buffer one last time
+            // in case there was some tailing output that hasn't been flushed yet
+            servletResponse.flushBuffer();
+            return;
+        }
+
+        // grab the needed objects
+        Object responseObj = context
+                .getProperty(ContextConstants.INVOCATION_RESULT);
+        OperationResourceInfo operation = (OperationResourceInfo) context
+                .getProperty(ContextConstants.OPERATION_RESOURCE);
+        List<MediaType> acceptContentTypes = (List<MediaType>) context
+                .getProperty(ContextConstants.ACCEPT_CONTENT_TYPES);
+
+        Response response = (Response) context
+                .getProperty(ContextConstants.RESPONSE);
+
+        ContentMonitor monitor = (ContentMonitor) context
+                .getProperty(ContextConstants.CONTENT_MONITOR);
+
+        // in some cases, such as error flows, the response may already have been
+        // built and set on the RESTContext
+        if (response == null) {
+            if (responseObj instanceof Response) {
+                response = (Response) responseObj;
+            } else if (responseObj == null) {
+                response = Response.noContent().build();
+            } else {
+                response = Response.ok(responseObj).build();
+            }
+        }
+
+        String path = (String) context
+                .getProperty(ContextConstants.HTTP_PATH_INFO);
+        String httpMethod = (String) context
+                .getProperty(ContextConstants.HTTP_METHOD);
+
+        String contentType = (String) response.getMetadata().getFirst(
+                HttpHeaders.CONTENT_TYPE);
+        context.setProperty(ContextConstants.RESPONSE, response);
+        context.setProperty(ContextConstants.HTTP_HEADER_VALUES, response
+                .getMetadata());
+        OutputStream os = (OutputStream) context
+                .getProperty(ContextConstants.RESPONSE_OUTPUT_STREAM);
+
+        ResponseWriter responseWriter = (ResponseWriter) IntegrationRegistry
+                .getIntegrationProvider(
+                        context
+                                .getProperty(ContextConstants.INTEGRATION_REGISTRATION_KEY),
+                        ResponseWriter.class);
+        if (responseWriter == null) {
+            responseWriter = new DefaultResponseWriter();
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("Found this ResponseWriter: " + responseWriter);
+        }
+
+        responseWriter.preWrite(context);
+
+        responseObj = response.getEntity();
+        if (responseObj == null) {
+            responseWriter.postWrite(context);
+            return;
+        }
+
+        List<MediaType> availableContentTypes = computeAvailableContentTypes(
+                contentType, response, operation, acceptContentTypes);
+
+        // if we did not find interesecting content types AND this is an options
+        // request, we have two options: first, check the Accept header and set
+        // that to the content type if it is present, otherwise, the */* type
+        // becomes the content type
+        if (availableContentTypes == null || availableContentTypes.isEmpty()) {
+
+            if ("OPTIONS".equalsIgnoreCase(httpMethod)) {
+                if (acceptContentTypes != null && !acceptContentTypes.isEmpty()) {
+                    availableContentTypes = acceptContentTypes;
+                } else {
+                    availableContentTypes = new ArrayList<MediaType>();
+                    availableContentTypes.add(MediaType.WILDCARD_TYPE);
+                }
+            }
+        }
+
+        Method invoked = operation == null ? null : operation
+                .getMethodToInvoke();
+        Type genericType = invoked != null ? invoked.getGenericReturnType()
+                : null;
+        Object objToInvokeWriterWith = responseObj;
+        Class targetType = responseObj.getClass();
+        if (GenericEntity.class.isAssignableFrom(responseObj.getClass())) {
+            GenericEntity ge = (GenericEntity) responseObj;
+            targetType = ge.getRawType();
+            genericType = ge.getType();
+            objToInvokeWriterWith = ge.getEntity();
+        } else if (invoked != null) {
+            if (invoked.getGenericReturnType() instanceof Class) {
+                Class retType = (Class) invoked.getGenericReturnType();
+                if (Response.class.isAssignableFrom(retType)) {
+                    targetType = responseObj.getClass();
+                    genericType = responseObj.getClass();
+                }
+            }
+        }
+
+        MessageBodyWriter writer = null;
+        MediaType responseType = null;
+
+        boolean written = false;
+        try {
+            for (MediaType type : availableContentTypes) {
+                writer = ProviderFactory.getInstance(context)
+                        .createMessageBodyWriter(
+                                targetType,
+                                genericType,
+                                invoked != null ? invoked.getAnnotations()
+                                        : new Annotation[] {}, type, context);
+
+                if (writer != null) {
+                    responseType = (MediaType) context
+                            .getProperty(ContextConstants.RESPONSE_CONTENT_TYPE);
+                    break;
+                }
+            }
+
+            if (writer != null) {
+                responseType = checkFinalContentType(responseType);
+                responseWriter.writeWithEntityProvider(context, writer,
+                        objToInvokeWriterWith, targetType, genericType,
+                        (invoked != null ? invoked.getAnnotations()
+                                : new Annotation[] {}), responseType, response
+                                .getMetadata(), os);
+                written = true;
+            }
+            // if we could not find a MessageBodyWriter via JAF, let's find a
+            // DataHandler via the JAF
+            else if (!written) {
+                for (MediaType type : availableContentTypes) {
+                    DataContentHandler dch = CommandMap.getDefaultCommandMap()
+                            .createDataContentHandler(type.toString());
+                    if (dch != null) {
+                        if (log.isDebugEnabled()) {
+                            log
+                                    .debug("Writing application response with DataHandler for mimeType: "
+                                            + type.toString());
+                        }
+                        responseWriter.writeWithDataHandler(context,
+                                responseObj, type.toString(), dch, os);
+                        written = true;
+                        break;
+                    }
+                }
+            }
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("Throwable caught during processResponse: " + t, t);
+            }
+            written = processWriteException(context, t);
+        }
+
+        if (!written) {
+            // give as much info in the log as possible so app developer knows what needs to be implemented
+            String invokedString = getMethodInfoForErrorLog(invoked);
+            log.error(Messages.getMessage("writerNotFound", httpMethod, path,
+                    invokedString, targetType.getName()));
+            context.setProperty(ContextConstants.RESPONSE, Response.status(
+                    Response.Status.INTERNAL_SERVER_ERROR).build());
+            processResponse(context);
+        }
+
+        // let's try to set the content length of the response
+        if (monitor != null) {
+            Integer contentLength = monitor.getContentLength();
+            if (log.isDebugEnabled()) {
+                log.debug("Setting response content length: " + contentLength);
+            }
+            context.setProperty(ContextConstants.RESPONSE_CONTENT_LENGTH,
+                    contentLength);
+        }
+        responseWriter.postWrite(context);
+    }
+
+    /**
+     * This processes an exception that occurs during response serialization. If
+     * the exception has not been mapped, we'll attempt to map it and allow the
+     * mapper to handle it. Otherwise, the exception will be thrown to the underlying
+     * container. If this is an exception that is occurring from processing an
+     * exception response, we will throw an error indicating a 500 status.
+     */
+    static boolean processWriteException(RESTContext context, Throwable t)
+            throws Exception {
+        Boolean mappedException = (Boolean) context
+                .getProperty(ContextConstants.MAPPED_EXCEPTION);
+
+        if (log.isErrorEnabled()) {
+            log.error(t.getMessage(), t);
+        }
+
+        // if this is not an error that occurred while processing a previous error
+        if (mappedException == null || !mappedException.booleanValue()) {
+            ExceptionMapper mapper = ProviderFactory.getInstance(context)
+                    .createExceptionMapper(t.getClass(), context);
+
+            // if we find the mapper, let it handle the exception
+            if (mapper != null) {
+                Response response = null;
+                try {
+                    response = mapper.toResponse(t);
+                } catch (Throwable t2) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(mapper.getClass().getName() + ".toResponse("
+                                + t.getClass() + ") threw throwable "
+                                + t2.getClass().getName() + " with message \""
+                                + t2.getMessage() + "\"");
+                    }
+                    response = Response.status(
+                            Response.Status.INTERNAL_SERVER_ERROR).build();
+                }
+                context.setProperty(ContextConstants.RESPONSE, response);
+                context.setProperty(ContextConstants.MAPPED_EXCEPTION,
+                        Boolean.TRUE);
+                processResponse(context);
+                return true;
+            }
+
+            if (log.isDebugEnabled()) {
+                log
+                        .debug("ExceptionMapper could not be found for the throwable class: "
+                                + t.getClass());
+            }
+
+            /*
+             * need to re-throw again if there was no mapper to let the underlying container handle the "real" exception
+             */
+            if (t instanceof Exception) {
+                throw (Exception) t;
+            }
+            throw (Error) t;
+        }
+
+        // if this exception occurred serializing an exception response, just
+        // return a 500 status code
+        else if (mappedException.booleanValue()) {
+            if (log.isDebugEnabled()) {
+                log
+                        .debug("An exception was already thrown once and mapped to a response so returning a 500 Internal server error");
+            }
+
+            context.setProperty(ContextConstants.MAPPED_EXCEPTION, null);
+            context.setProperty(ContextConstants.RESPONSE, Response.status(
+                    Response.Status.INTERNAL_SERVER_ERROR).build());
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * This method will construct a String that represents a MIME type and representation
+     * class for hte MIME type. This will be used to construct a DataFlavor when dealing
+     * with the JAF layer.
+     *
+     */
+    public static String constructFlavorString(String mimeType, String className) {
+        return mimeType + ";class=" + className;
+    }
+
+    /**
+     * Determines the response's media type.
+     * @param contentType the Response object's content type
+     * @param response the actual Response object
+     * @param operation the operation resource info
+     * @param acceptContentTypes the request's Accept header media types in sorted order
+     * @return a list of media types that are acceptable
+     */
+    public static List<MediaType> computeAvailableContentTypes(String contentType, Response response, OperationResourceInfo operation, List<MediaType> acceptContentTypes) {
+        List<MediaType> produceTypes = null;
+        List<MediaType> operationProduces = (operation != null) ? operation
+                .getProduces() : null;
+        if (contentType != null) {
+            return Collections.singletonList(MediaType.valueOf(contentType
+                    .toString()));
+        } else if (operationProduces != null) {
+            produceTypes = operationProduces;
+        } else {
+            produceTypes = Collections.singletonList(MediaType.WILDCARD_TYPE);
+        }
+        List<MediaType> acceptTypes = acceptContentTypes;
+        if (acceptTypes == null) {
+            acceptTypes = Collections.singletonList(MediaType.WILDCARD_TYPE);
+        }
+        return JAXRSUtils.intersectMimeTypes(acceptTypes, produceTypes);
+
+    }
+
+    public static MediaType checkFinalContentType(MediaType mt) {
+        if (mt.isWildcardType() && mt.isWildcardSubtype()) {
+            return MediaType.APPLICATION_OCTET_STREAM_TYPE;
+        } else if ("application".equals(mt.getType())
+                && "*".equals(mt.getSubtype())) {
+            return MediaType.APPLICATION_OCTET_STREAM_TYPE;
+        } else {
+            return mt;
+        }
+    }
+
+    /**
+     * Helper method to return a ClassResourceInfo for the class name supplied by
+     * looking at all the subresources on the ClassResourceInfo list supplied.
+     *
+     */
+    public static ClassResourceInfo getSubResourceInfo(String className, List<ClassResourceInfo> classInfoList) {
+        ClassResourceInfo targetInfo = null;
+        for (ClassResourceInfo classInfo : classInfoList) {
+            List<ClassResourceInfo> subInfoList = classInfo
+                    .getSubClassResourceInfo();
+            if (subInfoList != null) {
+                for (ClassResourceInfo subResource : subInfoList) {
+                    if (subResource.getServiceClass().getName().equals(
+                            className)) {
+                        targetInfo = subResource;
+                        break;
+                    }
+                }
+            }
+        }
+        return targetInfo;
+    }
+
+    /**
+     * This is a helper method to determine the matched parts of an OperationResourceInfo
+     * objects uri template with the final matched group that is supplied.
+     *
+     */
+    public static String getPathForOperation(String finalGroup, String currentPath) {
+
+        String pathForOp = "";
+        if (finalGroup == null || finalGroup.equals("/")) {
+            pathForOp = currentPath;
+        } else if (currentPath.indexOf(finalGroup) != -1) {
+            pathForOp = currentPath.substring(0, currentPath
+                    .lastIndexOf(finalGroup));
+        }
+
+        pathForOp = removePrecedingSlash(pathForOp);
+        pathForOp = removeTrailingSlash(pathForOp);
+
+        return pathForOp;
+    }
+
+    /**
+     * This will remove a preceding '/', if one exists, from a String.
+     *
+     */
+    public static String removePrecedingSlash(String input) {
+        if (input != null && input.startsWith("/") && !input.equals("/")) {
+            return input.substring(1);
+        }
+        return input;
+    }
+
+    /**
+     * This will remove a trailing '/', if one exists, from a String.
+     *
+     */
+    public static String removeTrailingSlash(String input) {
+        if (input.endsWith("/") && !input.equals("/")) {
+            return input.substring(0, input.length() - 1);
+        }
+        return input;
+    }
+
+    public static List<ProviderInfo.Type> getProviderTypes(Class<?> providerClass) {
+        java.lang.reflect.Type[] interfaceTypes = providerClass
+                .getGenericInterfaces();
+        List<ProviderInfo.Type> providerTypes = null;
+        if (interfaceTypes != null) {
+            providerTypes = new ArrayList<ProviderInfo.Type>();
+            for (java.lang.reflect.Type interfaceType : interfaceTypes) {
+                if (interfaceType instanceof ParameterizedType) {
+                    ParameterizedType parameterizedType = (ParameterizedType) interfaceType;
+                    if (parameterizedType.getRawType() instanceof Class) {
+                        Class<?> interfaze = (Class<?>) parameterizedType
+                                .getRawType();
+
+                        // first determine the type of provider this repersents
+                        if (MessageBodyWriter.class.isAssignableFrom(interfaze)) {
+                            providerTypes
+                                    .add(ProviderInfo.Type.MessageBodyWriter);
+                        }
+                        if (MessageBodyReader.class.isAssignableFrom(interfaze)) {
+                            providerTypes
+                                    .add(ProviderInfo.Type.MessageBodyReader);
+                        }
+                        if (ContextResolver.class.isAssignableFrom(interfaze)) {
+                            providerTypes
+                                    .add(ProviderInfo.Type.ContextResolver);
+                        }
+                        if (ExceptionMapper.class.isAssignableFrom(interfaze)) {
+                            providerTypes
+                                    .add(ProviderInfo.Type.ExceptionMapper);
+                        }
+                    }
+                }
+            }
+        }
+        return providerTypes;
+    }
+
+    /*
+     * Looks for an OptionsResponseProvider based on the 'Accept' media types.
+     */
+    public static OptionsResponseProvider getOptionsResponseProvider(RESTContext context) {
+        List<MediaType> mTypes = (List<MediaType>) context
+                .getProperty(ContextConstants.ACCEPT_CONTENT_TYPES);
+        if (mTypes == null) {
+            mTypes = new ArrayList<MediaType>();
+            mTypes.add(MediaType.WILDCARD_TYPE);
+        }
+        List<OptionsResponseProvider> providers = (List<OptionsResponseProvider>) IntegrationRegistry
+                .getIntegrationProvider(
+                        context
+                                .getProperty(ContextConstants.INTEGRATION_REGISTRATION_KEY),
+                        OptionsResponseProvider.class);
+        OptionsResponseProvider provider = null;
+        if (providers != null) {
+            for (MediaType mType : mTypes) {
+                for (OptionsResponseProvider orp : providers) {
+                    if (orp.isWriteable(mType)) {
+                        provider = orp;
+                        break;
+                    }
+                }
+                if (provider != null) {
+                    break;
+                }
+            }
+        }
+        return provider;
+    }
+
+    /**
+     * Utility method to give JAX-RS app developer as much info as possible about the method being invoked
+     * @return
+     */
+    private static String getMethodInfoForErrorLog(Method method) {
+        String methodSignatureString = "UNKNOWN";
+        if (method != null) {
+            String paramTypesString = "";
+            for (int i = 0; i < method.getParameterTypes().length; i++) {
+                paramTypesString += method.getParameterTypes()[i].getName();
+                if ((i + 1) != method.getParameterTypes().length) {
+                    paramTypesString += ", ";
+                }
+            }
+            methodSignatureString = method.getDeclaringClass().getName() + "."
+                    + method.getName() + "(" + paramTypesString + ")";
+        }
+        return methodSignatureString;
+    }
+
+}



Mime
View raw message