You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2021/04/30 09:00:17 UTC

[tomee-jakarta] 02/03: TOMEE-3187 jaxrs.spec.provider.standardnotnull clientDataSourceProviderTest

This is an automated email from the ASF dual-hosted git repository.

dblevins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-jakarta.git

commit 33415ca9cef1054d21f483f111a1adba6f7029b8
Author: David Blevins <da...@gmail.com>
AuthorDate: Fri Apr 30 01:56:37 2021 -0700

    TOMEE-3187 jaxrs.spec.provider.standardnotnull clientDataSourceProviderTest
---
 .../org/apache/cxf/jaxrs/impl/ResponseImpl.java    | 629 +++++++++++++++++++++
 .../org/apache/cxf/jaxrs/utils/JAXRSUtils.java     |  69 +--
 2 files changed, 664 insertions(+), 34 deletions(-)

diff --git a/transform/src/patch/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java b/transform/src/patch/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
new file mode 100644
index 0000000..e240f50
--- /dev/null
+++ b/transform/src/patch/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
@@ -0,0 +1,629 @@
+/**
+ * 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.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.ResponseProcessingException;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.NoContentException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status.Family;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.Source;
+
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.io.ReaderInputStream;
+import org.apache.cxf.jaxrs.provider.ProviderFactory;
+import org.apache.cxf.jaxrs.utils.HttpUtils;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
+
+public final class ResponseImpl extends Response {
+
+    private static final Pattern LINK_DELIMITER = Pattern.compile(",\\s*(?=\\<|$)");
+
+    private StatusType status;
+    private Object entity;
+    private Annotation[] entityAnnotations;
+    private MultivaluedMap<String, Object> metadata;
+
+    private Message outMessage;
+    private boolean entityClosed;
+    private boolean entityBufferred;
+    private Object lastEntity;
+
+    ResponseImpl(int statusCode) {
+        this.status = createStatusType(statusCode, null);
+    }
+
+    ResponseImpl(int statusCode, Object entity) {
+        this(statusCode);
+        this.entity = entity;
+    }
+
+    ResponseImpl(int statusCode, Object entity, String reasonPhrase) {
+        this.status = createStatusType(statusCode, reasonPhrase);
+        this.entity = entity;
+    }
+
+    public void addMetadata(MultivaluedMap<String, Object> meta) {
+        this.metadata = meta;
+    }
+
+    public void setStatus(int statusCode) {
+        this.status = createStatusType(statusCode, null);
+    }
+
+    public void setStatus(int statusCode, String reasonPhrase) {
+        this.status = createStatusType(statusCode, reasonPhrase);
+    }
+
+    public void setEntity(Object e, Annotation[] anns) {
+        this.entity = e;
+        this.entityAnnotations = anns;
+    }
+
+    public void setEntityAnnotations(Annotation[] anns) {
+        this.entityAnnotations = anns;
+    }
+
+    public Annotation[] getEntityAnnotations() {
+        return entityAnnotations;
+    }
+
+    public void setOutMessage(Message message) {
+        this.outMessage = message;
+    }
+
+    public Message getOutMessage() {
+        return this.outMessage;
+    }
+
+    @Override
+    public int getStatus() {
+        return status.getStatusCode();
+    }
+
+    @Override
+    public StatusType getStatusInfo() {
+        return status;
+    }
+
+    public Object getActualEntity() {
+        checkEntityIsClosed();
+        return lastEntity != null ? lastEntity : entity;
+    }
+
+    @Override
+    public Object getEntity() {
+        return InjectionUtils.getEntity(getActualEntity());
+    }
+
+    @Override
+    public boolean hasEntity() {
+        // per spec, need to check if the stream exists and if it has data.
+        Object actualEntity = getActualEntity();
+        if (actualEntity == null) {
+            return false;
+        } else if (actualEntity instanceof InputStream) {
+            final InputStream is = (InputStream) actualEntity;
+            try {
+                if (is.markSupported()) {
+                    is.mark(1);
+                    int i = is.read();
+                    is.reset();
+                    return i != -1;
+                } else {
+                    try {
+                        if (is.available() > 0) {
+                            return true;
+                        }
+                    } catch (IOException ioe) {
+                        //Do nothing
+                    }
+                    int b = is.read();
+                    if (b == -1) {
+                        return false;
+                    }
+                    PushbackInputStream pbis;
+                    if (is instanceof PushbackInputStream) {
+                        pbis = (PushbackInputStream) is;
+                    } else {
+                        pbis = new PushbackInputStream(is, 1);
+                        if (lastEntity != null) {
+                            lastEntity = pbis;
+                        } else {
+                            entity = pbis;
+                        }
+                    }
+                    pbis.unread(b);
+                    return true;
+                }
+            } catch (IOException ex) {
+                throw new ProcessingException(ex);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public MultivaluedMap<String, Object> getMetadata() {
+        return getHeaders();
+    }
+
+    @Override
+    public MultivaluedMap<String, Object> getHeaders() {
+        return metadata;
+    }
+
+    @Override
+    public MultivaluedMap<String, String> getStringHeaders() {
+        MetadataMap<String, String> headers = new MetadataMap<>(metadata.size());
+        for (Map.Entry<String, List<Object>> entry : metadata.entrySet()) {
+            String headerName = entry.getKey();
+            headers.put(headerName, toListOfStrings(entry.getValue()));
+        }
+        return headers;
+    }
+
+    @Override
+    public String getHeaderString(String header) {
+        List<Object> methodValues = metadata.get(header);
+        return HttpUtils.getHeaderString(toListOfStrings(methodValues));
+    }
+
+    // This conversion is needed as some values may not be Strings
+    private List<String> toListOfStrings(List<Object> values) {
+        if (values == null) {
+            return null;
+        }
+        List<String> stringValues = new ArrayList<>(values.size());
+        HeaderDelegate<Object> hd = HttpUtils.getHeaderDelegate(values.get(0));
+        for (Object value : values) {
+            String actualValue = hd == null ? value.toString() : hd.toString(value);
+            stringValues.add(actualValue);
+        }
+        return stringValues;
+    }
+
+    @Override
+    public Set<String> getAllowedMethods() {
+        List<Object> methodValues = metadata.get(HttpHeaders.ALLOW);
+        if (methodValues == null) {
+            return Collections.emptySet();
+        }
+        Set<String> methods = new HashSet<>();
+        for (Object o : methodValues) {
+            methods.add(o.toString());
+        }
+        return methods;
+    }
+
+    @Override
+    public Map<String, NewCookie> getCookies() {
+        List<Object> cookieValues = metadata.get(HttpHeaders.SET_COOKIE);
+        if (cookieValues == null) {
+            return Collections.emptyMap();
+        }
+        Map<String, NewCookie> cookies = new HashMap<>();
+        for (Object o : cookieValues) {
+            NewCookie newCookie = NewCookie.valueOf(o.toString());
+            cookies.put(newCookie.getName(), newCookie);
+        }
+        return cookies;
+    }
+
+    @Override
+    public Date getDate() {
+        return doGetDate(HttpHeaders.DATE);
+    }
+
+    private Date doGetDate(String dateHeader) {
+        Object value = metadata.getFirst(dateHeader);
+        return value == null || value instanceof Date ? (Date)value
+            : HttpUtils.getHttpDate(value.toString());
+    }
+
+    @Override
+    public EntityTag getEntityTag() {
+        Object header = metadata.getFirst(HttpHeaders.ETAG);
+        return header == null || header instanceof EntityTag ? (EntityTag)header
+            : EntityTag.valueOf(header.toString());
+    }
+
+    @Override
+    public Locale getLanguage() {
+        Object header = metadata.getFirst(HttpHeaders.CONTENT_LANGUAGE);
+        return header == null || header instanceof Locale ? (Locale)header
+            : HttpUtils.getLocale(header.toString());
+    }
+
+    @Override
+    public Date getLastModified() {
+        return doGetDate(HttpHeaders.LAST_MODIFIED);
+    }
+
+    @Override
+    public int getLength() {
+        Object header = metadata.getFirst(HttpHeaders.CONTENT_LENGTH);
+        return HttpUtils.getContentLength(header == null ? null : header.toString());
+    }
+
+    @Override
+    public URI getLocation() {
+        Object header = metadata.getFirst(HttpHeaders.LOCATION);
+        return header == null || header instanceof URI ? (URI)header
+            : URI.create(header.toString());
+    }
+
+    @Override
+    public MediaType getMediaType() {
+        Object header = metadata.getFirst(HttpHeaders.CONTENT_TYPE);
+        return header == null || header instanceof MediaType ? (MediaType)header
+            : (MediaType)JAXRSUtils.toMediaType(header.toString());
+    }
+
+    @Override
+    public boolean hasLink(String relation) {
+        List<Object> linkValues = metadata.get(HttpHeaders.LINK);
+        if (linkValues != null) {
+            for (Object o : linkValues) {
+                if (o instanceof Link && relation.equals(((Link)o).getRel())) {
+                    return true;
+                }
+
+                String[] links = LINK_DELIMITER.split(o.toString());
+                for (String splitLink : links) {
+                    Link link = Link.valueOf(splitLink);
+                    if (relation.equals(link.getRel())) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Link getLink(String relation) {
+        Set<Link> links = getAllLinks();
+        for (Link link : links) {
+            if (link.getRel() != null && link.getRel().equals(relation)) {
+                return link;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Link.Builder getLinkBuilder(String relation) {
+        Link link = getLink(relation);
+        return link == null ? null : Link.fromLink(link);
+    }
+
+    @Override
+    public Set<Link> getLinks() {
+        return new HashSet<>(getAllLinks());
+    }
+
+    private Set<Link> getAllLinks() {
+        List<Object> linkValues = metadata.get(HttpHeaders.LINK);
+        if (linkValues == null) {
+            return Collections.emptySet();
+        }
+        Set<Link> links = new LinkedHashSet<>();
+        for (Object o : linkValues) {
+            List<Link> parsedLinks = parseLink(o);
+
+            links.addAll(parsedLinks);
+        }
+        return links;
+    }
+
+    private Link makeAbsoluteLink(Link link) {
+        if (!link.getUri().isAbsolute()) {
+            URI requestURI = URI.create((String)outMessage.get(Message.REQUEST_URI));
+            link = Link.fromLink(link).baseUri(requestURI).build();
+        }
+
+        return link;
+    }
+
+    private List<Link> parseLink(Object o) {
+        if (o instanceof Link) {
+            return Collections.singletonList(makeAbsoluteLink((Link) o));
+        }
+
+        List<Link> links = new ArrayList<>();
+        String[] linkArray = LINK_DELIMITER.split(o.toString());
+
+        for (String textLink : linkArray) {
+            Link link = Link.valueOf(textLink);
+            links.add(makeAbsoluteLink(link));
+        }
+
+        return Collections.unmodifiableList(links);
+    }
+
+    @Override
+    public <T> T readEntity(Class<T> cls) throws ProcessingException, IllegalStateException {
+        return readEntity(cls, new Annotation[]{});
+    }
+
+    @Override
+    public <T> T readEntity(GenericType<T> genType) throws ProcessingException, IllegalStateException {
+        return readEntity(genType, new Annotation[]{});
+    }
+
+    @Override
+    public <T> T readEntity(Class<T> cls, Annotation[] anns) throws ProcessingException, IllegalStateException {
+        return doReadEntity(cls, cls, anns);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T readEntity(GenericType<T> genType, Annotation[] anns)
+        throws ProcessingException, IllegalStateException {
+        return doReadEntity((Class<T>) genType.getRawType(),
+                            genType.getType(), anns);
+    }
+
+    public <T> T doReadEntity(Class<T> cls, Type t, Annotation[] anns)
+        throws ProcessingException, IllegalStateException {
+
+        checkEntityIsClosed();
+        //according to javadoc, should close when is not buffered.
+        boolean shouldClose = !entityBufferred && !JAXRSUtils.isStreamingOutType(cls);
+
+        if (lastEntity != null && cls.isAssignableFrom(lastEntity.getClass())
+            && !(lastEntity instanceof InputStream)) {
+            return cls.cast(lastEntity);
+        }
+
+        MediaType mediaType = getMediaType();
+        if (mediaType == null) {
+            mediaType = MediaType.WILDCARD_TYPE;
+        }
+
+        // the stream is available if entity is IS or
+        // message contains XMLStreamReader or Reader
+        boolean entityStreamAvailable = entityStreamAvailable();
+        InputStream entityStream = null;
+        if (!entityStreamAvailable) {
+            // try create a stream if the entity is String or Number
+            entityStream = convertEntityToStreamIfPossible();
+            entityStreamAvailable = entityStream != null;
+        } else if (entity instanceof InputStream) {
+            entityStream = InputStream.class.cast(entity);
+        } else {
+            Message inMessage = getResponseMessage();
+            Reader reader = inMessage.getContent(Reader.class);
+            if (reader != null) {
+                entityStream = InputStream.class.cast(new ReaderInputStream(reader));
+            }
+        }
+
+        // we need to check for readers even if no IS is set - the readers may still do it
+        List<ReaderInterceptor> readers = outMessage == null ? null : ProviderFactory.getInstance(outMessage)
+            .createMessageBodyReaderInterceptor(cls, t, anns, mediaType, outMessage, entityStreamAvailable, null);
+
+        if (readers != null) {
+            try {
+                if (entityBufferred) {
+                    InputStream.class.cast(entity).reset();
+                }
+
+                Message responseMessage = getResponseMessage();
+                responseMessage.put(Message.PROTOCOL_HEADERS, getHeaders());
+
+                lastEntity = JAXRSUtils.readFromMessageBodyReader(readers, cls, t,
+                                                                  anns,
+                                                                  entityStream,
+                                                                  mediaType,
+                                                                  responseMessage);
+                // close the entity after readEntity is called.
+                T tCastLastEntity = castLastEntity();
+                shouldClose = shouldClose && !(tCastLastEntity instanceof AutoCloseable)
+                    && !(tCastLastEntity instanceof Source);
+                if (shouldClose) {
+                    close();
+                }
+                return tCastLastEntity;
+            } catch (NoContentException ex) {
+                //when content is empty, return null instead of throw exception to pass TCK
+                //check if basic type. Basic type throw exception, else return null.
+                if (isBasicType(cls)) {
+                    autoClose(cls, true);
+                    reportMessageHandlerProblem("MSG_READER_PROBLEM", cls, mediaType, ex);
+                } else {
+                    if (shouldClose) {
+                        close();
+                    }
+                    return null;
+                }
+            } catch (Exception ex) {
+                autoClose(cls, true);
+                reportMessageHandlerProblem("MSG_READER_PROBLEM", cls, mediaType, ex);
+            } finally {
+                ProviderFactory pf = ProviderFactory.getInstance(outMessage);
+                if (pf != null) {
+                    pf.clearThreadLocalProxies();
+                }
+            }
+        } else if (entity != null && cls.isAssignableFrom(entity.getClass())) {
+            lastEntity = entity;
+            return castLastEntity();
+        } else if (entityStreamAvailable) {
+            reportMessageHandlerProblem("NO_MSG_READER", cls, mediaType, null);
+        }
+
+        throw new IllegalStateException("The entity is not backed by an input stream, entity class is : "
+            + (entity != null ? entity.getClass().getName() : cls.getName()));
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T> T castLastEntity() {
+        return (T)lastEntity;
+    }
+
+    public InputStream convertEntityToStreamIfPossible() {
+        String stringEntity = null;
+        if (entity instanceof String || entity instanceof Number) {
+            stringEntity = entity.toString();
+        }
+        if (stringEntity != null) {
+            try {
+                return new ByteArrayInputStream(stringEntity.getBytes(StandardCharsets.UTF_8));
+            } catch (Exception ex) {
+                throw new ProcessingException(ex);
+            }
+        }
+        return null;
+    }
+
+    private boolean entityStreamAvailable() {
+        if (entity == null) {
+            Message inMessage = getResponseMessage();
+            return inMessage != null && (inMessage.getContent(XMLStreamReader.class) != null
+                || inMessage.getContent(Reader.class) != null);
+        }
+        return entity instanceof InputStream;
+    }
+
+    private Message getResponseMessage() {
+        Message responseMessage = outMessage.getExchange().getInMessage();
+        if (responseMessage == null) {
+            responseMessage = outMessage.getExchange().getInFaultMessage();
+        }
+        return responseMessage;
+    }
+
+    private void reportMessageHandlerProblem(String name, Class<?> cls, MediaType ct, Throwable cause) {
+        String errorMessage = JAXRSUtils.logMessageHandlerProblem(name, cls, ct);
+        throw new ResponseProcessingException(this, errorMessage, cause);
+    }
+
+    protected void autoClose(Class<?> cls, boolean exception) {
+        if (!entityBufferred && !JAXRSUtils.isStreamingOutType(cls)
+            && (exception || MessageUtils.getContextualBoolean(outMessage, "response.stream.auto.close"))) {
+            close();
+        }
+    }
+
+    @Override
+    public boolean bufferEntity() throws ProcessingException {
+        checkEntityIsClosed();
+        if (!entityBufferred && entity instanceof InputStream) {
+            try {
+                InputStream oldEntity = (InputStream)entity;
+                entity = IOUtils.loadIntoBAIS(oldEntity);
+                oldEntity.close();
+                entityBufferred = true;
+            } catch (IOException ex) {
+                throw new ResponseProcessingException(this, ex);
+            }
+        }
+        return entityBufferred;
+    }
+
+    @Override
+    public void close() throws ProcessingException {
+        if (!entityClosed) {
+            if (!entityBufferred && entity instanceof InputStream) {
+                try {
+                    ((InputStream)entity).close();
+                } catch (IOException ex) {
+                    throw new ResponseProcessingException(this, ex);
+                }
+            }
+            entity = null;
+            entityClosed = true;
+        }
+
+    }
+
+    private void checkEntityIsClosed() {
+        if (entityClosed) {
+            throw new IllegalStateException("Entity is not available");
+        }
+    }
+
+    private Response.StatusType createStatusType(int statusCode, String reasonPhrase) {
+        return new Response.StatusType() {
+
+            @Override
+            public Family getFamily() {
+                return Response.Status.Family.familyOf(statusCode);
+            }
+
+            @Override
+            public String getReasonPhrase() {
+                if (reasonPhrase != null) {
+                    return reasonPhrase;
+                }
+                Response.Status statusEnum = Response.Status.fromStatusCode(statusCode);
+                return statusEnum != null ? statusEnum.getReasonPhrase() : "";
+            }
+
+            @Override
+            public int getStatusCode() {
+                return statusCode;
+            }
+
+        };
+    }
+
+    private static boolean isBasicType(Class<?> type) {
+        return type.isPrimitive() || Number.class.isAssignableFrom(type) || Boolean.class.isAssignableFrom(type)
+            || Character.class.isAssignableFrom(type);
+    }
+}
\ No newline at end of file
diff --git a/transform/src/patch/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java b/transform/src/patch/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
index 0254368..4cf99ff 100644
--- a/transform/src/patch/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
+++ b/transform/src/patch/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
@@ -47,39 +47,40 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
-import jakarta.ws.rs.ClientErrorException;
-import jakarta.ws.rs.Consumes;
-import jakarta.ws.rs.HttpMethod;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.container.AsyncResponse;
-import jakarta.ws.rs.container.ContainerRequestContext;
-import jakarta.ws.rs.container.ContainerRequestFilter;
-import jakarta.ws.rs.container.ContainerResponseContext;
-import jakarta.ws.rs.container.ContainerResponseFilter;
-import jakarta.ws.rs.container.ResourceContext;
-import jakarta.ws.rs.container.ResourceInfo;
-import jakarta.ws.rs.core.Application;
-import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Cookie;
-import jakarta.ws.rs.core.HttpHeaders;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.PathSegment;
-import jakarta.ws.rs.core.Request;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.Response.ResponseBuilder;
-import jakarta.ws.rs.core.SecurityContext;
-import jakarta.ws.rs.core.StreamingOutput;
-import jakarta.ws.rs.core.UriInfo;
-import jakarta.ws.rs.ext.ContextResolver;
-import jakarta.ws.rs.ext.MessageBodyReader;
-import jakarta.ws.rs.ext.MessageBodyWriter;
-import jakarta.ws.rs.ext.Providers;
-import jakarta.ws.rs.ext.ReaderInterceptor;
-import jakarta.ws.rs.ext.ReaderInterceptorContext;
-import jakarta.ws.rs.ext.WriterInterceptor;
-import jakarta.ws.rs.ext.WriterInterceptorContext;
+import javax.activation.DataSource;
+import javax.ws.rs.ClientErrorException;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Configuration;
+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.StreamingOutput;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Providers;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
 import javax.xml.namespace.QName;
 
 import org.apache.cxf.common.i18n.BundleUtils;
@@ -168,7 +169,7 @@ public final class JAXRSUtils {
     private static final String HTTP_CHARSET_PARAM = "charset";
     private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0];
     private static final Set<Class<?>> STREAMING_OUT_TYPES = new HashSet<>(
-        Arrays.asList(InputStream.class, Reader.class, StreamingOutput.class));
+        Arrays.asList(InputStream.class, Reader.class, StreamingOutput.class, DataSource.class));
 
     private JAXRSUtils() {
     }