org.eclipse.kapua.app.console.servlet.FileServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.kapua.app.console.servlet.FileServlet.java

Source

/*******************************************************************************
 * Copyright (c) 2011, 2016 Eurotech and/or its affiliates and others
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Eurotech - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.kapua.app.console.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.poi.util.IOUtils;
import org.eclipse.kapua.KapuaEntityNotFoundException;
import org.eclipse.kapua.KapuaIllegalAccessException;
import org.eclipse.kapua.KapuaUnauthenticatedException;
import org.eclipse.kapua.app.console.server.KapuaRemoteServiceServlet;
import org.eclipse.kapua.app.console.setting.ConsoleSetting;
import org.eclipse.kapua.app.console.setting.ConsoleSettingKeys;
import org.eclipse.kapua.app.console.shared.model.GwtXSRFToken;
import org.eclipse.kapua.app.console.shared.model.KapuaFormFields;
import org.eclipse.kapua.commons.model.id.KapuaEid;
import org.eclipse.kapua.locator.KapuaLocator;
import org.eclipse.kapua.service.device.management.command.DeviceCommandFactory;
import org.eclipse.kapua.service.device.management.command.DeviceCommandInput;
import org.eclipse.kapua.service.device.management.command.DeviceCommandManagementService;
import org.eclipse.kapua.service.device.management.command.DeviceCommandOutput;
import org.eclipse.kapua.service.device.management.configuration.DeviceConfigurationManagementService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileServlet extends KapuaHttpServlet {

    private static final long serialVersionUID = -5016170117606322129L;
    private static Logger s_logger = LoggerFactory.getLogger(FileServlet.class);

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");

        String reqPathInfo = req.getPathInfo();
        if (reqPathInfo == null) {
            resp.sendError(404);
            return;
        }

        // BEGIN XSRF - Servlet dependent code
        KapuaFormFields kapuaFormFields = getFormFields(req);
        try {
            GwtXSRFToken token = new GwtXSRFToken(kapuaFormFields.get("xsrfToken"));
            KapuaRemoteServiceServlet.checkXSRFToken(req, token);
        } catch (Exception e) {
            throw new ServletException("Security error: please retry this operation correctly.", e);
        }
        // END XSRF security check

        if (reqPathInfo.equals("/command")) {
            doPostCommand(kapuaFormFields, resp);
        } else if (reqPathInfo.equals("/configuration/snapshot")) {
            doPostConfigurationSnapshot(kapuaFormFields, resp);
        } else {
            resp.sendError(404);
            return;
        }
    }

    private void doPostConfigurationSnapshot(KapuaFormFields kapuaFormFields, HttpServletResponse resp)
            throws ServletException, IOException {
        try {
            List<FileItem> fileItems = kapuaFormFields.getFileItems();
            String scopeIdString = kapuaFormFields.get("scopeIdString");
            String deviceIdString = kapuaFormFields.get("deviceIdString");

            if (scopeIdString == null || scopeIdString.isEmpty()) {
                throw new IllegalArgumentException("scopeIdString");
            }

            if (deviceIdString == null || deviceIdString.isEmpty()) {
                throw new IllegalArgumentException("deviceIdString");
            }

            if (fileItems == null || fileItems.size() != 1) {
                throw new IllegalArgumentException("configuration");
            }

            KapuaLocator locator = KapuaLocator.getInstance();
            DeviceConfigurationManagementService deviceConfigurationManagementService = locator
                    .getService(DeviceConfigurationManagementService.class);

            FileItem fileItem = fileItems.get(0);
            byte[] data = fileItem.get();
            String xmlConfigurationString = new String(data, "UTF-8");

            deviceConfigurationManagementService.put(KapuaEid.parseShortId(scopeIdString),
                    KapuaEid.parseShortId(deviceIdString), xmlConfigurationString, null);

        } catch (IllegalArgumentException iae) {
            resp.sendError(400, "Illegal value for query parameter: " + iae.getMessage());
            return;
        } catch (KapuaEntityNotFoundException eenfe) {
            resp.sendError(400, eenfe.getMessage());
            return;
        } catch (KapuaUnauthenticatedException eiae) {
            resp.sendError(401, eiae.getMessage());
            return;
        } catch (KapuaIllegalAccessException eiae) {
            resp.sendError(403, eiae.getMessage());
            return;
        } catch (Exception e) {
            s_logger.error("Error posting configuration", e);
            throw new ServletException(e);
        }
    }

    private void doPostCommand(KapuaFormFields kapuaFormFields, HttpServletResponse resp)
            throws ServletException, IOException {
        try {
            List<FileItem> fileItems = kapuaFormFields.getFileItems();

            final String scopeIdString = kapuaFormFields.get("scopeIdString");
            final String deviceIdString = kapuaFormFields.get("deviceIdString");
            final String command = kapuaFormFields.get("command");
            final String password = kapuaFormFields.get("password");
            final String timeoutString = kapuaFormFields.get("timeout");

            if (scopeIdString == null || scopeIdString.isEmpty()) {
                throw new IllegalArgumentException("scopeId");
            }

            if (deviceIdString == null || deviceIdString.isEmpty()) {
                throw new IllegalArgumentException("deviceId");
            }

            if (command == null || command.isEmpty()) {
                throw new IllegalArgumentException("command");
            }

            if (fileItems.size() > 1) {
                throw new IllegalArgumentException("file");
            }

            Integer timeout = null;
            if (timeoutString != null && !timeoutString.isEmpty()) {
                try {
                    timeout = Integer.parseInt(timeoutString);
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("timeout");
                }
            }

            KapuaLocator locator = KapuaLocator.getInstance();
            DeviceCommandManagementService deviceService = locator.getService(DeviceCommandManagementService.class);

            // FIXME: set a max size on the MQtt payload
            byte[] data = fileItems.size() == 0 ? null : fileItems.get(0).get();

            DeviceCommandFactory deviceCommandFactory = locator.getFactory(DeviceCommandFactory.class);
            DeviceCommandInput commandInput = deviceCommandFactory.newCommandInput();

            StringTokenizer st = new StringTokenizer(command);
            int count = st.countTokens();

            String cmd = count > 0 ? st.nextToken() : null;
            String[] args = count > 1 ? new String[count - 1] : null;
            int i = 0;
            while (st.hasMoreTokens()) {
                args[i++] = st.nextToken();
            }

            commandInput.setCommand(cmd);
            commandInput.setPassword((password == null || password.isEmpty()) ? null : password);
            commandInput.setArguments(args);
            commandInput.setTimeout(timeout);
            commandInput.setWorkingDir("/tmp/");
            commandInput.setBody(data);

            DeviceCommandOutput deviceCommandOutput = deviceService.exec(KapuaEid.parseShortId(scopeIdString),
                    KapuaEid.parseShortId(deviceIdString), commandInput, null);
            resp.setContentType("text/plain");
            if (deviceCommandOutput.getStderr() != null && deviceCommandOutput.getStderr().length() > 0) {
                resp.getWriter().println(deviceCommandOutput.getStderr());
            }
            if (deviceCommandOutput.getStdout() != null && deviceCommandOutput.getStdout().length() > 0) {
                resp.getWriter().println(deviceCommandOutput.getStdout());
            }
            if (deviceCommandOutput.getExceptionMessage() != null
                    && deviceCommandOutput.getExceptionMessage().length() > 0) {
                resp.getWriter().println(deviceCommandOutput.getExceptionMessage());
            }

        } catch (IllegalArgumentException iae) {
            resp.sendError(400, "Illegal value for query parameter: " + iae.getMessage());
            return;
        } catch (KapuaEntityNotFoundException eenfe) {
            resp.sendError(400, eenfe.getMessage());
            return;
        } catch (KapuaUnauthenticatedException eiae) {
            resp.sendError(401, eiae.getMessage());
            return;
        } catch (KapuaIllegalAccessException eiae) {
            resp.sendError(403, eiae.getMessage());
            return;
        } catch (Exception e) {
            s_logger.error("Error sending command", e);
            throw new ServletException(e);
        }
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String reqPathInfo = request.getPathInfo();

        if (reqPathInfo.startsWith("/icons")) {
            doGetIconResource(request, response);
        } else {
            response.sendError(404);
        }
    }

    private void doGetIconResource(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final String id = request.getParameter("id");

        if (id == null || id.isEmpty()) {
            throw new IllegalArgumentException("id");
        }

        if (!id.matches("[0-9A-Za-z]{1,}")) {
            throw new IllegalArgumentException("id");
        }

        String tmpPath = System.getProperty("java.io.tmpdir");

        StringBuilder filePathSb = new StringBuilder(tmpPath);

        if (!tmpPath.endsWith("/")) {
            filePathSb.append("/");
        }

        ConsoleSetting config = ConsoleSetting.getInstance();

        filePathSb.append(config.getString(ConsoleSettingKeys.DEVICE_CONFIGURATION_ICON_FOLDER)).append("/")
                .append(id);

        File requestedFile = new File(filePathSb.toString());
        if (!requestedFile.exists()) {
            throw new IllegalArgumentException("id");
        }

        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("UTF-8");
        OutputStream out = response.getOutputStream();
        IOUtils.copy(new FileInputStream(requestedFile), out);
    }
}

class UploadRequest extends ServletFileUpload {

    private static Logger s_logger = LoggerFactory.getLogger(UploadRequest.class);

    Map<String, String> formFields;
    List<FileItem> fileItems;

    public UploadRequest(DiskFileItemFactory diskFileItemFactory) {
        super(diskFileItemFactory);
        setSizeMax(ConsoleSetting.getInstance().getLong(ConsoleSettingKeys.FILE_UPLOAD_SIZE_MAX));
        formFields = new HashMap<String, String>();
        fileItems = new ArrayList<FileItem>();
    }

    @SuppressWarnings("unchecked")
    public void parse(HttpServletRequest req) throws FileUploadException {
        s_logger.debug("upload.getFileSizeMax(): {}", getFileSizeMax());
        s_logger.debug("upload.getSizeMax(): {}", getSizeMax());

        // Parse the request
        List<FileItem> items = null;
        items = parseRequest(req);

        // Process the uploaded items
        Iterator<FileItem> iter = items.iterator();
        while (iter.hasNext()) {
            FileItem item = (FileItem) iter.next();

            if (item.isFormField()) {
                String name = item.getFieldName();
                String value = item.getString();

                s_logger.debug("Form field item name: {}, value: {}", name, value);

                formFields.put(name, value);
            } else {
                String fieldName = item.getFieldName();
                String fileName = item.getName();
                String contentType = item.getContentType();
                boolean isInMemory = item.isInMemory();
                long sizeInBytes = item.getSize();

                s_logger.debug("File upload item name: {}, fileName: {}, contentType: {}, isInMemory: {}, size: {}",
                        new Object[] { fieldName, fileName, contentType, isInMemory, sizeInBytes });

                fileItems.add(item);
            }
        }
    }

    public Map<String, String> getFormFields() {
        return formFields;
    }

    public List<FileItem> getFileItems() {
        return fileItems;
    }
}