org.eclipse.smarthome.ui.icon.internal.IconServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.smarthome.ui.icon.internal.IconServlet.java

Source

/**
 * Copyright (c) 2014-2017 by the respective copyright holders.
 * 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
 */
package org.eclipse.smarthome.ui.icon.internal;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.smarthome.ui.icon.IconProvider;
import org.eclipse.smarthome.ui.icon.IconSet.Format;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Registers a servlet that serves icons through {@link IconProvider}s.
 *
 * @author Kai Kreuzer - Initial contribution
 */
public class IconServlet extends HttpServlet {

    private static final long serialVersionUID = 2880642275858634578L;

    private final Logger logger = LoggerFactory.getLogger(IconServlet.class);

    private static final String SERVLET_NAME = "/icon";
    private static final String PARAM_ICONSET = "iconset";
    private static final String PARAM_FORMAT = "format";
    private static final String PARAM_STATE = "state";

    private long startupTime;

    protected HttpService httpService;

    protected String defaultIconSetId = "classic";

    private List<IconProvider> iconProvider = new ArrayList<>();

    public void setHttpService(HttpService httpService) {
        this.httpService = httpService;
    }

    public void unsetHttpService(HttpService httpService) {
        this.httpService = null;
    }

    public void addIconProvider(IconProvider iconProvider) {
        this.iconProvider.add(iconProvider);
    }

    public void removeIconProvider(IconProvider iconProvider) {
        this.iconProvider.remove(iconProvider);
    }

    protected void activate(Map<String, Object> config) {
        try {
            logger.debug("Starting up icon servlet at " + SERVLET_NAME);

            Hashtable<String, String> props = new Hashtable<String, String>();
            httpService.registerServlet(SERVLET_NAME, this, props, createHttpContext());
        } catch (NamespaceException e) {
            logger.error("Error during servlet startup", e);
        } catch (ServletException e) {
            logger.error("Error during servlet startup", e);
        }
        startupTime = System.currentTimeMillis();

        modified(config);
    }

    protected void modified(Map<String, Object> config) {
        Object iconSetId = config.get("default");
        if (iconSetId instanceof String) {
            defaultIconSetId = (String) iconSetId;
        }
    }

    /**
     * Creates a {@link HttpContext}
     *
     * @return a {@link HttpContext}
     */
    protected HttpContext createHttpContext() {
        HttpContext defaultHttpContext = httpService.createDefaultHttpContext();
        return defaultHttpContext;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        if (req.getDateHeader("If-Modified-Since") > startupTime) {
            resp.setStatus(304);
            return;
        }

        String category = getCategory(req);
        Format format = getFormat(req);
        String state = getState(req);
        String iconSetId = getIconSetId(req);

        IconProvider topProvider = null;
        int maxPrio = Integer.MIN_VALUE;
        for (IconProvider provider : iconProvider) {
            Integer prio = provider.hasIcon(category, iconSetId, format);
            if (prio != null && prio > maxPrio) {
                maxPrio = prio;
                topProvider = provider;
            }
        }
        if (topProvider != null) {
            if (format.equals(Format.SVG)) {
                resp.setContentType("image/svg+xml");
            } else {
                resp.setContentType("image/png");
            }
            resp.setDateHeader("Last-Modified", new Date().getTime());
            ServletOutputStream os = resp.getOutputStream();
            try (InputStream is = topProvider.getIcon(category, iconSetId, state, format)) {
                IOUtils.copy(is, os);
                resp.flushBuffer();
            } catch (IOException e) {
                logger.error("Failed sending the icon byte stream as a response: {}", e.getMessage());
                resp.sendError(500, e.getMessage());
            }
        } else {
            resp.sendError(404);
        }
    }

    private String getCategory(HttpServletRequest req) {
        String category = StringUtils.substringAfterLast(req.getRequestURI(), "/");
        category = StringUtils.substringBeforeLast(category, ".");
        return StringUtils.substringBeforeLast(category, "-");
    }

    private Format getFormat(HttpServletRequest req) {
        String format = req.getParameter(PARAM_FORMAT);
        if (format == null) {
            String filename = StringUtils.substringAfterLast(req.getRequestURI(), "/");
            format = StringUtils.substringAfterLast(filename, ".");
        }
        try {
            Format f = Format.valueOf(format.toUpperCase());
            return f;
        } catch (IllegalArgumentException e) {
            logger.debug("unknown format '{}' in HTTP request - falling back to PNG", format);
            return Format.PNG;
        }
    }

    private String getIconSetId(HttpServletRequest req) {
        String iconSetId = req.getParameter(PARAM_ICONSET);
        if (iconSetId == null || iconSetId.isEmpty()) {
            return defaultIconSetId;
        } else {
            return iconSetId;
        }
    }

    private String getState(HttpServletRequest req) {
        String state = req.getParameter(PARAM_STATE);
        if (state != null) {
            return state;
        } else {
            String filename = StringUtils.substringAfterLast(req.getRequestURI(), "/");
            state = StringUtils.substringAfterLast(filename, "-");
            state = StringUtils.substringBeforeLast(state, ".");
            if (StringUtils.isNotEmpty(state)) {
                return state;
            } else {
                return null;
            }
        }
    }
}