Search in sources :

Example 11 with AcceptableMediaType

use of org.glassfish.jersey.message.internal.AcceptableMediaType in project jersey by jersey.

the class MethodSelectingRouter method selectMethod.

/**
     * Select method to be invoked. Method is chosen among the given set of acceptors (if they are compatible with acceptable
     * media types).
     *
     * @param acceptableMediaTypes  media types acceptable by the client.
     * @param satisfyingAcceptors   pre-computed acceptors.
     * @param effectiveContentType  media type of incoming entity.
     * @param singleInvokableMethod flag determining whether only one method to be invoked has been found among satisfying
     *                              acceptors.
     * @return method to be invoked.
     */
private MethodSelector selectMethod(final List<AcceptableMediaType> acceptableMediaTypes, final List<ConsumesProducesAcceptor> satisfyingAcceptors, final MediaType effectiveContentType, final boolean singleInvokableMethod) {
    // Selected method we have a reader and writer for.
    final MethodSelector method = new MethodSelector(null);
    // If we cannot find a writer at this point use the best alternative.
    final MethodSelector alternative = new MethodSelector(null);
    for (final MediaType acceptableMediaType : acceptableMediaTypes) {
        for (final ConsumesProducesAcceptor satisfiable : satisfyingAcceptors) {
            final CombinedMediaType produces = CombinedMediaType.create(acceptableMediaType, satisfiable.produces);
            if (produces != CombinedMediaType.NO_MATCH) {
                final CombinedMediaType consumes = CombinedMediaType.create(effectiveContentType, satisfiable.consumes);
                final RequestSpecificConsumesProducesAcceptor candidate = new RequestSpecificConsumesProducesAcceptor(consumes, produces, satisfiable.produces.isDerived(), satisfiable.methodRouting);
                if (singleInvokableMethod) {
                    // Only one possible method and it's compatible.
                    return new MethodSelector(candidate);
                } else if (candidate.compareTo(method.selected) < 0) {
                    // Candidate is better than the previous one.
                    if (method.selected == null || candidate.methodRouting.method != method.selected.methodRouting.method) {
                        // No candidate so far or better candidate.
                        if (isReadable(candidate) && isWriteable(candidate)) {
                            method.consider(candidate);
                        } else {
                            alternative.consider(candidate);
                        }
                    } else {
                        // Same resource method - better candidate, no need to compare anything else.
                        method.consider(candidate);
                    }
                }
            }
        }
    }
    return method.selected != null ? method : alternative;
}
Also used : MediaType(javax.ws.rs.core.MediaType) AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType)

Example 12 with AcceptableMediaType

use of org.glassfish.jersey.message.internal.AcceptableMediaType in project jersey by jersey.

the class MethodSelectingRouter method getMethodRouter.

