001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027
028package org.apache.http.nio.protocol;
029
030import java.io.IOException;
031
032import org.apache.http.HttpEntity;
033import org.apache.http.HttpResponse;
034import org.apache.http.nio.ContentEncoder;
035import org.apache.http.nio.IOControl;
036import org.apache.http.nio.entity.EntityAsyncContentProducer;
037import org.apache.http.nio.entity.HttpAsyncContentProducer;
038import org.apache.http.protocol.HttpContext;
039import org.apache.http.util.Args;
040
041/**
042 * Basic implementation of {@link HttpAsyncResponseProducer}. The producer
043 * can make use of the {@link HttpAsyncContentProducer} interface to
044 * efficiently stream out message content to the underlying non-blocking HTTP
045 * connection, if it is implemented by the {@link HttpEntity} inclosed in
046 * the response.
047 *
048 * @see HttpAsyncContentProducer
049 *
050 * @since 4.2
051 */
052public class BasicAsyncResponseProducer implements HttpAsyncResponseProducer {
053
054    private final HttpResponse response;
055    private final HttpAsyncContentProducer producer;
056
057    /**
058     * Creates a producer that can be used to transmit the given response
059     * message. The given content producer will be used to stream out message
060     * content. Please note that the response message is expected to enclose
061     * an {@link HttpEntity} whose properties are consistent with the behavior
062     * of the content producer.
063     *
064     * @param response response message.
065     * @param producer response content producer.
066     */
067    protected BasicAsyncResponseProducer(
068            final HttpResponse response,
069            final HttpAsyncContentProducer producer) {
070        super();
071        Args.notNull(response, "HTTP response");
072        Args.notNull(producer, "HTTP content producer");
073        this.response = response;
074        this.producer = producer;
075    }
076
077    /**
078     * Creates a producer that can be used to transmit the given response
079     * message. If the response message encloses an {@link HttpEntity}
080     * it is also expected to implement {@link HttpAsyncContentProducer}.
081     *
082     * @param response response message.
083     */
084    public BasicAsyncResponseProducer(final HttpResponse response) {
085        super();
086        Args.notNull(response, "HTTP response");
087        this.response = response;
088        final HttpEntity entity = response.getEntity();
089        if (entity != null) {
090            if (entity instanceof HttpAsyncContentProducer) {
091                this.producer = (HttpAsyncContentProducer) entity;
092            } else {
093                this.producer = new EntityAsyncContentProducer(entity);
094            }
095        } else {
096            this.producer = null;
097        }
098    }
099
100    @Override
101    public HttpResponse generateResponse() {
102        return this.response;
103    }
104
105    @Override
106    public void produceContent(
107            final ContentEncoder encoder, final IOControl ioctrl) throws IOException {
108        if (this.producer != null) {
109            this.producer.produceContent(encoder, ioctrl);
110            if (encoder.isCompleted()) {
111                this.producer.close();
112            }
113        }
114    }
115
116    @Override
117    public void responseCompleted(final HttpContext context) {
118    }
119
120    @Override
121    public void failed(final Exception ex) {
122    }
123
124    @Override
125    public void close() throws IOException {
126        if (this.producer != null) {
127            this.producer.close();
128        }
129    }
130
131    @Override
132    public String toString() {
133        final StringBuilder buf = new StringBuilder();
134        buf.append(this.response);
135        if (this.producer != null) {
136            buf.append(" ").append(this.producer);
137        }
138        return buf.toString();
139    }
140
141}