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 2012-2015 ForgeRock AS.
015 */
016
017package org.forgerock.json.resource.http;
018
019import static org.forgerock.json.resource.http.HttpUtils.*;
020
021import java.net.URI;
022
023import org.forgerock.services.context.Context;
024import org.forgerock.http.Filter;
025import org.forgerock.http.Handler;
026import org.forgerock.http.filter.Filters;
027import org.forgerock.http.handler.Handlers;
028import org.forgerock.json.resource.ConnectionFactory;
029import org.forgerock.json.resource.RequestHandler;
030import org.forgerock.json.resource.Resources;
031import org.forgerock.util.Reject;
032
033/**
034 * <p>A CREST HTTP utility class which creates instances of the {@link HttpAdapter}
035 * to handle CREST HTTP requests.</p>
036 *
037 * <p>Instances must be provided with a {@code ConnectionFactory} in order to
038 * operate and optionally a {@code HttpContextFactory}.</p>
039 */
040public final class CrestHttp {
041
042    private CrestHttp() {
043    }
044
045    /**
046     * Creates a new JSON resource HTTP Handler with the provided connection
047     * factory and no context factory.
048     *
049     * @param connectionFactory
050     *            The connection factory.
051     * @return A CREST HTTP {@code Handler}.
052     */
053    public static Handler newHttpHandler(ConnectionFactory connectionFactory) {
054        Reject.ifNull(connectionFactory);
055        return Handlers.chainOf(new HttpAdapter(connectionFactory), newOptionsFilter());
056    }
057
058    /**
059     * Creates a new JSON resource HTTP Handler with the provided connection
060     * factory and a context factory which will always return the provided
061     * request context.
062     *
063     * @param connectionFactory
064     *            The connection factory.
065     * @param parentContext
066     *            The parent request context which should be used as the parent
067     *            context of each request context.
068     * @return A HTTP Handler.
069     */
070    public static Handler newHttpHandler(ConnectionFactory connectionFactory, Context parentContext) {
071        Reject.ifNull(connectionFactory);
072        Reject.ifNull(parentContext);
073        return Handlers.chainOf(new HttpAdapter(connectionFactory, parentContext), newOptionsFilter());
074    }
075
076    /**
077     * Creates a new JSON resource HTTP Handler with the provided connection
078     * factory and context factory.
079     *
080     * @param connectionFactory
081     *            The connection factory.
082     * @param contextFactory
083     *            The context factory which will be used to obtain the parent
084     *            context of each request context.
085     * @return A HTTP Handler.
086     */
087    public static Handler newHttpHandler(ConnectionFactory connectionFactory, HttpContextFactory contextFactory) {
088        Reject.ifNull(connectionFactory);
089        Reject.ifNull(contextFactory);
090        return Handlers.chainOf(new HttpAdapter(connectionFactory, contextFactory), newOptionsFilter());
091    }
092
093    /**
094     * Creates a new JSON resource HTTP handler with the provided CREST request handler.
095     *
096     * @param handler The {@link RequestHandler}.
097     * @return A HTTP Handler.
098     */
099    public static Handler newHttpHandler(RequestHandler handler) {
100        Reject.ifNull(handler);
101        return Handlers.chainOf(new HttpAdapter(Resources.newInternalConnectionFactory(handler)), newOptionsFilter());
102    }
103
104    /**
105     * Creates a new {@link RequestHandler} that map back and forth JSON resource objects to CHF objects.
106     *
107     * @param handler
108     *         HTTP {@link Handler} responsible for emitting the HTTP request build from JSON resource {@link
109     *         org.forgerock.json.resource.Request}s.
110     * @param uri
111     *         base URI used to build the target URI for built HTTP message
112     * @return a JSON resource {@link RequestHandler}
113     */
114    public static RequestHandler newRequestHandler(Handler handler, final URI uri) {
115        return new CrestAdapter(handler, uri);
116    }
117
118    /**
119     * Creates a new {@link ConnectionFactory} that map back and forth JSON resource objects to CHF objects.
120     * <p>
121     * Convenience method. Note that ConnectionFactory is going to be removed soon, so you may not need this.
122     *
123     * @param handler
124     *         HTTP {@link Handler} responsible for emitting the HTTP request build from JSON resource {@link
125     *         org.forgerock.json.resource.Request}s.
126     * @param uri
127     *         base URI used to build the target URI for built HTTP message
128     * @return a JSON resource {@link RequestHandler}
129     */
130    public static ConnectionFactory newConnectionFactory(Handler handler, final URI uri) {
131        return Resources.newInternalConnectionFactory(newRequestHandler(handler, uri));
132    }
133
134    private static Filter newOptionsFilter() {
135        return Filters.newOptionsFilter(METHOD_DELETE,
136                                        METHOD_GET,
137                                        METHOD_HEAD,
138                                        METHOD_PATCH,
139                                        METHOD_PUT,
140                                        METHOD_OPTIONS,
141                                        METHOD_TRACE);
142    }
143}