use of javax.ws.rs.core.MultivaluedHashMap in project jersey by jersey.
the class WebResourceFactory method invoke.
@Override
@SuppressWarnings("unchecked")
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if (args == null && method.getName().equals("toString")) {
return toString();
}
if (args == null && method.getName().equals("hashCode")) {
//unique instance in the JVM, and no need to override
return hashCode();
}
if (args != null && args.length == 1 && method.getName().equals("equals")) {
//unique instance in the JVM, and no need to override
return equals(args[0]);
}
// get the interface describing the resource
final Class<?> proxyIfc = proxy.getClass().getInterfaces()[0];
// response type
final Class<?> responseType = method.getReturnType();
// determine method name
String httpMethod = getHttpMethodName(method);
if (httpMethod == null) {
for (final Annotation ann : method.getAnnotations()) {
httpMethod = getHttpMethodName(ann.annotationType());
if (httpMethod != null) {
break;
}
}
}
// create a new UriBuilder appending the @Path attached to the method
WebTarget newTarget = addPathFromAnnotation(method, target);
if (httpMethod == null) {
if (newTarget == target) {
// no path annotation on the method -> fail
throw new UnsupportedOperationException("Not a resource method.");
} else if (!responseType.isInterface()) {
// not interface - can't help here
throw new UnsupportedOperationException("Return type not an interface");
}
}
// process method params (build maps of (Path|Form|Cookie|Matrix|Header..)Params
// and extract entity type
final MultivaluedHashMap<String, Object> headers = new MultivaluedHashMap<String, Object>(this.headers);
final LinkedList<Cookie> cookies = new LinkedList<>(this.cookies);
final Form form = new Form();
form.asMap().putAll(this.form.asMap());
final Annotation[][] paramAnns = method.getParameterAnnotations();
Object entity = null;
Type entityType = null;
for (int i = 0; i < paramAnns.length; i++) {
final Map<Class, Annotation> anns = new HashMap<>();
for (final Annotation ann : paramAnns[i]) {
anns.put(ann.annotationType(), ann);
}
Annotation ann;
Object value = args[i];
if (!hasAnyParamAnnotation(anns)) {
entityType = method.getGenericParameterTypes()[i];
entity = value;
} else {
if (value == null && (ann = anns.get(DefaultValue.class)) != null) {
value = ((DefaultValue) ann).value();
}
if (value != null) {
if ((ann = anns.get(PathParam.class)) != null) {
newTarget = newTarget.resolveTemplate(((PathParam) ann).value(), value);
} else if ((ann = anns.get((QueryParam.class))) != null) {
if (value instanceof Collection) {
newTarget = newTarget.queryParam(((QueryParam) ann).value(), convert((Collection) value));
} else {
newTarget = newTarget.queryParam(((QueryParam) ann).value(), value);
}
} else if ((ann = anns.get((HeaderParam.class))) != null) {
if (value instanceof Collection) {
headers.addAll(((HeaderParam) ann).value(), convert((Collection) value));
} else {
headers.addAll(((HeaderParam) ann).value(), value);
}
} else if ((ann = anns.get((CookieParam.class))) != null) {
final String name = ((CookieParam) ann).value();
Cookie c;
if (value instanceof Collection) {
for (final Object v : ((Collection) value)) {
if (!(v instanceof Cookie)) {
c = new Cookie(name, v.toString());
} else {
c = (Cookie) v;
if (!name.equals(((Cookie) v).getName())) {
// is this the right thing to do? or should I fail? or ignore the difference?
c = new Cookie(name, c.getValue(), c.getPath(), c.getDomain(), c.getVersion());
}
}
cookies.add(c);
}
} else {
if (!(value instanceof Cookie)) {
cookies.add(new Cookie(name, value.toString()));
} else {
c = (Cookie) value;
if (!name.equals(((Cookie) value).getName())) {
// is this the right thing to do? or should I fail? or ignore the difference?
cookies.add(new Cookie(name, c.getValue(), c.getPath(), c.getDomain(), c.getVersion()));
}
}
}
} else if ((ann = anns.get((MatrixParam.class))) != null) {
if (value instanceof Collection) {
newTarget = newTarget.matrixParam(((MatrixParam) ann).value(), convert((Collection) value));
} else {
newTarget = newTarget.matrixParam(((MatrixParam) ann).value(), value);
}
} else if ((ann = anns.get((FormParam.class))) != null) {
if (value instanceof Collection) {
for (final Object v : ((Collection) value)) {
form.param(((FormParam) ann).value(), v.toString());
}
} else {
form.param(((FormParam) ann).value(), value.toString());
}
}
}
}
}
if (httpMethod == null) {
// the method is a subresource locator
return WebResourceFactory.newResource(responseType, newTarget, true, headers, cookies, form);
}
// accepted media types
Produces produces = method.getAnnotation(Produces.class);
if (produces == null) {
produces = proxyIfc.getAnnotation(Produces.class);
}
final String[] accepts = (produces == null) ? EMPTY : produces.value();
// determine content type
String contentType = null;
if (entity != null) {
final List<Object> contentTypeEntries = headers.get(HttpHeaders.CONTENT_TYPE);
if ((contentTypeEntries != null) && (!contentTypeEntries.isEmpty())) {
contentType = contentTypeEntries.get(0).toString();
} else {
Consumes consumes = method.getAnnotation(Consumes.class);
if (consumes == null) {
consumes = proxyIfc.getAnnotation(Consumes.class);
}
if (consumes != null && consumes.value().length > 0) {
contentType = consumes.value()[0];
}
}
}
Invocation.Builder builder = newTarget.request().headers(// this resets all headers so do this first
headers).accept(// if @Produces is defined, propagate values into Accept header; empty array is NO-OP
accepts);
for (final Cookie c : cookies) {
builder = builder.cookie(c);
}
final Object result;
if (entity == null && !form.asMap().isEmpty()) {
entity = form;
contentType = MediaType.APPLICATION_FORM_URLENCODED;
} else {
if (contentType == null) {
contentType = MediaType.APPLICATION_OCTET_STREAM;
}
if (!form.asMap().isEmpty()) {
if (entity instanceof Form) {
((Form) entity).asMap().putAll(form.asMap());
} else {
// TODO: should at least log some warning here
}
}
}
final GenericType responseGenericType = new GenericType(method.getGenericReturnType());
if (entity != null) {
if (entityType instanceof ParameterizedType) {
entity = new GenericEntity(entity, entityType);
}
result = builder.method(httpMethod, Entity.entity(entity, contentType), responseGenericType);
} else {
result = builder.method(httpMethod, responseGenericType);
}
return result;
}
use of javax.ws.rs.core.MultivaluedHashMap in project jersey by jersey.
the class ApplicationHandler method filterNameBound.
/**
* Takes collection of all filters/interceptors (either request/reader or response/writer)
* and separates out all name-bound filters/interceptors, returns them as a separate MultivaluedMap,
* mapping the name-bound annotation to the list of name-bound filters/interceptors. The same key values
* are also added into the inverse map passed in {@code inverseNameBoundMap}.
* <p/>
* Note, the name-bound filters/interceptors are removed from the original filters/interceptors collection.
* If non-null collection is passed in the postMatching parameter (applicable for filters only),
* this method also removes all the global
* postMatching filters from the original collection and adds them to the collection passed in the postMatching
* parameter.
*
* @param all Collection of all filters to be processed.
* @param preMatchingFilters Collection into which pre-matching filters should be added.
* @param componentBag Component bag
* @param applicationNameBindings Collection of name binding annotations attached to the JAX-RS application.
* @param inverseNameBoundMap Inverse name bound map into which the name bound providers should be inserted. The keys
* are providers (filters, interceptor)
* @return {@link MultivaluedMap} of all name-bound filters.
*/
private static <T> MultivaluedMap<Class<? extends Annotation>, RankedProvider<T>> filterNameBound(final Iterable<RankedProvider<T>> all, final Collection<RankedProvider<ContainerRequestFilter>> preMatchingFilters, final ComponentBag componentBag, final Collection<Class<? extends Annotation>> applicationNameBindings, final MultivaluedMap<RankedProvider<T>, Class<? extends Annotation>> inverseNameBoundMap) {
final MultivaluedMap<Class<? extends Annotation>, RankedProvider<T>> result = new MultivaluedHashMap<>();
for (final Iterator<RankedProvider<T>> it = all.iterator(); it.hasNext(); ) {
final RankedProvider<T> provider = it.next();
Class<?> providerClass = provider.getProvider().getClass();
final Set<Type> contractTypes = provider.getContractTypes();
if (contractTypes != null && !contractTypes.contains(providerClass)) {
providerClass = ReflectionHelper.theMostSpecificTypeOf(contractTypes);
}
ContractProvider model = componentBag.getModel(providerClass);
if (model == null) {
// the provider was (most likely) bound in HK2 externally
model = ComponentBag.modelFor(providerClass);
}
final boolean preMatching = providerClass.getAnnotation(PreMatching.class) != null;
if (preMatching && preMatchingFilters != null) {
it.remove();
preMatchingFilters.add(new RankedProvider<>((ContainerRequestFilter) provider.getProvider(), model.getPriority(ContainerRequestFilter.class)));
}
boolean nameBound = model.isNameBound();
if (nameBound && !applicationNameBindings.isEmpty() && applicationNameBindings.containsAll(model.getNameBindings())) {
// override the name-bound flag
nameBound = false;
}
if (nameBound) {
// not application-bound
if (!preMatching) {
it.remove();
for (final Class<? extends Annotation> binding : model.getNameBindings()) {
result.add(binding, provider);
inverseNameBoundMap.add(provider, binding);
}
} else {
LOGGER.warning(LocalizationMessages.PREMATCHING_ALSO_NAME_BOUND(providerClass));
}
}
}
return result;
}
use of javax.ws.rs.core.MultivaluedHashMap in project jersey by jersey.
the class RequestUtil method getEntityParameters.
/**
* Returns the form parameters from a request entity as a multi-valued map.
* If the request does not have a POST method, or the media type is not
* x-www-form-urlencoded, then null is returned.
*
* @param request the client request containing the entity to extract parameters from.
* @return a {@link javax.ws.rs.core.MultivaluedMap} containing the entity form parameters.
*/
@SuppressWarnings("unchecked")
public static MultivaluedMap<String, String> getEntityParameters(ClientRequestContext request, MessageBodyWorkers messageBodyWorkers) {
Object entity = request.getEntity();
String method = request.getMethod();
MediaType mediaType = request.getMediaType();
// no entity, not a post or not x-www-form-urlencoded: return empty map
if (entity == null || method == null || !HttpMethod.POST.equalsIgnoreCase(method) || mediaType == null || !mediaType.equals(MediaType.APPLICATION_FORM_URLENCODED_TYPE)) {
return new MultivaluedHashMap<String, String>();
}
// it's ready to go if already expressed as a multi-valued map
if (entity instanceof MultivaluedMap) {
return (MultivaluedMap<String, String>) entity;
}
Type entityType = entity.getClass();
// if the entity is generic, get specific type and class
if (entity instanceof GenericEntity) {
final GenericEntity generic = (GenericEntity) entity;
// overwrite
entityType = generic.getType();
entity = generic.getEntity();
}
final Class entityClass = entity.getClass();
ByteArrayOutputStream out = new ByteArrayOutputStream();
MessageBodyWriter writer = messageBodyWorkers.getMessageBodyWriter(entityClass, entityType, EMPTY_ANNOTATIONS, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
try {
writer.writeTo(entity, entityClass, entityType, EMPTY_ANNOTATIONS, MediaType.APPLICATION_FORM_URLENCODED_TYPE, null, out);
} catch (WebApplicationException wae) {
throw new IllegalStateException(wae);
} catch (IOException ioe) {
throw new IllegalStateException(ioe);
}
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
MessageBodyReader reader = messageBodyWorkers.getMessageBodyReader(MultivaluedMap.class, MultivaluedMap.class, EMPTY_ANNOTATIONS, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
try {
return (MultivaluedMap<String, String>) reader.readFrom(MultivaluedMap.class, MultivaluedMap.class, EMPTY_ANNOTATIONS, MediaType.APPLICATION_FORM_URLENCODED_TYPE, null, in);
} catch (IOException ioe) {
throw new IllegalStateException(ioe);
}
}
use of javax.ws.rs.core.MultivaluedHashMap in project jersey by jersey.
the class RequestTokenResource method postReqTokenRequest.
/**
* POST method for creating a request for a Request Token.
*
* @return an HTTP response with content of the updated or created resource.
*/
@POST
@Consumes("application/x-www-form-urlencoded")
@Produces("application/x-www-form-urlencoded")
@TokenResource
public Response postReqTokenRequest() {
OAuthServerRequest request = new OAuthServerRequest(requestContext);
OAuth1Parameters params = new OAuth1Parameters();
params.readRequest(request);
String tok = params.getToken();
if ((tok != null) && (!tok.contentEquals(""))) {
throw new OAuth1Exception(Response.Status.BAD_REQUEST, null);
}
String consKey = params.getConsumerKey();
if (consKey == null) {
throw new OAuth1Exception(Response.Status.BAD_REQUEST, null);
}
OAuth1Consumer consumer = provider.getConsumer(consKey);
if (consumer == null) {
throw new OAuth1Exception(Response.Status.BAD_REQUEST, null);
}
OAuth1Secrets secrets = new OAuth1Secrets().consumerSecret(consumer.getSecret()).tokenSecret("");
boolean sigIsOk = false;
try {
sigIsOk = oAuth1Signature.verify(request, params, secrets);
} catch (OAuth1SignatureException ex) {
Logger.getLogger(RequestTokenResource.class.getName()).log(Level.SEVERE, null, ex);
}
if (!sigIsOk) {
throw new OAuth1Exception(Response.Status.BAD_REQUEST, null);
}
MultivaluedMap<String, String> parameters = new MultivaluedHashMap<String, String>();
for (String n : request.getParameterNames()) {
parameters.put(n, request.getParameterValues(n));
}
OAuth1Token rt = provider.newRequestToken(consKey, params.getCallback(), parameters);
Form resp = new Form();
resp.param(OAuth1Parameters.TOKEN, rt.getToken());
resp.param(OAuth1Parameters.TOKEN_SECRET, rt.getSecret());
resp.param(OAuth1Parameters.CALLBACK_CONFIRMED, "true");
return Response.ok(resp).build();
}
use of javax.ws.rs.core.MultivaluedHashMap in project jersey by jersey.
the class HttpAuthenticationFilter method repeatRequest.
/**
* Repeat the {@code request} with provided {@code newAuthorizationHeader}
* and update the {@code response} with newest response data.
*
* @param request Request context.
* @param response Response context (will be updated with the new response data).
* @param newAuthorizationHeader {@code Authorization} header that should be added to the new request.
* @return {@code true} is the authentication was successful ({@code true} if 401 response code was not returned;
* {@code false} otherwise).
*/
static boolean repeatRequest(ClientRequestContext request, ClientResponseContext response, String newAuthorizationHeader) {
Client client = request.getClient();
String method = request.getMethod();
MediaType mediaType = request.getMediaType();
URI lUri = request.getUri();
WebTarget resourceTarget = client.target(lUri);
Invocation.Builder builder = resourceTarget.request(mediaType);
MultivaluedMap<String, Object> newHeaders = new MultivaluedHashMap<String, Object>();
for (Map.Entry<String, List<Object>> entry : request.getHeaders().entrySet()) {
if (HttpHeaders.AUTHORIZATION.equals(entry.getKey())) {
continue;
}
newHeaders.put(entry.getKey(), entry.getValue());
}
newHeaders.add(HttpHeaders.AUTHORIZATION, newAuthorizationHeader);
builder.headers(newHeaders);
builder.property(REQUEST_PROPERTY_FILTER_REUSED, "true");
Invocation invocation;
if (request.getEntity() == null) {
invocation = builder.build(method);
} else {
invocation = builder.build(method, Entity.entity(request.getEntity(), request.getMediaType()));
}
Response nextResponse = invocation.invoke();
if (nextResponse.hasEntity()) {
response.setEntityStream(nextResponse.readEntity(InputStream.class));
}
MultivaluedMap<String, String> headers = response.getHeaders();
headers.clear();
headers.putAll(nextResponse.getStringHeaders());
response.setStatus(nextResponse.getStatus());
return response.getStatus() != Response.Status.UNAUTHORIZED.getStatusCode();
}
Aggregations