001/*
002 * #%L
003 * Netarchivesuite - harvester
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023
024package dk.netarkivet.viewerproxy;
025
026import dk.netarkivet.common.exceptions.ArgumentNotValid;
027
028/**
029 * An abstract superclass for URIResolvers that handle commands given to the server host
030 * (http://<<serverhost>>/<<command>>/<<param>>=<<value>>*).
031 */
032
033public abstract class CommandResolver implements URIResolverHandler, URIResolver {
034    /**
035     * The URI resolver which is wrapped, and which handles all non-command URIs.
036     */
037    protected URIResolver ur;
038    /** Fake host used as hostname when doing commands. */
039    public static final String VIEWERPROXY_COMMAND_NAME = "netarchivesuite.viewerproxy.invalid";
040
041    /**
042     * Constructor which sets the next resolver in the chain.
043     *
044     * @param ur The URIResolver that handles URIs that are not handled by this resolver.
045     */
046    public CommandResolver(URIResolver ur) {
047        setURIResolver(ur);
048    }
049
050    /**
051     * Change the URI resolver which handles URIs that we don't handle here.
052     *
053     * @param anUr The URI resolver to handle unhandled URIs.
054     * @throws ArgumentNotValid if either argument is null.
055     */
056    public final void setURIResolver(URIResolver anUr) {
057        ArgumentNotValid.checkNotNull(anUr, "URIResolver anUr");
058        this.ur = anUr;
059    }
060
061    /**
062     * Parses the given URI and executes commands for all command URLs. The possible commands are of the form
063     * http://<<localhostname>>/<<command>>?<<param>>=<<value>>* where command and param are defined in the subclass.
064     * <p>
065     * If uri is none of these, the uri and response are forwarded to the wrapped URI resolver.
066     *
067     * @param request The HTTP request we are working on
068     * @param response HTTP response to generate effect on or to forward
069     * @return response code
070     */
071    public final int lookup(Request request, Response response) {
072        boolean command = executeCommand(request, response);
073        if (!command) {
074            return ur.lookup(request, response);
075        } else {
076            return response.getStatus();
077        }
078    }
079
080    /**
081     * Abstract method for parsing of the URL and delegating to relevant methods. This should start by calling
082     * isCommandHostRequest.
083     *
084     * @param request The request to check
085     * @param response The response to give command results to if it is a command
086     * @return Whether this was a command URL
087     */
088    protected abstract boolean executeCommand(Request request, Response response);
089
090    /**
091     * Returns true if the request specifies the host that we're running on. Alternative specifications such as
092     * 'localhost' or '127.0.0.1' or an actual IP of this machine are not considered command hosts. Local hosts would
093     * only be command hosts if we happen to get a request from a browser running on this machine.
094     *
095     * @param request An HTTP request.
096     * @return True if the HTTP request specifies a URI that indicates this machine, false otherwise.
097     */
098    protected static boolean isCommandHostRequest(Request request) {
099        return request != null && request.getURI() != null && request.getURI().getHost() != null
100                && request.getURI().getHost().equals(VIEWERPROXY_COMMAND_NAME);
101    }
102}