Search in sources :

Example 1 with WeightedMediaType

use of org.jboss.resteasy.util.WeightedMediaType in project resteasy by resteasy.

the class SegmentNode method match.

public MatchCache match(List<Match> matches, String httpMethod, HttpRequest request) {
    MediaType contentType = request.getHttpHeaders().getMediaType();
    List<MediaType> requestAccepts = request.getHttpHeaders().getAcceptableMediaTypes();
    List<WeightedMediaType> weightedAccepts = new ArrayList<WeightedMediaType>();
    for (MediaType accept : requestAccepts) weightedAccepts.add(WeightedMediaType.parse(accept));
    List<Match> list = new ArrayList<Match>();
    boolean methodMatch = false;
    boolean consumeMatch = false;
    // make a list of all compatible ResourceMethods
    for (Match match : matches) {
        ResourceMethodInvoker invoker = (ResourceMethodInvoker) match.expression.getInvoker();
        if (invoker.getHttpMethods().contains(httpMethod.toUpperCase())) {
            methodMatch = true;
            if (invoker.doesConsume(contentType)) {
                consumeMatch = true;
                if (invoker.doesProduce(weightedAccepts)) {
                    list.add(match);
                }
            }
        }
    }
    if (list.size() == 0) {
        if (!methodMatch) {
            HashSet<String> allowed = new HashSet<String>();
            for (Match match : matches) {
                allowed.addAll(((ResourceMethodInvoker) match.expression.getInvoker()).getHttpMethods());
            }
            if (httpMethod.equalsIgnoreCase("HEAD") && allowed.contains("GET")) {
                return match(matches, "GET", request);
            }
            if (allowed.contains("GET"))
                allowed.add("HEAD");
            allowed.add("OPTIONS");
            StringBuilder allowHeaders = new StringBuilder("");
            boolean first = true;
            for (String allow : allowed) {
                if (first)
                    first = false;
                else
                    allowHeaders.append(", ");
                allowHeaders.append(allow);
            }
            String allowHeaderValue = allowHeaders.toString();
            if (httpMethod.equals("OPTIONS")) {
                ResponseBuilder resBuilder = Response.ok(allowHeaderValue.toString(), MediaType.TEXT_PLAIN_TYPE).header(HttpHeaderNames.ALLOW, allowHeaderValue.toString());
                if (allowed.contains("PATCH")) {
                    Set<MediaType> patchAccepts = new HashSet<MediaType>(8);
                    for (Match match : matches) {
                        if (((ResourceMethodInvoker) match.expression.getInvoker()).getHttpMethods().contains("PATCH")) {
                            patchAccepts.addAll(Arrays.asList(((ResourceMethodInvoker) match.expression.getInvoker()).getConsumes()));
                        }
                    }
                    StringBuilder acceptPatch = new StringBuilder("");
                    first = true;
                    for (MediaType mediaType : patchAccepts) {
                        if (first)
                            first = false;
                        else
                            acceptPatch.append(", ");
                        acceptPatch.append(mediaType.toString());
                    }
                    resBuilder.header(HttpHeaderNames.ACCEPT_PATCH, acceptPatch.toString());
                }
                throw new DefaultOptionsMethodException(Messages.MESSAGES.noResourceMethodFoundForOptions(), resBuilder.build());
            } else {
                Response res = Response.status(HttpResponseCodes.SC_METHOD_NOT_ALLOWED).header(HttpHeaderNames.ALLOW, allowHeaderValue).build();
                throw new NotAllowedException(Messages.MESSAGES.noResourceMethodFoundForHttpMethod(httpMethod), res);
            }
        } else if (!consumeMatch) {
            throw new NotSupportedException(Messages.MESSAGES.cannotConsumeContentType());
        }
        throw new NotAcceptableException(Messages.MESSAGES.noMatchForAcceptHeader());
    }
    // if (list.size() == 1) return list.get(0); //don't do this optimization as we need to set chosen accept
    List<SortEntry> sortList = new ArrayList<SortEntry>();
    for (Match match : list) {
        ResourceMethodInvoker invoker = (ResourceMethodInvoker) match.expression.getInvoker();
        if (contentType == null)
            contentType = MediaType.WILDCARD_TYPE;
        MediaType[] consumes = invoker.getConsumes();
        if (consumes.length == 0) {
            consumes = WILDCARD_ARRAY;
        }
        MediaType[] produces = invoker.getProduces();
        if (produces.length == 0) {
            produces = WILDCARD_ARRAY;
        }
        List<SortFactor> consumeCombo = new ArrayList<SortFactor>();
        for (MediaType consume : consumes) {
            consumeCombo.add(createSortFactor(contentType, consume));
        }
        for (MediaType produce : produces) {
            List<MediaType> acceptableMediaTypes = requestAccepts;
            if (acceptableMediaTypes.size() == 0) {
                acceptableMediaTypes = DEFAULT_ACCEPTS;
            }
            for (MediaType accept : acceptableMediaTypes) {
                if (accept.isCompatible(produce)) {
                    SortFactor sortFactor = createSortFactor(accept, produce);
                    for (SortFactor consume : consumeCombo) {
                        sortList.add(new SortEntry(match, consume, sortFactor, produce));
                    }
                }
            }
        }
    }
    Collections.sort(sortList);
    SortEntry sortEntry = sortList.get(0);
    String[] mm = matchingMethods(sortList);
    if (mm != null) {
        boolean isFailFast = ConfigurationFactory.getInstance().getConfiguration().getOptionalValue(ResteasyContextParameters.RESTEASY_FAIL_FAST_ON_MULTIPLE_RESOURCES_MATCHING, boolean.class).orElse(false);
        if (isFailFast) {
            throw new RuntimeException(Messages.MESSAGES.multipleMethodsMatchFailFast(requestToString(request), mm));
        } else {
            LogMessages.LOGGER.multipleMethodsMatch(requestToString(request), mm);
        }
    }
    MediaType acceptType = sortEntry.getAcceptType();
    request.setAttribute(RESTEASY_CHOSEN_ACCEPT, acceptType);
    MatchCache ctx = new MatchCache();
    ctx.chosen = acceptType;
    ctx.match = sortEntry.match;
    ctx.invoker = sortEntry.match.expression.invoker;
    return ctx;
}
Also used : NotAllowedException(jakarta.ws.rs.NotAllowedException) ArrayList(java.util.ArrayList) MediaType(jakarta.ws.rs.core.MediaType) WeightedMediaType(org.jboss.resteasy.util.WeightedMediaType) ResponseBuilder(jakarta.ws.rs.core.Response.ResponseBuilder) HashSet(java.util.HashSet) WeightedMediaType(org.jboss.resteasy.util.WeightedMediaType) DefaultOptionsMethodException(org.jboss.resteasy.spi.DefaultOptionsMethodException) ResourceMethodInvoker(org.jboss.resteasy.core.ResourceMethodInvoker) Response(jakarta.ws.rs.core.Response) NotAcceptableException(jakarta.ws.rs.NotAcceptableException) NotSupportedException(jakarta.ws.rs.NotSupportedException)

Aggregations

NotAcceptableException (jakarta.ws.rs.NotAcceptableException)1 NotAllowedException (jakarta.ws.rs.NotAllowedException)1 NotSupportedException (jakarta.ws.rs.NotSupportedException)1 MediaType (jakarta.ws.rs.core.MediaType)1 Response (jakarta.ws.rs.core.Response)1 ResponseBuilder (jakarta.ws.rs.core.Response.ResponseBuilder)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 ResourceMethodInvoker (org.jboss.resteasy.core.ResourceMethodInvoker)1 DefaultOptionsMethodException (org.jboss.resteasy.spi.DefaultOptionsMethodException)1 WeightedMediaType (org.jboss.resteasy.util.WeightedMediaType)1