private List<Router> getMethodRouter(final RequestProcessingContext context) {
    final ContainerRequest request = context.request();
    final List<ConsumesProducesAcceptor> acceptors = consumesProducesAcceptors.get(request.getMethod());
    if (acceptors == null) {
        throw new NotAllowedException(Response.status(Status.METHOD_NOT_ALLOWED).allow(consumesProducesAcceptors.keySet()).build());
    }
    final List<ConsumesProducesAcceptor> satisfyingAcceptors = new LinkedList<>();
    final Set<ResourceMethod> differentInvokableMethods = Collections.newSetFromMap(new IdentityHashMap<>());
    for (ConsumesProducesAcceptor cpi : acceptors) {
        if (cpi.isConsumable(request)) {
            satisfyingAcceptors.add(cpi);
            differentInvokableMethods.add(cpi.methodRouting.method);
        }
    }
    if (satisfyingAcceptors.isEmpty()) {
        throw new NotSupportedException();
    }
    final List<AcceptableMediaType> acceptableMediaTypes = request.getQualifiedAcceptableMediaTypes();
    final MediaType requestContentType = request.getMediaType();
    final MediaType effectiveContentType = requestContentType == null ? MediaType.WILDCARD_TYPE : requestContentType;
    final MethodSelector methodSelector = selectMethod(acceptableMediaTypes, satisfyingAcceptors, effectiveContentType, differentInvokableMethods.size() == 1);
    if (methodSelector.selected != null) {
        final RequestSpecificConsumesProducesAcceptor selected = methodSelector.selected;
        if (methodSelector.sameFitnessAcceptors != null) {
            reportMethodSelectionAmbiguity(acceptableMediaTypes, methodSelector.selected, methodSelector.sameFitnessAcceptors);
        }
        context.push(new Function<ContainerResponse, ContainerResponse>() {

            @Override
            public ContainerResponse apply(final ContainerResponse responseContext) {
                // - either there is an entity, or we are responding to a HEAD request
                if (responseContext.getMediaType() == null && ((responseContext.hasEntity() || HttpMethod.HEAD.equals(request.getMethod())))) {
                    MediaType effectiveResponseType = determineResponseMediaType(responseContext.getEntityClass(), responseContext.getEntityType(), methodSelector.selected, acceptableMediaTypes);
                    if (MediaTypes.isWildcard(effectiveResponseType)) {
                        if (effectiveResponseType.isWildcardType() || "application".equalsIgnoreCase(effectiveResponseType.getType())) {
                            effectiveResponseType = MediaType.APPLICATION_OCTET_STREAM_TYPE;
                        } else {
                            throw new NotAcceptableException();
                        }
                    }
                    responseContext.setMediaType(effectiveResponseType);
                }
                return responseContext;
            }
        });
        return selected.methodRouting.routers;
    }
    throw new NotAcceptableException();
}
Also used : NotAllowedException(javax.ws.rs.NotAllowedException) ContainerResponse(org.glassfish.jersey.server.ContainerResponse) LinkedList(java.util.LinkedList) NotAcceptableException(javax.ws.rs.NotAcceptableException) AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType) MediaType(javax.ws.rs.core.MediaType) AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType) ContainerRequest(org.glassfish.jersey.server.ContainerRequest) NotSupportedException(javax.ws.rs.NotSupportedException) ResourceMethod(org.glassfish.jersey.server.model.ResourceMethod)

Example 13 with AcceptableMediaType

use of org.glassfish.jersey.message.internal.AcceptableMediaType in project jersey by jersey.

the class MethodSelectingRouter method determineResponseMediaType.

/**
     * Determine the {@link MediaType} of the {@link Response} based on writers suitable for the given entity class,
     * pre-selected method and acceptable media types.
     *
     * @param entityClass          entity class to determine the media type for.
     * @param entityType           entity type for writers.
     * @param selectedMethod       pre-selected (invoked) method.
     * @param acceptableMediaTypes acceptable media types from request.
     * @return media type of the response.
     */
private MediaType determineResponseMediaType(final Class<?> entityClass, final Type entityType, final RequestSpecificConsumesProducesAcceptor selectedMethod, final List<AcceptableMediaType> acceptableMediaTypes) {
    // Return pre-selected MediaType.
    if (usePreSelectedMediaType(selectedMethod, acceptableMediaTypes)) {
        return selectedMethod.produces.combinedType;
    }
    final ResourceMethod resourceMethod = selectedMethod.methodRouting.method;
    final Invocable invocable = resourceMethod.getInvocable();
    // Entity class can be null when considering HEAD method || empty entity.
    final Class<?> responseEntityClass = entityClass == null ? invocable.getRawRoutingResponseType() : entityClass;
    final Method handlingMethod = invocable.getHandlingMethod();
    // Media types producible by method.
    final List<MediaType> methodProducesTypes = !resourceMethod.getProducedTypes().isEmpty() ? resourceMethod.getProducedTypes() : Collections.singletonList(MediaType.WILDCARD_TYPE);
    // Applicable entity providers
    final List<WriterModel> writersForEntityType = workers.getWritersModelsForType(responseEntityClass);
    CombinedMediaType selected = null;
    for (final MediaType acceptableMediaType : acceptableMediaTypes) {
        for (final MediaType methodProducesType : methodProducesTypes) {
            if (!acceptableMediaType.isCompatible(methodProducesType)) {
                // no need to go deeper if acceptable and method produces type are incompatible
                continue;
            }
            // Use writers suitable for entity class to determine the media type.
            for (final WriterModel model : writersForEntityType) {
                for (final MediaType writerProduces : model.declaredTypes()) {
                    if (!writerProduces.isCompatible(acceptableMediaType) || !methodProducesType.isCompatible(writerProduces)) {
                        continue;
                    }
                    final CombinedMediaType.EffectiveMediaType effectiveProduces = new CombinedMediaType.EffectiveMediaType(MediaTypes.mostSpecific(methodProducesType, writerProduces), false);
                    final CombinedMediaType candidate = CombinedMediaType.create(acceptableMediaType, effectiveProduces);
                    if (candidate != CombinedMediaType.NO_MATCH) {
                        // Look for a better compatible worker.
                        if (selected == null || CombinedMediaType.COMPARATOR.compare(candidate, selected) < 0) {
                            if (model.isWriteable(responseEntityClass, entityType, handlingMethod.getDeclaredAnnotations(), candidate.combinedType)) {
                                selected = candidate;
                            }
                        }
                    }
                }
            }
        }
    }
    // Found media type for current writer.
    if (selected != null) {
        return selected.combinedType;
    }
    // so it can be written.
    return selectedMethod.produces.combinedType;
}
Also used : Invocable(org.glassfish.jersey.server.model.Invocable) WriterModel(org.glassfish.jersey.message.WriterModel) MediaType(javax.ws.rs.core.MediaType) AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType) HttpMethod(javax.ws.rs.HttpMethod) ResourceMethod(org.glassfish.jersey.server.model.ResourceMethod) Method(java.lang.reflect.Method) ResourceMethod(org.glassfish.jersey.server.model.ResourceMethod)

