be.iminds.aiolos.ui.CommonServlet.java Source code

Java tutorial

Introduction

Here is the source code for be.iminds.aiolos.ui.CommonServlet.java

Source

/*******************************************************************************
 * AIOLOS  - Framework for dynamic distribution of software components at runtime.
 * Copyright (C) 2014-2016  iMinds - IBCN - UGent
 *
 * This file is part of AIOLOS.
 *
 * AIOLOS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Tim Verbelen, Steven Bohez, Elias Deconinck
 *******************************************************************************/
package be.iminds.aiolos.ui;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

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

import org.apache.commons.io.IOUtils;
import org.osgi.framework.BundleContext;
import org.osgi.service.log.LogService;
import org.osgi.service.repository.Repository;
import org.osgi.util.tracker.ServiceTracker;

import be.iminds.aiolos.cloud.api.CloudManager;
import be.iminds.aiolos.platform.api.PlatformManager;

@SuppressWarnings("serial")
public abstract class CommonServlet extends HttpServlet {

    public final String LABEL;
    public final String CATEGORY;
    public final String TITLE;
    public final String CSS[];
    private final String TEMPLATE;
    protected final ServiceTracker<PlatformManager, PlatformManager> platformTracker;
    protected final ServiceTracker<Repository, Repository> repositoryTracker;
    protected final ServiceTracker<CloudManager, CloudManager> cloudTracker;

    protected final ExecutorService executor = Executors.newCachedThreadPool();
    protected boolean drawDetails = false;

    protected abstract void writeJSON(final Writer w, final Locale locale) throws IOException;

    public CommonServlet(String label, String title, String category, String[] css, String template,
            BundleContext bundleContext) {
        this.LABEL = label;
        this.TITLE = title;
        this.CATEGORY = category;
        this.CSS = css;
        this.TEMPLATE = readTemplateFile(template);
        this.platformTracker = new ServiceTracker<PlatformManager, PlatformManager>(bundleContext,
                PlatformManager.class, null);
        this.repositoryTracker = new ServiceTracker<Repository, Repository>(bundleContext, Repository.class, null);
        this.cloudTracker = new ServiceTracker<CloudManager, CloudManager>(bundleContext, CloudManager.class, null);

    }

    @Override
    public void destroy() {
        executor.shutdownNow();
        platformTracker.close();
        repositoryTracker.close();
        cloudTracker.close();
        super.destroy();
    }

    @Override
    public void init() throws ServletException {
        platformTracker.open();
        repositoryTracker.open();
        cloudTracker.open();
        super.init();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Not necessary for plugin only as standalone app.
        // doGetPlugin allways needed.
        // check whether we are not at .../{webManagerRoot}
        final String pathInfo = request.getPathInfo();
        if (pathInfo == null || pathInfo.equals("/")) {
            String path = request.getRequestURI();
            if (!path.endsWith("/")) {
                path = path.concat("/");
            }
            path = path.concat(LABEL);
            response.sendRedirect(path);
            return;
        }

        int slash = pathInfo.indexOf("/", 1);
        if (slash < 2) {
            slash = pathInfo.length();
        }

        final String label = pathInfo.substring(1, slash);
        if (label != null && label.startsWith(LABEL)) {
            final RequestInfo reqInfo = new RequestInfo(request, LABEL);
            if (reqInfo.extension.equals("html")) {
                doGetPlugin(request, response);
            } else if (reqInfo.extension.equals("json")) {
                renderJSON(response, request.getLocale());
            }
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }

    private void doGetPlugin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        StringWriter sw = new StringWriter();
        writeJSON(sw, request.getLocale());

        Map<Object, Object> vars = getProperties(request);
        vars.put("__data__", sw.toString());
        vars.put("drawDetails", drawDetails);

        response.getWriter().print(TEMPLATE);
    }

    protected void renderJSON(HttpServletResponse response, Locale locale) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        final PrintWriter pw = response.getWriter();
        writeJSON(pw, locale);
    }

    @SuppressWarnings("unchecked")
    public static Map<Object, Object> getProperties(final ServletRequest request) {
        final Object resolverObj = request.getAttribute("felix.webconsole.variable.resolver");
        if (resolverObj instanceof Map<?, ?>) {
            return (Map<Object, Object>) resolverObj;
        }

        final Map<Object, Object> resolver = new HashMap<Object, Object>();
        request.setAttribute("felix.webconsole.variable.resolver", resolver);
        return resolver;
    }

    /**
      * Called internally by {@link AbstractWebConsolePlugin} to load resources.
      *
      * This particular implementation depends on the label. As example, if the
      * plugin is accessed as <code>/system/console/abc</code>, and the plugin
      * resources are accessed like <code>/system/console/abc/res/logo.gif</code>,
      * the code here will try load resource <code>/res/logo.gif</code> from the
      * bundle, providing the plugin.
      *
      *
      * @param path the path to read.
      * @return the URL of the resource or <code>null</code> if not found.
      */
    protected URL getResource(String path) {
        String labelRes = '/' + LABEL + '/';
        int labelResLen = labelRes.length() - 1;
        return (path != null && path.startsWith(labelRes)) ? //
                getClass().getResource(path.substring(labelResLen)) : null;
    }

    /**
     * Reads the <code>templateFile</code> as a resource through the class
     * loader of this class converting the binary data into a string using
     * UTF-8 encoding.
     * <p>
     * If the template file cannot read into a string and an exception is
     * caused, the exception is logged and an empty string returned.
     *
     * @param templateFile The absolute path to the template file to read.
     * @return The contents of the template file as a string or and empty
     *      string if the template file fails to be read.
     *
     * @throws NullPointerException if <code>templateFile</code> is
     *      <code>null</code>
     * @throws RuntimeException if an <code>IOException</code> is thrown reading
     *      the template file into a string. The exception provides the
     *      exception thrown as its cause.
     */
    protected final String readTemplateFile(final String templateFile) {
        Class<? extends HttpServlet> clazz = this.getClass();
        InputStream templateStream = clazz.getResourceAsStream(templateFile);
        if (templateStream != null) {
            try {
                String str = IOUtils.toString(templateStream, "UTF-8"); //$NON-NLS-1$
                switch (str.charAt(0)) { // skip BOM
                case 0xFEFF: // UTF-16/UTF-32, big-endian
                case 0xFFFE: // UTF-16, little-endian
                case 0xEFBB: // UTF-8
                    return str.substring(1);
                }
                return str;
            } catch (Exception e) {
                // don't use new Exception(message, cause) because cause is 1.4+
                throw new RuntimeException("readTemplateFile: Error loading " + templateFile + ": " + e); //$NON-NLS-1$ //$NON-NLS-2$
            } finally {
                IOUtils.closeQuietly(templateStream);
            }
        }

        // template file does not exist, return an empty string
        Activator.logger.log(LogService.LOG_ERROR,
                "readTemplateFile: File '" + templateFile + "' not found through class " + clazz); //$NON-NLS-1$ //$NON-NLS-2$
        return ""; //$NON-NLS-1$
    }
}