marytts.server.http.BaseHttpRequestHandler.java Source code

Java tutorial

Introduction

Here is the source code for marytts.server.http.BaseHttpRequestHandler.java

Source

/**
 * Copyright 2007 DFKI GmbH.
 * All Rights Reserved.  Use is subject to license terms.
 *
 * This file is part of MARY TTS.
 *
 * MARY TTS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package marytts.server.http;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;

import marytts.Version;
import marytts.config.LanguageConfig;
import marytts.config.MaryConfig;
import marytts.datatypes.MaryDataType;
import marytts.htsengine.HMMVoice;
import marytts.modules.synthesis.Voice;
import marytts.server.MaryProperties;
import marytts.signalproc.effects.AudioEffect;
import marytts.signalproc.effects.AudioEffects;
import marytts.signalproc.effects.BaseAudioEffect;
import marytts.unitselection.UnitSelectionVoice;
import marytts.unitselection.interpolation.InterpolatingVoice;
import marytts.util.MaryRuntimeUtils;
import marytts.util.MaryUtils;
import marytts.util.http.Address;
import marytts.util.string.StringUtils;
import marytts.vocalizations.VocalizationSynthesizer;

import org.apache.http.Header;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.nio.ContentDecoder;
import org.apache.http.nio.ContentDecoderChannel;
import org.apache.http.nio.FileContentDecoder;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.entity.ConsumingNHttpEntity;
import org.apache.http.nio.entity.ConsumingNHttpEntityTemplate;
import org.apache.http.nio.entity.ContentListener;
import org.apache.http.nio.protocol.SimpleNHttpRequestHandler;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

/**
 * Provides baseline functionality to process http requests to the Mary server.
 * 
 * @author Oytun T&uuml;rk, Marc Schrder
 */
public abstract class BaseHttpRequestHandler extends SimpleNHttpRequestHandler implements HttpRequestHandler {
    private final boolean useFileChannels = true;

    protected static Logger logger;
    private int runningNumber = 1;
    private Map<String, Object[]> requestMap;

    public BaseHttpRequestHandler() {
        super();
        logger = MaryUtils.getLogger("server");
        requestMap = Collections.synchronizedMap(new HashMap<String, Object[]>());

    }

    /**
     * The entry point of all HttpRequestHandlers.
     * When this method returns, the response is sent to the client.
     */
    public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context)
            throws HttpException, IOException {
        try {
            Header[] tmp = request.getHeaders("Host");
            Address serverAddressAtClient = getServerAddressAtClient(tmp[0].getValue());
            String uri = request.getRequestLine().getUri();

            String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
            if (!(method.equals("GET") || method.equals("POST"))) {
                throw new MethodNotSupportedException(method + " method not supported");
            }

            String absPath = null;
            String query = null;
            if (uri != null && uri.length() > 0) {
                if (!uri.startsWith("/")) {
                    throw new HttpException("Unexpected uri: '" + uri + "' does not start with a slash");
                }
                int q = uri.indexOf('?');
                if (q == -1) {
                    absPath = uri;
                } else {
                    absPath = uri.substring(0, q);
                    query = uri.substring(q + 1);
                }
            }
            Map<String, String> queryItems = null;
            if (query != null && query.length() > 0) {
                queryItems = MaryHttpServerUtils.toKeyValuePairs(query, true);
            }

            //Try and get parameters from different HTTP POST requests if you have not been able to do this above
            if (method.equals("POST") && queryItems == null && request instanceof HttpEntityEnclosingRequest) {
                try {
                    String postQuery = EntityUtils.toString(((HttpEntityEnclosingRequest) request).getEntity());
                    queryItems = MaryHttpServerUtils.toKeyValuePairs(postQuery, true);
                } catch (Exception e) {
                    logger.debug("Cannot read post query", e);
                    MaryHttpServerUtils.errorInternalServerError(response, "Cannot read post query", e);
                }
            }

            //Parse request and create appropriate response
            handleClientRequest(absPath, queryItems, response, serverAddressAtClient);

        } catch (RuntimeException re) {
            logger.warn("runtime exception in handle():", re);
        }
    }

    protected abstract void handleClientRequest(String absPath, Map<String, String> queryItems,
            HttpResponse response, Address serverAddressAtClient) throws IOException;

    protected Address getServerAddressAtClient(String fullHeader) {
        String fullAddress = fullHeader.trim();
        int index = fullAddress.indexOf('?');

        if (index > 0)
            fullAddress = fullAddress.substring(0, index);

        return new Address(fullAddress);
    }

    public ConsumingNHttpEntity entityRequest(final HttpEntityEnclosingRequest request, final HttpContext context)
            throws HttpException, IOException {
        return new ConsumingNHttpEntityTemplate(request.getEntity(), new FileWriteListener(useFileChannels));
    }

    static class FileWriteListener implements ContentListener {
        private final File file;
        private final FileInputStream inputFile;
        private final FileChannel fileChannel;
        private final boolean useFileChannels;
        private long idx = 0;

        public FileWriteListener(boolean useFileChannels) throws IOException {
            this.file = File.createTempFile("tmp", ".tmp", null);
            this.inputFile = new FileInputStream(file);
            this.fileChannel = inputFile.getChannel();
            this.useFileChannels = useFileChannels;
        }

        public void contentAvailable(ContentDecoder decoder, IOControl ioctrl) throws IOException {
            long transferred;
            if (useFileChannels && decoder instanceof FileContentDecoder) {
                transferred = ((FileContentDecoder) decoder).transfer(fileChannel, idx, Long.MAX_VALUE);
            } else {
                transferred = fileChannel.transferFrom(new ContentDecoderChannel(decoder), idx, Long.MAX_VALUE);
            }

            if (transferred > 0)
                idx += transferred;
        }

        public void finished() {
            try {
                inputFile.close();
            } catch (IOException ignored) {
            }
            try {
                fileChannel.close();
            } catch (IOException ignored) {
            }
        }
    }

}