org.electrologic.convergence.server.TargetServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.electrologic.convergence.server.TargetServlet.java

Source

/****************************************************************************
 * Copyright 2013 Tobias Wich
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************************/

package org.electrologic.convergence.server;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.regex.Pattern;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.electrologic.convergence.server.cache.Cache;
import org.electrologic.convergence.server.cache.CacheResult;
import org.electrologic.convergence.server.util.FingerprintList;
import org.electrologic.convergence.server.util.Sha1RSASignature;
import org.electrologic.convergence.server.verifier.InternalVerificationError;
import org.electrologic.convergence.server.verifier.VerificationResultCode;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * This class implements the endpoint of the convergence target interface.
 * A description of its usage can be found at the <a href="https://github.com/moxie0/Convergence/wiki/Notary-Protocol">
 * Convergence Wiki</a>.
 *
 * @author Tobias Wich <tobias.wich@ecsec.de>
 */
@WebServlet("/target/*")
public class TargetServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private Cache cache;
    private Sha1RSASignature signer;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        ServletContext ctx = config.getServletContext();
        cache = (Cache) ctx.getAttribute(TargetConfigurator.CACHEPATH);
        signer = (Sha1RSASignature) ctx.getAttribute(TargetConfigurator.SIGNERPATH);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            // extract host and port
            String[] hostPort = extractHostPort(req);
            String host = hostPort[0];
            int port = getPort(hostPort[1]);

            CacheResult cacheResult = cache.queryOrUpdateCache(host, port);
            updateResponse(cacheResult, resp);
        } catch (ParameterException ex) {
            sendError(ex.getMessage(), VerificationResultCode.PARAMETER_MISSING.code, resp);
        } catch (JSONException ex) {
            sendError(ex.getMessage(), VerificationResultCode.INTERNAL_ERROR.code, resp);
        } catch (GeneralSecurityException ex) {
            sendError(ex.getMessage(), VerificationResultCode.INTERNAL_ERROR.code, resp);
        } catch (InternalVerificationError ex) {
            sendError(ex.getMessage(), ex.getCode().code, resp);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            // extract host, port and fingerprint
            String[] hostPort = extractHostPort(req);
            String host = hostPort[0];
            int port = getPort(hostPort[1]);
            String fingerprint = getFingerprint(req);

            CacheResult cacheResult = cache.queryOrUpdateCache(host, port, fingerprint);
            updateResponse(cacheResult, resp);
        } catch (ParameterException ex) {
            sendError(ex.getMessage(), VerificationResultCode.PARAMETER_MISSING.code, resp);
        } catch (JSONException ex) {
            sendError(ex.getMessage(), VerificationResultCode.INTERNAL_ERROR.code, resp);
        } catch (GeneralSecurityException ex) {
            sendError(ex.getMessage(), VerificationResultCode.INTERNAL_ERROR.code, resp);
        } catch (InternalVerificationError ex) {
            sendError(ex.getMessage(), ex.getCode().code, resp);
        }
    }

    private String[] extractHostPort(HttpServletRequest req) throws ParameterException {
        String uri = req.getRequestURI();
        String pathPrefix = req.getContextPath();
        uri = uri.substring(pathPrefix.length());
        String[] pathParts = uri.split(Pattern.quote("/"));
        if (pathParts.length != 3) {
            throw new ParameterException("Host and port entries missing in request.");
        }
        String[] hostPort = pathParts[2].split(Pattern.quote("+"));
        if (hostPort.length != 2) {
            throw new ParameterException("Host and port part of URL not matching the service specification.");
        }
        return hostPort;
    }

    private int getPort(String portStr) throws ParameterException {
        int port = 0;
        try {
            port = Integer.parseInt(portStr);
        } catch (NumberFormatException ex) {
            throw new ParameterException("Specified port is not a number.");
        }
        return port;
    }

    private String getFingerprint(HttpServletRequest req) throws ParameterException {
        String fp = req.getParameter("fingerprint");
        if (fp == null) {
            throw new ParameterException("Fingerprint parameter is missing.");
        }
        return fp;
    }

    private void updateResponse(CacheResult cacheResult, HttpServletResponse resp)
            throws JSONException, GeneralSecurityException, IOException {
        // create fingerprint and generate response data
        FingerprintList result = new FingerprintList(cacheResult.getEntries(), signer);
        JSONObject resultData = result.getSignedJSON();
        String resultDataStr = resultData.toString();
        // write everything to the response
        resp.setStatus(cacheResult.getResultCode().code);
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json");
        resp.getOutputStream().print(resultDataStr);
    }

    private void sendError(String message, int code, HttpServletResponse resp) throws IOException {
        // TODO: make fancy error page
        resp.sendError(code, message);
    }

}