HttpConnection.java 5.43 KB
Newer Older
Alex Wenckus's avatar
Alex Wenckus committed
1
/**
Matt Tucker's avatar
Matt Tucker committed
2 3 4
 * $RCSfile$
 * $Revision: $
 * $Date: $
Alex Wenckus's avatar
Alex Wenckus committed
5
 *
6
 * Copyright (C) 2005-2008 Jive Software. All rights reserved.
Matt Tucker's avatar
Matt Tucker committed
7
 *
8 9 10 11 12 13 14 15 16 17 18
 * Licensed 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.
Alex Wenckus's avatar
Alex Wenckus committed
19
 */
Matt Tucker's avatar
Matt Tucker committed
20

21
package org.jivesoftware.openfire.http;
Alex Wenckus's avatar
Alex Wenckus committed
22

23 24
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Alex Wenckus's avatar
Alex Wenckus committed
25

26 27
import javax.servlet.AsyncContext;
import java.io.IOException;
28 29
import java.security.cert.X509Certificate;

Alex Wenckus's avatar
Alex Wenckus committed
30
/**
31
 * Represents one HTTP connection with a client using the HTTP Binding service. The client will wait
32
 * on a response until the server forwards a message to it or the wait time on the
33
 * session timeout.
Alex Wenckus's avatar
Alex Wenckus committed
34 35 36 37
 *
 * @author Alexander Wenckus
 */
public class HttpConnection {
38 39

    private static final Logger Log = LoggerFactory.getLogger(HttpConnection.class);
40 41 42 43 44

    private final long requestId;
    private final X509Certificate[] sslCertificates;
    private final boolean isSecure;
    
Alex Wenckus's avatar
Alex Wenckus committed
45 46
    private HttpSession session;
    private boolean isClosed;
47

48 49
    private final AsyncContext context;

50 51 52 53 54
    /**
     * Constructs an HTTP Connection.
     *
     * @param requestId the ID which uniquely identifies this request.
     * @param isSecure true if this connection is using HTTPS
55
     * @param sslCertificates list of certificates presented by the client.
56
     */
57
    public HttpConnection(long requestId, boolean isSecure, X509Certificate[] sslCertificates, AsyncContext context) {
Alex Wenckus's avatar
Alex Wenckus committed
58 59
        this.requestId = requestId;
        this.isSecure = isSecure;
60
        this.sslCertificates = sslCertificates;
61
        this.context = context;
Alex Wenckus's avatar
Alex Wenckus committed
62 63 64 65 66 67
    }

    /**
     * The connection should be closed without delivering a stanza to the requestor.
     */
    public void close() {
68 69 70 71
        synchronized (this) {
            if (isClosed) {
                return;
            }
Alex Wenckus's avatar
Alex Wenckus committed
72 73 74
        }

        try {
75
            deliverBody(null, true);
Alex Wenckus's avatar
Alex Wenckus committed
76 77
        }
        catch (HttpConnectionClosedException e) {
78
            Log.warn("Unexpected exception occurred while trying to close an HttpException.", e);
79 80
        } catch (IOException e) {
            Log.warn("Unexpected exception occurred while trying to close an HttpException.", e);
Alex Wenckus's avatar
Alex Wenckus committed
81 82 83
        }
    }

84 85
    /**
     * Returns true if this connection has been closed, either a response was delivered to the
86
     * client or the server closed the connection abruptly.
87 88 89
     *
     * @return true if this connection has been closed.
     */
90
    public synchronized boolean isClosed() {
Alex Wenckus's avatar
Alex Wenckus committed
91 92 93
        return isClosed;
    }

94 95 96 97 98
    /**
     * Returns true if this connection is using HTTPS.
     *
     * @return true if this connection is using HTTPS.
     */
Alex Wenckus's avatar
Alex Wenckus committed
99 100 101 102 103 104 105 106 107 108
    public boolean isSecure() {
        return isSecure;
    }

    /**
     * Delivers content to the client. The content should be valid XMPP wrapped inside of a body.
     * A <i>null</i> value for body indicates that the connection should be closed and the client
     * sent an empty body.
     *
     * @param body the XMPP content to be forwarded to the client inside of a body tag.
109
     * @param async when false, this method blocks until the data has been delivered to the client.
Alex Wenckus's avatar
Alex Wenckus committed
110
     *
111
     * @throws HttpConnectionClosedException when this connection to the client has already received
Alex Wenckus's avatar
Alex Wenckus committed
112 113
     * a deliverable to forward to the client
     */
114
    public void deliverBody(String body, boolean async) throws HttpConnectionClosedException, IOException {
Alex Wenckus's avatar
Alex Wenckus committed
115
        // We only want to use this function once so we will close it when the body is delivered.
116 117 118 119 120
    	synchronized (this) {
	        if (isClosed) {
	            throw new HttpConnectionClosedException("The http connection is no longer " +
	                    "available to deliver content");
	        }
121
            isClosed = true;
Alex Wenckus's avatar
Alex Wenckus committed
122 123
        }

124
        if (body == null) {
125
            body = getSession().createEmptyBody(false);
126
        }
127
        HttpBindServlet.respond(getSession(), this.context, body, async);
Alex Wenckus's avatar
Alex Wenckus committed
128 129
    }

130 131 132 133 134
    /**
     * Returns the ID which uniquely identifies this connection.
     *
     * @return the ID which uniquely identifies this connection.
     */
Alex Wenckus's avatar
Alex Wenckus committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
    public long getRequestId() {
        return requestId;
    }

    /**
     * Set the session that this connection belongs to.
     *
     * @param session the session that this connection belongs to.
     */
    void setSession(HttpSession session) {
        this.session = session;
    }

    /**
     * Returns the session that this connection belongs to.
     *
     * @return the session that this connection belongs to.
     */
    public HttpSession getSession() {
        return session;
    }
156 157 158 159 160 161 162 163 164
    
    /**
     * Returns the peer certificates for this connection. 
     * 
     * @return the peer certificates for this connection or null.
     */
    public X509Certificate[] getPeerCertificates() {
        return sslCertificates;
    }
Alex Wenckus's avatar
Alex Wenckus committed
165

166 167 168 169 170
	@Override
	public String toString() {
		return (session != null ? session.toString() : "[Anonymous]")
				+ " rid: " + this.getRequestId();
	}
Alex Wenckus's avatar
Alex Wenckus committed
171
}