com.moss.appkeep.server.HttpPublisher.java Source code

Java tutorial

Introduction

Here is the source code for com.moss.appkeep.server.HttpPublisher.java

Source

/**
 * Copyright (C) 2013, Moss Computing Inc.
 *
 * This file is part of appkeep.
 *
 * appkeep is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * appkeep 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with appkeep; see the file COPYING.  If not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 *
 * Linking this library statically or dynamically with other modules is
 * making a combined work based on this library.  Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *
 * As a special exception, the copyright holders of this library give you
 * permission to link this library with independent modules to produce an
 * executable, regardless of the license terms of these independent
 * modules, and to copy and distribute the resulting executable under
 * terms of your choice, provided that you also meet, for each linked
 * independent module, the terms and conditions of the license of that
 * module.  An independent module is a module which is not derived from
 * or based on this library.  If you modify this library, you may extend
 * this exception to your version of the library, but you are not
 * obligated to do so.  If you do not wish to do so, delete this
 * exception statement from your version.
 */
package com.moss.appkeep.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.List;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mortbay.jetty.handler.AbstractHandler;

import com.moss.appkeep.api.ComponentId;
import com.moss.appkeep.api.endorse.ComponentEndorsement;
import com.moss.appkeep.api.endorse.JarsignEndorsement;
import com.moss.appkeep.api.endorse.x509.X509CertId;
import com.moss.appkeep.server.data.Data;
import com.moss.launch.components.ComponentType;
import com.moss.lobstore.LobStore;
import com.sleepycat.je.LockMode;

/**
 * /by-component-id/uuid.TYPE?with-endorsement=jarsign:UUID
 */
public class HttpPublisher extends AbstractHandler {
    enum RootType {
        BY_COMPONENT_ID("by-component-id");

        private final String value;

        private RootType(String value) {
            this.value = value;
        }

        public static RootType read(String v) {
            for (RootType next : RootType.values()) {
                if (next.value.equals(v)) {
                    return next;
                }
            }
            return null;
        }

    }

    enum EndorsementType {
        JARSIGN {
            @Override
            public ComponentEndorsement parse(String text) {
                List<X509CertId> certs = new LinkedList<X509CertId>();
                for (String next : splitWell(text, ",")) {
                    certs.add(new X509CertId(next));
                }
                return new JarsignEndorsement(certs.toArray(new X509CertId[certs.size()]));
            }
        };

        public abstract ComponentEndorsement parse(String text);
    }

    private final Log log = LogFactory.getLog(getClass());
    private final Data data;
    private final LobStore lobs;
    private final KeepTool tool;

    public HttpPublisher(Data data, LobStore lobs, KeepTool tool) {
        super();
        this.data = data;
        this.lobs = lobs;
        this.tool = tool;
    }

    public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)
            throws java.io.IOException, javax.servlet.ServletException {
        ComponentRequest cr = parse(request);

        if (cr != null) {
            final StoredComponent c = data.components.get(cr.componentId, null, LockMode.DEFAULT);

            if (c == null) {
                completeWithError("No such component:" + cr.componentId, HttpServletResponse.SC_BAD_REQUEST,
                        response);
            }

            if (c.type() != cr.componentType) {
                completeWithError("Invalid type for component: " + cr.componentType,
                        HttpServletResponse.SC_BAD_REQUEST, response);
            }

            if (!c.isPublic()) {
                completeWithError(
                        "ACCESS DENIED: component " + cr.componentId + " is not configured for public access",
                        HttpServletResponse.SC_FORBIDDEN, response);
                return;
            }

            OutputStream out = response.getOutputStream();

            // FIND THE COMPONENT
            InputStream i = tool.getComponent(c, cr.endorsements);

            // WRITE THE DATA TO THE CLIENT
            try {
                byte[] buf = new byte[1024 * 100];
                for (int x = i.read(buf); x != -1; x = i.read(buf)) {
                    out.write(buf, 0, x);
                }

                out.close();
            } finally {
                i.close();
            }
        }
    }

    private void completeWithError(String message, int code, HttpServletResponse response) throws IOException {
        response.setStatus(code);
        PrintWriter w = response.getWriter();
        w.write(message);
        w.close();
    }

    public static ComponentRequest parse(HttpServletRequest request) {
        List<String> parts = splitWell(request.getPathInfo(), "/");

        RootType type = RootType.read(parts.get(0));

        if (type != RootType.BY_COMPONENT_ID) {
            return null;
        }

        ComponentId componentId;
        ComponentType componentType;
        {
            String fileName = parts.get(1);

            int pos = fileName.lastIndexOf('.');

            componentId = new ComponentId(fileName.substring(0, pos));
            componentType = ComponentType.valueOf(fileName.substring(pos + 1).toUpperCase());
        }

        //      System.out.println("Component ID: " + componentId);
        //      System.out.println("Component Type: " + componentType);

        List<String> endorsementStrings = splitWell(request.getParameter("with-endorsements"), ";");

        List<ComponentEndorsement> endorsements = new LinkedList<ComponentEndorsement>();

        for (String next : endorsementStrings) {
            int delimiterPos = next.indexOf(':');
            String typeString = next.substring(0, delimiterPos);
            String value = next.substring(delimiterPos + 1);
            //         System.out.println("Type " + typeString + ", value=" + value);

            EndorsementType endorsementType = EndorsementType.valueOf(typeString.toUpperCase());
            ComponentEndorsement e = endorsementType.parse(value);
            endorsements.add(e);
            //         System.out.println("Endorsement " + e);
        }

        return new ComponentRequest(endorsements, componentId, componentType);
    }

    public static class ComponentRequest {
        private final List<ComponentEndorsement> endorsements;
        private final ComponentId componentId;
        private final ComponentType componentType;

        private ComponentRequest(List<ComponentEndorsement> endorsements, ComponentId componentId,
                ComponentType componentType) {
            super();
            this.endorsements = endorsements;
            this.componentId = componentId;
            this.componentType = componentType;
        }

    }

    private static List<String> splitWell(String text, String delimiter) {
        List<String> parts = new LinkedList<String>();

        for (String next : text.split(delimiter)) {
            if (next.trim().length() > 0) {
                parts.add(next);
            }
        }

        return parts;
    }
}