Example 14 with AcceptableMediaType

use of org.glassfish.jersey.message.internal.AcceptableMediaType in project jersey by jersey.

the class AcceptMediaTypeProviderTest method testOneMediaTypeWithParameters.

@Test
public void testOneMediaTypeWithParameters() throws Exception {
    String header = "application/xml;charset=utf8";
    List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
    assertEquals(1, l.size());
    MediaType m = l.get(0);
    assertEquals("application", m.getType());
    assertEquals("xml", m.getSubtype());
    assertEquals(1, m.getParameters().size());
    assertTrue(m.getParameters().containsKey("charset"));
    assertEquals("utf8", m.getParameters().get("charset"));
}
Also used : AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType) MediaType(javax.ws.rs.core.MediaType) AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType) Test(org.junit.Test)

Example 15 with AcceptableMediaType

use of org.glassfish.jersey.message.internal.AcceptableMediaType in project jersey by jersey.

the class AcceptMediaTypeProviderTest method testMediaTypeSpecifityHTTPExample1.

@Test
public void testMediaTypeSpecifityHTTPExample1() throws Exception {
    String header = "text/*, text/html, text/html;level=1, */*";
    List<AcceptableMediaType> l = HttpHeaderReader.readAcceptMediaType(header);
    MediaType m;
    m = l.get(0);
    assertEquals("text", m.getType());
    assertEquals("html", m.getSubtype());
    assertEquals(0, m.getParameters().size());
    m = l.get(1);
    assertEquals("text", m.getType());
    assertEquals("html", m.getSubtype());
    assertEquals(1, m.getParameters().size());
    m = l.get(2);
    assertEquals("text", m.getType());
    assertEquals("*", m.getSubtype());
    assertEquals(0, m.getParameters().size());
    m = l.get(3);
    assertEquals("*", m.getType());
    assertEquals("*", m.getSubtype());
    assertEquals(0, m.getParameters().size());
}
Also used : AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType) MediaType(javax.ws.rs.core.MediaType) AcceptableMediaType(org.glassfish.jersey.message.internal.AcceptableMediaType) Test(org.junit.Test)

Aggregations

MediaType (javax.ws.rs.core.MediaType)17 AcceptableMediaType (org.glassfish.jersey.message.internal.AcceptableMediaType)17 Test (org.junit.Test)14 ResourceMethod (org.glassfish.jersey.server.model.ResourceMethod)2 Method (java.lang.reflect.Method)1 LinkedList (java.util.LinkedList)1 HttpMethod (javax.ws.rs.HttpMethod)1 NotAcceptableException (javax.ws.rs.NotAcceptableException)1 NotAllowedException (javax.ws.rs.NotAllowedException)1 NotSupportedException (javax.ws.rs.NotSupportedException)1 WriterModel (org.glassfish.jersey.message.WriterModel)1 ContainerRequest (org.glassfish.jersey.server.ContainerRequest)1 ContainerResponse (org.glassfish.jersey.server.ContainerResponse)1 Invocable (org.glassfish.jersey.server.model.Invocable)1