001/*
002 * Syncany, www.syncany.org
003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com>
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package org.syncany.operations.daemon.handlers;
019
020import java.io.File;
021import java.io.FileInputStream;
022import java.io.FileNotFoundException;
023import java.io.IOException;
024import java.util.logging.Level;
025import java.util.logging.Logger;
026
027import org.apache.commons.io.IOUtils;
028import org.syncany.config.LocalEventBus;
029import org.syncany.operations.daemon.WebServer;
030import org.syncany.operations.daemon.WebServer.RequestFormatType;
031import org.syncany.operations.daemon.messages.BadRequestResponse;
032import org.syncany.operations.daemon.messages.api.JsonMessageFactory;
033import org.syncany.operations.daemon.messages.api.Request;
034import org.syncany.operations.daemon.messages.api.XmlMessageFactory;
035
036import com.google.common.base.Joiner;
037
038import io.undertow.server.HttpHandler;
039import io.undertow.server.HttpServerExchange;
040
041/**
042 * InteralRestHandler handles the REST requests sent to the daemon.
043 *
044 * @author Philipp C. Heckel (philipp.heckel@gmail.com)
045 */
046public class InternalRestHandler implements HttpHandler {
047        private static final Logger logger = Logger.getLogger(InternalRestHandler.class.getSimpleName());
048
049        private final WebServer daemonWebServer;
050        private final LocalEventBus eventBus;
051        private final RequestFormatType requestFormatType;
052
053        public InternalRestHandler(WebServer daemonWebServer, RequestFormatType requestFormatType) {
054                this.daemonWebServer = daemonWebServer;
055                this.eventBus = LocalEventBus.getInstance();
056                this.requestFormatType = requestFormatType;
057        }
058
059        @Override
060        public void handleRequest(final HttpServerExchange exchange) throws Exception {
061                handleRestRequest(exchange);
062        }
063
064        private void handleRestRequest(HttpServerExchange exchange) throws IOException {
065                logger.log(Level.INFO, "HTTP request received:" + exchange.getRelativePath());
066
067                exchange.startBlocking();
068
069                if (exchange.getRelativePath().startsWith("/file/")) {
070                        handleFileRequest(exchange);
071                }
072                else {
073                        handleNormalRequest(exchange);
074                }
075        }
076
077        private void handleNormalRequest(HttpServerExchange exchange) throws IOException {
078                String message = IOUtils.toString(exchange.getInputStream()); // TODO [high] Read entire file to memory. Dangerous!
079                logger.log(Level.INFO, "REST message received: " + message);
080
081                try {
082                        Request request;
083                        
084                        switch (requestFormatType) {
085                                case JSON:
086                                        request = JsonMessageFactory.toRequest(message);
087                                        break;
088
089                                case XML:
090                                        request = XmlMessageFactory.toRequest(message);
091                                        break;
092
093                                default:
094                                        throw new Exception("Unknown request format. Valid formats are " + Joiner.on(", ").join(RequestFormatType.values()));
095                        }
096
097                        daemonWebServer.putRequestFormatType(request.getId(), requestFormatType);
098                        daemonWebServer.putCacheRestRequest(request.getId(), exchange);
099                        
100                        eventBus.post(request);
101                }
102                catch (Exception e) {
103                        logger.log(Level.WARNING, "Invalid request received; cannot serialize to Request.", e);
104                        eventBus.post(new BadRequestResponse(-1, "Invalid request."));
105                }
106        }
107
108        private void handleFileRequest(HttpServerExchange exchange) throws FileNotFoundException, IOException {
109                String tempFileToken = exchange.getRelativePath().substring("/file/".length());
110                File tempFile = daemonWebServer.getFileTokenTempFileFromCache(tempFileToken);
111
112                if (tempFile != null) {
113                        logger.log(Level.INFO, "- Temp file: " + tempFileToken);
114
115                        IOUtils.copy(new FileInputStream(tempFile), exchange.getOutputStream());
116                        exchange.endExchange();
117                }
118                else {
119                        logger.log(Level.WARNING, "Invalid request received; Cannot find file token " + tempFileToken);
120                        eventBus.post(new BadRequestResponse(-1, "Invalid request."));
121                }
122        }
123}