001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2009 Sun Microsystems Inc.
015 * Portions Copyright 2010–2011 ApexIdentity Inc.
016 * Portions Copyright 2011-2014 ForgeRock AS.
017 */
018
019package org.forgerock.openig.http;
020
021import java.io.Closeable;
022import java.io.IOException;
023
024import org.forgerock.openig.io.BranchingInputStream;
025
026/**
027 * Elements common to requests and responses.
028 *
029 * @param <T>
030 *            The sub-type of this message.
031 */
032public abstract class Message<T extends Message<T>> implements Closeable {
033
034    /** Message entity body. */
035    private final Entity entity = new Entity(this);
036
037    /** Message header fields. */
038    private final Headers headers = new Headers();
039
040    /** Protocol version. Default: {@code HTTP/1.1}. */
041    private String version = "HTTP/1.1";
042
043    Message() {
044        // Hidden constructor.
045    }
046
047    /**
048     * Returns the entity.
049     *
050     * @return The entity.
051     */
052    public final Entity getEntity() {
053        return entity;
054    }
055
056    /**
057     * Returns the headers.
058     *
059     * @return The headers.
060     */
061    public final Headers getHeaders() {
062        prepareHeaders(headers);
063        return headers;
064    }
065
066    /**
067     * Update the headers if needed.
068     */
069    void prepareHeaders(final Headers headers) {
070        // Nothing to do.
071    }
072
073    /**
074     * Returns the protocol version. Default: {@code HTTP/1.1}.
075     *
076     * @return The protocol version.
077     */
078    public final String getVersion() {
079        return version;
080    }
081
082    /**
083     * Sets the content of the entity to the provided value. Calling this method
084     * will close any existing streams associated with the entity. May also set
085     * the {@code Content-Length} header, overwriting any existing header.
086     * <p>
087     * This method is intended mostly as a convenience method within scripts.
088     * The parameter will be handled depending on its type as follows:
089     * <ul>
090     * <li>{@code BranchingInputStream} - equivalent to calling
091     * {@link Entity#setRawInputStream}
092     * <li>{@code byte[]} - equivalent to calling {@link Entity#setBytes}
093     * <li>{@code String} - equivalent to calling {@link Entity#setString}
094     * <li>{@code Object} - equivalent to calling {@link Entity#setJson}.
095     * </ul>
096     * <p>
097     * Note: This method does not attempt to encode the entity based-on any
098     * codings specified in the {@code Content-Encoding} header.
099     *
100     * @param o
101     *            The object whose value should be stored in the entity.
102     * @return This message.
103     * @throws IOException
104     *             If an IO error occurred while reading/mapping the content.
105     */
106    public final T setEntity(Object o) throws IOException {
107        if (o instanceof BranchingInputStream) {
108            entity.setRawInputStream((BranchingInputStream) o);
109        } else if (o instanceof byte[]) {
110            entity.setBytes((byte[]) o);
111        } else if (o instanceof String) {
112            entity.setString((String) o);
113        } else {
114            entity.setJson(o);
115        }
116        return thisMessage();
117    }
118
119    /**
120     * Sets the protocol version. Default: {@code HTTP/1.1}.
121     *
122     * @param version
123     *            The protocol version.
124     * @return This message.
125     */
126    public final T setVersion(final String version) {
127        this.version = version;
128        return thisMessage();
129    }
130
131    /**
132     * Closes all resources associated with the entity. Any open streams will be
133     * closed, and the underlying content reset back to a zero length.
134     *
135     * @see Entity#close()
136     */
137    @Override
138    public void close() {
139        entity.close();
140    }
141
142    abstract T thisMessage();
143}