Java tutorial
/* * Copyright 2013 Hewlett-Packard Development Company, L.P * * 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 com.hp.alm.ali; import org.apache.commons.io.IOUtils; 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.junit.Assert; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class Handler extends AbstractHandler { final private LinkedList<MyRequest> requests; private LinkedList<Runnable> cleanup; private Throwable firstError; private Semaphore async = new Semaphore(100); private ServerVersion version; public Handler(ServerVersion version) throws Exception { this.version = version; this.requests = new LinkedList<MyRequest>(); this.cleanup = new LinkedList<Runnable>(); new Server(0).setHandler(this); } public void async() { async(1); } public void async(int count) { async.acquireUninterruptibly(count); } public void done() { done(1); } public void done(int count) { async.release(count); } public void fail(String message) { if (firstError == null) { try { Assert.fail(message); } catch (Throwable t) { firstError = t; } } done(); } public void done(Runnable runnable) { if (firstError == null) { try { runnable.run(); } catch (Throwable t) { firstError = t; } } done(); } public MyRequest addRequest(String method, String url, int responseCode) { return addRequest(true, method, url, responseCode); } public MyRequest addRequest(boolean strict, String method, String url, int responseCode) { MyRequest request = new MyRequest(strict, method, url, responseCode); synchronized (requests) { requests.add(request); } return request; } public int getLocalPort() { return ((ServerConnector) getServer().getConnectors()[0]).getLocalPort(); } public String getQcUrl() { return getServerUrl("/qcbin"); } public String getServerUrl(String path) { return "http://localhost:" + getLocalPort() + path; } @Override public void handle(String url, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String urlWithQuery = baseRequest.getUri().getPath(); if (baseRequest.getUri().hasQuery()) { urlWithQuery += "?" + URLDecoder.decode(baseRequest.getQueryString(), "UTF-8"); } System.out.println("[incoming] " + baseRequest.getMethod() + " " + urlWithQuery); baseRequest.setHandled(true); if (firstError != null) { System.out.println("[ignored]"); // once there was an error, simply fail all requests response.setStatus(500); return; } MyRequest myRequest = null; try { synchronized (requests) { for (MyRequest candidate : requests) { if (candidate.strict) { break; } try { Assert.assertEquals(candidate.method, baseRequest.getMethod()); Assert.assertEquals(candidate.url, urlWithQuery); candidate.evaluateAssertions(baseRequest, request, response, true); requests.remove(candidate); myRequest = candidate; break; } catch (Throwable t) { // negative } } if (myRequest == null) { if (requests.isEmpty()) { throw new Exception("Unexpected request: " + baseRequest.getMethod() + " " + urlWithQuery); } myRequest = requests.removeFirst(); } requests.notifyAll(); } Assert.assertEquals(myRequest.method, baseRequest.getMethod()); Assert.assertEquals(myRequest.url, urlWithQuery); myRequest.evaluateAssertions(baseRequest, request, response, false); myRequest.evaluateActions(response); if (myRequest.reasonPhrase != null) { response.setStatus(myRequest.responseCode, myRequest.reasonPhrase); } else { response.setStatus(myRequest.responseCode); } System.out.println("[success]"); } catch (Throwable t) { System.out.println("[failed] " + t.getMessage()); firstError = t; response.setStatus(500); async.release(100); } } public void authenticate() { addRequest("POST", "/qcbin/authentication-point/alm-authenticate", 200).expectXmlBody( "<alm-authentication><user>user</user><password>password</password></alm-authentication>"); addRequest("POST", "/qcbin/rest/site-session", 200).expectXmlBody( "<session-parameters><client-type>ALI_IDEA_plugin</client-type></session-parameters>"); } public void checkpoint() throws Throwable { Assert.assertTrue("Test timed out", async.tryAcquire(100, 2000, TimeUnit.MILLISECONDS)); async.release(100); } public void finish() throws Throwable { Assert.assertTrue("Test timed out", async.tryAcquire(100, 2000, TimeUnit.MILLISECONDS)); if (firstError != null) { throw firstError; } Assert.assertTrue("There are unresponded requests", requests.isEmpty()); for (Runnable action : cleanup) { action.run(); } } public void clear() { async = new Semaphore(100); firstError = null; requests.clear(); cleanup.clear(); } public String getContent(String content) throws IOException { InputStream is = Handler.class.getResourceAsStream("/" + version.name() + "/" + content); if (is == null) { is = Handler.class.getResourceAsStream("/" + content); } if (is == null) { throw new IOException("Content '" + content + "' not available for '" + version + "'."); } else { return IOUtils.toString(is); } } public void consume() throws RuntimeException { if (firstError != null) { throw new RuntimeException(firstError); } synchronized (requests) { while (!requests.isEmpty()) { try { requests.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public ServerVersion getVersion() { return version; } public void addCleanup(Runnable action) { cleanup.add(action); } private interface Assertion { void evaluate(Request baseRequest, HttpServletRequest request, HttpServletResponse response, boolean soft) throws IOException; } private interface Action { void evaluate(HttpServletResponse response) throws IOException; } public class MyRequest { private List<Assertion> assertions; private List<Action> actions; private boolean strict; private String method; private String url; private int responseCode; private String reasonPhrase; private MyRequest(boolean strict, String method, String url, int responseCode) { this.strict = strict; this.method = method; this.url = url; this.responseCode = responseCode; assertions = new LinkedList<Assertion>(); actions = new LinkedList<Action>(); } public void evaluateAssertions(Request baseRequest, HttpServletRequest request, HttpServletResponse response, boolean soft) throws IOException { for (Assertion assertion : assertions) { assertion.evaluate(baseRequest, request, response, soft); } } public void evaluateActions(HttpServletResponse response) throws IOException { for (Action action : actions) { action.evaluate(response); } } public MyRequest expectHeader(final String header, final String value) { assertions.add(new Assertion() { @Override public void evaluate(Request baseRequest, HttpServletRequest request, HttpServletResponse response, boolean soft) { Assert.assertEquals(value, baseRequest.getHeader(header)); } }); return this; } public MyRequest expectXmlBody(final String value) { assertions.add(new Assertion() { @Override public void evaluate(Request baseRequest, HttpServletRequest request, HttpServletResponse response, boolean soft) throws IOException { if (!soft) { Assert.assertEquals( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + value.replaceAll("\r\n", "\n") + "\n", IOUtils.toString(baseRequest.getInputStream()).replaceAll("\r\n", "\n")); } } }); return this; } public MyRequest expectBody(final String value) { assertions.add(new Assertion() { @Override public void evaluate(Request baseRequest, HttpServletRequest request, HttpServletResponse response, boolean soft) throws IOException { if (!soft) { Assert.assertEquals(value, IOUtils.toString(baseRequest.getInputStream())); } } }); return this; } public MyRequest responseHeader(final String header, final String value) { actions.add(new Action() { @Override public void evaluate(HttpServletResponse response) { response.addHeader(header, value); } }); return this; } public MyRequest responseBody(final String value) { actions.add(new Action() { @Override public void evaluate(HttpServletResponse response) throws IOException { response.getWriter().write(value); } }); return this; } public MyRequest reasonPhrase(String reasonPhrase) { this.reasonPhrase = reasonPhrase; return this; } public MyRequest content(final String content) { actions.add(new Action() { @Override public void evaluate(HttpServletResponse response) throws IOException { response.getWriter().write(getContent(content)); } }); return this; } } }