Java tutorial
/**************************************************************************** * 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); } }