ee.ria.xroad.proxy.testsuite.DummyService.java Source code

Java tutorial

Introduction

Here is the source code for ee.ria.xroad.proxy.testsuite.DummyService.java

Source

/**
 * The MIT License
 * Copyright (c) 2015 Estonian Information System Authority (RIA), Population Register Centre (VRK)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package ee.ria.xroad.proxy.testsuite;

import ee.ria.xroad.common.TestCertUtil;
import ee.ria.xroad.common.TestCertUtil.PKCS12;
import ee.ria.xroad.common.util.CryptoUtils;
import ee.ria.xroad.common.util.StartStop;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;

import javax.net.ssl.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import static ee.ria.xroad.common.ErrorCodes.translateException;

@Slf4j
class DummyService extends Server implements StartStop {

    private static X509Certificate serverCert;
    private static PrivateKey serverKey;

    DummyService() {
        super();
        try {
            setupConnectors();
            setHandler(new ServiceHandler());
        } catch (Exception e) {
            throw translateException(e);
        }
    }

    private void setupConnectors() throws Exception {
        ServerConnector connector = new ServerConnector(this);
        connector.setName("httpConnector");
        connector.setPort(ProxyTestSuite.SERVICE_PORT);
        connector.setSoLingerTime(0);
        addConnector(connector);

        ServerConnector sslConnector = createSslConnector();
        sslConnector.setName("httpsConnector");
        sslConnector.setPort(ProxyTestSuite.SERVICE_SSL_PORT);
        sslConnector.setSoLingerTime(0);
        addConnector(sslConnector);
    }

    private ServerConnector createSslConnector() throws Exception {
        PKCS12 consumer = TestCertUtil.getConsumer();
        serverCert = consumer.cert;
        serverKey = consumer.key;

        SslContextFactory cf = new SslContextFactory(false);
        cf.setNeedClientAuth(true);

        cf.setIncludeCipherSuites(CryptoUtils.getINCLUDED_CIPHER_SUITES());
        cf.setSessionCachingEnabled(true);

        SSLContext ctx = SSLContext.getInstance(CryptoUtils.SSL_PROTOCOL);
        ctx.init(new KeyManager[] { new DummyServiceKeyManager() },
                new TrustManager[] { new DummyServiceTrustManager() }, new SecureRandom());

        cf.setSslContext(ctx);

        return new ServerConnector(this, cf);
    }

    private class ServiceHandler extends AbstractHandler {
        @Override
        public void handle(String target, Request baseRequest, HttpServletRequest request,
                HttpServletResponse response) throws IOException, ServletException {
            log.debug("Service simulator received request {}, contentType={}", target, request.getContentType());
            debugRequestHeaders(request);
            try {
                // check if the test case implements custom service response
                AbstractHandler handler = currentTestCase().getServiceHandler();
                if (handler != null) {
                    handler.handle(target, baseRequest, request, response);
                    return;
                }

                currentTestCase().onServiceReceivedHttpRequest(request);

                Message receivedRequest = new Message(request.getInputStream(), request.getContentType()).parse();

                String encoding = request.getCharacterEncoding();

                log.debug("Request: encoding={}, soap={}", encoding, receivedRequest.getSoap());

                currentTestCase().onServiceReceivedRequest(receivedRequest);

                String responseFile = currentTestCase().getResponseFile();

                if (responseFile != null) {
                    try {
                        sendResponseFromFile(responseFile, response);
                    } catch (Exception e) {
                        log.error("An error has occurred when sending response" + " from file '{}': {}",
                                responseFile, e);
                    }
                } else {
                    log.error("Unknown request {}", target);
                }
            } catch (Exception ex) {
                response.sendError(HttpStatus.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
                log.error("Error when reading request", ex);
            } finally {
                baseRequest.setHandled(true);
            }
        }

        private void debugRequestHeaders(HttpServletRequest request) {
            log.debug("Request headers:");

            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                log.debug("\t{} = {}", headerName, request.getHeader(headerName));
            }
        }

        private void sendResponseFromFile(String fileName, HttpServletResponse response) throws Exception {
            String responseContentType = currentTestCase().getResponseContentType();

            log.debug("Sending response, content-type = {}, BOM = {}", responseContentType,
                    currentTestCase().addUtf8BomToResponseFile);

            response.setContentType(responseContentType);
            response.setStatus(HttpServletResponse.SC_OK);

            String file = MessageTestCase.QUERIES_DIR + '/' + fileName;

            try (InputStream fileIs = new FileInputStream(file);
                    InputStream responseIs = currentTestCase().changeQueryId(fileIs)) {

                if (currentTestCase().addUtf8BomToResponseFile) {
                    response.getOutputStream().write(ByteOrderMark.UTF_8.getBytes());
                }

                IOUtils.copy(responseIs, response.getOutputStream());
            }

            try (InputStream fileIs = new FileInputStream(file);
                    InputStream responseIs = currentTestCase().changeQueryId(fileIs)) {
                currentTestCase().onSendResponse(
                        new Message(responseIs, currentTestCase().getResponseServiceContentType()).parse());
            } catch (Exception e) {
                log.error("Error when sending response from file '{}': {}", file, e.toString());
            }
        }
    }

    private static MessageTestCase currentTestCase() {
        return ProxyTestSuite.currentTestCase;
    }

    private static class DummyServiceKeyManager extends X509ExtendedKeyManager {

        private static final String ALIAS = "AuthKeyManager";

        @Override
        public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
            log.debug("chooseClientAlias");
            return ALIAS;
        }

        @Override
        public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
            log.debug("chooseServerAlias");
            return ALIAS;
        }

        @Override
        public X509Certificate[] getCertificateChain(String alias) {
            return new X509Certificate[] { serverCert };
        }

        @Override
        public String[] getClientAliases(String keyType, Principal[] issuers) {
            log.debug("getClientAliases");
            return null;
        }

        @Override
        public PrivateKey getPrivateKey(String alias) {
            log.debug("getPrivateKey {} - {}", alias, serverKey);
            return serverKey;
        }

        @Override
        public String[] getServerAliases(String keyType, Principal[] issuers) {
            log.debug("getServerAliases");
            return null;
        }

        @Override
        public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
            log.debug("chooseEngineClientAlias");
            return ALIAS;
        }

        @Override
        public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
            log.debug("chooseEngineServerAlias");
            return ALIAS;
        }
    }

    private static class DummyServiceTrustManager implements X509TrustManager {

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            log.debug("getAcceptedIssuers {}", serverCert);
            return new X509Certificate[] { serverCert };
        }

        @Override
        public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
            log.debug("checkClientTrusted");
        }

        @Override
        public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
            log.debug("checkServerTrusted");
        }
    }
}