
org.apache.cxf.jaxrs.utils.JAXRSUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cxf-bundle-jaxrs Show documentation
Show all versions of cxf-bundle-jaxrs Show documentation
Apache CXF JAX-RS Bundle Jar
/**
* 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.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.logging.Logger;
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.CookieParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
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.Response.ResponseBuilder;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
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.cxf.common.i18n.BundleUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.ext.MessageContextImpl;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
import org.apache.cxf.jaxrs.impl.HttpServletResponseFilter;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
import org.apache.cxf.jaxrs.impl.ProvidersImpl;
import org.apache.cxf.jaxrs.impl.RequestImpl;
import org.apache.cxf.jaxrs.impl.SecurityContextImpl;
import org.apache.cxf.jaxrs.impl.UriInfoImpl;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.ClassResourceInfoComparator;
import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.jaxrs.model.OperationResourceInfoComparator;
import org.apache.cxf.jaxrs.model.URITemplate;
import org.apache.cxf.jaxrs.provider.AbstractConfigurableProvider;
import org.apache.cxf.jaxrs.provider.ProviderFactory;
import org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
public final class JAXRSUtils {
public static final MediaType ALL_TYPES = new MediaType();
private static final Logger LOG = LogUtils.getL7dLogger(JAXRSUtils.class);
private static final ResourceBundle BUNDLE = BundleUtils.getBundle(JAXRSUtils.class);
private JAXRSUtils() {
}
public static List getPathSegments(String thePath, boolean decode) {
return getPathSegments(thePath, decode, true);
}
public static List getPathSegments(String thePath, boolean decode,
boolean ignoreLastSlash) {
String[] segments = thePath.split("/");
List theList = new ArrayList();
for (String path : segments) {
if (!StringUtils.isEmpty(path)) {
theList.add(new PathSegmentImpl(path, decode));
}
}
int len = thePath.length();
if (len > 0 && thePath.charAt(len - 1) == '/') {
String value = ignoreLastSlash ? "" : "/";
theList.add(new PathSegmentImpl(value, false));
}
return theList;
}
@SuppressWarnings("unchecked")
private static String[] getUserMediaTypes(Object provider, String methodName) {
String[] values = null;
if (AbstractConfigurableProvider.class.isAssignableFrom(provider.getClass())) {
try {
Method m = provider.getClass().getMethod(methodName, new Class[]{});
List types = (List)m.invoke(provider, new Object[]{});
if (types != null) {
values = types.size() > 0 ? types.toArray(new String[]{})
: new String[]{"*/*"};
}
} catch (Exception ex) {
// ignore
}
}
return values;
}
public static List getProviderConsumeTypes(MessageBodyReader provider) {
String[] values = getUserMediaTypes(provider, "getConsumeMediaTypes");
if (values == null) {
Consumes c = provider.getClass().getAnnotation(Consumes.class);
values = c == null ? new String[]{"*/*"} : c.value();
}
return JAXRSUtils.getMediaTypes(values);
}
public static List getProviderProduceTypes(MessageBodyWriter provider) {
String[] values = getUserMediaTypes(provider, "getProduceMediaTypes");
if (values == null) {
Produces c = provider.getClass().getAnnotation(Produces.class);
values = c == null ? new String[]{"*/*"} : c.value();
}
return JAXRSUtils.getMediaTypes(values);
}
public static List getMediaTypes(String[] values) {
List supportedMimeTypes = new ArrayList(values.length);
for (int i = 0; i < values.length; i++) {
supportedMimeTypes.add(MediaType.valueOf(values[i]));
}
return supportedMimeTypes;
}
@SuppressWarnings("unchecked")
public static void handleSetters(OperationResourceInfo ori,
Object requestObject,
Message message) {
ClassResourceInfo cri = ori.getClassResourceInfo();
InjectionUtils.injectContextMethods(requestObject, cri, message);
// Param methods
MultivaluedMap values =
(MultivaluedMap)message.get(URITemplate.TEMPLATE_PARAMETERS);
for (Method m : cri.getParameterMethods()) {
Object o = createHttpParameterValue(m.getAnnotations(),
m.getParameterTypes()[0],
m.getGenericParameterTypes()[0],
message,
values,
ori);
if (o != null) {
InjectionUtils.injectThroughMethod(requestObject, m, o);
}
}
// Param fields
for (Field f : cri.getParameterFields()) {
Object o = createHttpParameterValue(f.getAnnotations(),
f.getType(),
f.getGenericType(),
message,
values,
ori);
if (o != null) {
InjectionUtils.injectFieldValue(f, requestObject, o);
}
}
}
public static ClassResourceInfo selectResourceClass(List resources,
String path,
MultivaluedMap values) {
if (resources.size() == 1) {
return resources.get(0).getURITemplate().match(path, values)
? resources.get(0) : null;
}
SortedMap> candidateList =
new TreeMap>(
new ClassResourceInfoComparator());
for (ClassResourceInfo resource : resources) {
MultivaluedMap map = new MetadataMap();
if (resource.getURITemplate().match(path, map)) {
candidateList.put(resource, map);
}
}
if (!candidateList.isEmpty()) {
Map.Entry> firstEntry =
candidateList.entrySet().iterator().next();
values.putAll(firstEntry.getValue());
return firstEntry.getKey();
}
return null;
}
public static OperationResourceInfo findTargetMethod(ClassResourceInfo resource,
String path,
String httpMethod,
MultivaluedMap values,
String requestContentType,
List acceptContentTypes) {
SortedMap> candidateList =
new TreeMap>(
new OperationResourceInfoComparator());
MediaType requestType = requestContentType == null
? ALL_TYPES : MediaType.valueOf(requestContentType);
int pathMatched = 0;
int methodMatched = 0;
int consumeMatched = 0;
int produceMatched = 0;
boolean subresourcesOnly = true;
for (MediaType acceptType : acceptContentTypes) {
for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
URITemplate uriTemplate = ori.getURITemplate();
MultivaluedMap map = new MetadataMap(values);
if (uriTemplate != null && uriTemplate.match(path, map)) {
if (ori.isSubResourceLocator()) {
candidateList.put(ori, map);
} else {
String finalGroup = map.getFirst(URITemplate.FINAL_MATCH_GROUP);
if (finalGroup == null || StringUtils.isEmpty(finalGroup)
|| finalGroup.equals("/")) {
pathMatched++;
boolean mMatched = matchHttpMethod(ori.getHttpMethod(), httpMethod);
boolean cMatched = matchConsumeTypes(requestType, ori);
boolean pMatched = matchProduceTypes(acceptType, ori);
if (mMatched && cMatched && pMatched) {
subresourcesOnly = false;
candidateList.put(ori, map);
} else {
methodMatched = mMatched ? methodMatched + 1 : methodMatched;
produceMatched = pMatched ? produceMatched + 1 : produceMatched;
consumeMatched = cMatched ? consumeMatched + 1 : consumeMatched;
}
}
}
}
}
if (!candidateList.isEmpty() && !subresourcesOnly) {
break;
}
}
if (!candidateList.isEmpty()) {
Map.Entry> firstEntry =
candidateList.entrySet().iterator().next();
values.clear();
values.putAll(firstEntry.getValue());
OperationResourceInfo ori = firstEntry.getKey();
if (headMethodPossible(ori.getHttpMethod(), httpMethod)) {
LOG.info(new org.apache.cxf.common.i18n.Message("GET_INSTEAD_OF_HEAD",
BUNDLE, resource.getServiceClass().getName(),
ori.getMethodToInvoke().getName()).toString());
}
return ori;
}
int status = pathMatched == 0 ? 404 : methodMatched == 0 ? 405
: consumeMatched == 0 ? 415 : produceMatched == 0 ? 406 : 404;
String name = resource.isRoot() ? "NO_OP_EXC" : "NO_SUBRESOURCE_METHOD_FOUND";
org.apache.cxf.common.i18n.Message errorMsg =
new org.apache.cxf.common.i18n.Message(name,
BUNDLE,
path,
requestType.toString(),
convertTypesToString(acceptContentTypes));
if (!"OPTIONS".equalsIgnoreCase(httpMethod)) {
LOG.warning(errorMsg.toString());
}
ResponseBuilder rb = createResponseBuilder(resource, status, methodMatched == 0);
throw new WebApplicationException(rb.build());
}
public static ResponseBuilder createResponseBuilder(ClassResourceInfo cri, int status, boolean addAllow) {
ResponseBuilder rb = Response.status(status);
if (addAllow) {
for (String m : cri.getAllowedMethods()) {
rb.header("Allow", m);
}
}
return rb;
}
private static boolean matchHttpMethod(String expectedMethod, String httpMethod) {
if (expectedMethod.equalsIgnoreCase(httpMethod)
|| headMethodPossible(expectedMethod, httpMethod)) {
return true;
}
return false;
}
public static boolean headMethodPossible(String expectedMethod, String httpMethod) {
return "HEAD".equalsIgnoreCase(httpMethod) && "GET".equals(expectedMethod);
}
private static String convertTypesToString(List types) {
StringBuilder sb = new StringBuilder();
for (MediaType type : types) {
sb.append(type.toString()).append(',');
}
return sb.toString();
}
public static List getConsumeTypes(Consumes cm) {
return cm == null ? Collections.singletonList(ALL_TYPES)
: getMediaTypes(cm.value());
}
public static List getProduceTypes(Produces pm) {
return pm == null ? Collections.singletonList(ALL_TYPES)
: getMediaTypes(pm.value());
}
public static int compareSortedMediaTypes(List mts1, List mts2) {
int size1 = mts1.size();
int size2 = mts2.size();
for (int i = 0; i < size1 && i < size2; i++) {
int result = compareMediaTypes(mts1.get(i), mts2.get(i));
if (result != 0) {
return result;
}
}
return size1 == size2 ? 0 : size1 < size2 ? -1 : 1;
}
public static int compareMediaTypes(MediaType mt1, MediaType mt2) {
if (mt1.isWildcardType() && !mt2.isWildcardType()) {
return 1;
}
if (!mt1.isWildcardType() && mt2.isWildcardType()) {
return -1;
}
if (mt1.isWildcardSubtype() && !mt2.isWildcardSubtype()) {
return 1;
}
if (!mt1.isWildcardSubtype() && mt2.isWildcardSubtype()) {
return -1;
}
float q1 = getMediaTypeQualityFactor(mt1.getParameters().get("q"));
float q2 = getMediaTypeQualityFactor(mt2.getParameters().get("q"));
int result = Float.compare(q1, q2);
if (result != 0) {
return result * -1;
}
return 0;
}
public static float getMediaTypeQualityFactor(String q) {
if (q == null) {
return 1;
}
if (q.charAt(0) == '.') {
q = '0' + q;
}
try {
return Float.parseFloat(q);
} catch (NumberFormatException ex) {
// default value will do
}
return 1;
}
//Message contains following information: PATH, HTTP_REQUEST_METHOD, CONTENT_TYPE, InputStream.
public static List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy