diff --git a/DEVELOPING.md b/DEVELOPING.md index 07ce23c5a3..df7fd0d9f4 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -63,3 +63,33 @@ To run the integration tests in an isolated environment, run docker build . if you have a Docker Engine available. + + +Examples Tests +============== + +The example tests try to run the service-proxy.sh/bat scripts in the examples folders of a +distribution build in the target folder. Remember to build after any change otherwise old code +is tested: + +Build a distribution in target/ . Then run the example tests. +```sh +mvn clean install -DskipTests +``` + + +## Prequisites + +On Mac OS the `setsid` command is needed. It can be installed with: + +```sh +brew install util-linux +``` + +## Running + +Run Testclass `ExampleTests` + +## Troubleshooting + +- \ No newline at end of file diff --git a/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java b/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java index c1221ece9f..36e847fb02 100644 --- a/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java +++ b/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java @@ -47,6 +47,8 @@ import com.predic8.membrane.annot.model.OtherAttributesInfo; import com.predic8.membrane.annot.model.doc.Doc; +import static java.util.Comparator.comparing; + public class HelpReference { private final ProcessingEnvironment processingEnv; @@ -63,7 +65,7 @@ public void writeHelp(Model m) { String path = System.getenv("MEMBRANE_GENERATE_DOC_DIR"); if (path == null) return; - path = path.replace("%VERSION%", "4.8"); + path = path.replace("%VERSION%", "5.0"); sw = new StringWriter(); XMLOutputFactory output = XMLOutputFactory.newInstance(); @@ -87,7 +89,7 @@ public void writeHelp(Model m) { } private String getFileName(Model m) { - ArrayList packages = new ArrayList(); + ArrayList packages = new ArrayList<>(); for (MainInfo mi : m.getMains()) packages.add(mi.getAnnotation().outputPackage()); Collections.sort(packages); @@ -111,15 +113,7 @@ private void handle(Model m, MainInfo main) throws XMLStreamException { xew.writeStartElement("namespace"); xew.writeAttribute("package", main.getAnnotation().outputPackage()); xew.writeAttribute("targetNamespace", main.getAnnotation().targetNamespace()); - Collections.sort(main.getIis(), new Comparator() { - @Override - public int compare(ElementInfo o1, ElementInfo o2) { - int res = o1.getAnnotation().name().compareTo(o2.getAnnotation().name()); - if (res == 0) - res = o1.getElement().getQualifiedName().toString().compareTo(o2.getElement().getQualifiedName().toString()); - return res; - } - }); + main.getIis().sort(comparing((ElementInfo o) -> o.getAnnotation().name()).thenComparing(o -> o.getElement().getQualifiedName().toString())); for (ElementInfo ei : main.getIis()) handle(m, main, ei); xew.writeEndElement(); @@ -141,14 +135,7 @@ private void handle(Model m, MainInfo main, ElementInfo ei) throws XMLStreamExce handleDoc(ei); List ais = ei.getAis(); - Collections.sort(ais, new Comparator() { - - @Override - public int compare(AttributeInfo o1, AttributeInfo o2) { - return o1.getXMLName().compareTo(o2.getXMLName()); - } - - }); + ais.sort(comparing(AttributeInfo::getXMLName)); OtherAttributesInfo oai = ei.getOai(); if (ais.size() > 0 && ais.get(0).getXMLName().equals("id")) @@ -179,7 +166,7 @@ public int compare(AttributeInfo o1, AttributeInfo o2) { private String getPrimaryParentId(Model m, MainInfo mi, ElementInfo ei) { // choose a random parent (TODO: choose a better one) - Set possibleParents = new HashSet(); + Set possibleParents = new HashSet<>(); for (Map.Entry e : mi.getChildElementDeclarations().entrySet()) if (e.getValue().getElementInfo().contains(ei)) { for (ChildElementInfo usedBy : e.getValue().getUsedBy()) { @@ -217,7 +204,7 @@ private void handle(Model m, MainInfo main, ChildElementInfo cei) throws XMLStre handleDoc(cei); - SortedSet possibilities = new TreeSet(); + SortedSet possibilities = new TreeSet<>(); for (ElementInfo ei : main.getChildElementDeclarations().get(cei.getTypeDeclaration()).getElementInfo()) { possibilities.add(ei.getId()); } diff --git a/core/pom.xml b/core/pom.xml index 5a8b20bc0b..84495e21df 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -51,6 +51,11 @@ commons-discovery commons-discovery + + org.apache.commons + commons-text + 1.10.0 + com.fasterxml.jackson.core @@ -74,7 +79,7 @@ org.json json - 20211205 + 20220924 @@ -155,6 +160,29 @@ spring-web + + + org.mozilla + rhino-engine + 1.7.14 + test + + + + org.graalvm.sdk + graal-sdk + 22.3.0 + provided + + + + + org.graalvm.js + js + 22.3.0 + test + + org.junit.jupiter junit-jupiter-api diff --git a/core/src/main/java/com/predic8/membrane/balancer/client/LBNotificationClient.java b/core/src/main/java/com/predic8/membrane/balancer/client/LBNotificationClient.java index 1a0fe60540..d3231ddc51 100644 --- a/core/src/main/java/com/predic8/membrane/balancer/client/LBNotificationClient.java +++ b/core/src/main/java/com/predic8/membrane/balancer/client/LBNotificationClient.java @@ -18,6 +18,7 @@ import java.io.FileInputStream; import java.io.InputStream; import java.net.URLEncoder; +import java.nio.charset.*; import java.security.SecureRandom; import java.util.Properties; @@ -38,6 +39,10 @@ import com.predic8.membrane.core.transport.http.HttpClient; import com.predic8.membrane.core.util.MessageUtil; +import static java.nio.charset.StandardCharsets.*; +import static javax.crypto.Cipher.ENCRYPT_MODE; +import static org.apache.commons.codec.binary.Base64.encodeBase64; + public class LBNotificationClient { private static Logger log = LoggerFactory.getLogger(LBNotificationClient.class.getName()); @@ -81,8 +86,7 @@ private Response notifiyClusterManager() throws Exception { r.setBodyContent(new byte[0]); exc.setRequest(r); exc.getDestinations().add(getRequestURL()); - Response res = client.call(exc).getResponse(); - return res; + return client.call(exc).getResponse(); } private void parseArguments(CommandLine cl) throws Exception { @@ -114,11 +118,8 @@ private String getArgument(CommandLine cl, int clArgPos, char option, if (prop != null && new File(propertiesFile).exists()) { Properties props = new Properties(); - InputStream is = new FileInputStream(propertiesFile); - try { + try (InputStream is = new FileInputStream(propertiesFile)) { props.load(is); - } finally { - is.close(); } if (props.containsKey(prop)) { return props.getProperty(prop); @@ -141,7 +142,7 @@ private String getQueryString() { private String getRequestURL() throws Exception { if (skeySpec!=null) { return cmURL + "/" + cmd + "?data="+ - URLEncoder.encode(getEncryptedQueryString(),"UTF-8"); + URLEncoder.encode(getEncryptedQueryString(), UTF_8); } String time = String.valueOf(System.currentTimeMillis()); return cmURL + "/" + cmd + "?balancer=" + balancer + "&cluster=" + cluster + "&host=" + host + "&port=" + port + "&time=" + time; @@ -150,8 +151,8 @@ private String getRequestURL() throws Exception { private String getEncryptedQueryString() throws Exception { Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.ENCRYPT_MODE, skeySpec); - return new String(Base64.encodeBase64(cipher.doFinal(getQueryString().getBytes("UTF-8"))),"UTF-8"); + cipher.init(ENCRYPT_MODE, skeySpec); + return new String(encodeBase64(cipher.doFinal(getQueryString().getBytes(UTF_8))), UTF_8); } private void logArguments() { diff --git a/core/src/main/java/com/predic8/membrane/core/Router.java b/core/src/main/java/com/predic8/membrane/core/Router.java index fa82b84e7f..b952efc8f8 100644 --- a/core/src/main/java/com/predic8/membrane/core/Router.java +++ b/core/src/main/java/com/predic8/membrane/core/Router.java @@ -62,6 +62,9 @@ import javax.annotation.concurrent.GuardedBy; +import static com.predic8.membrane.core.jmx.JmxExporter.JMX_EXPORTER_NAME; +import static java.util.stream.Collectors.toList; + /** * @description

* Membrane Service Proxy's main object. @@ -93,7 +96,7 @@ public class Router implements Lifecycle, ApplicationContextAware, BeanNameAware * app context, we track them here, so they start only one * HotDeploymentThread. */ - protected static final HashSet hotDeployingContexts = new HashSet(); + protected static final HashSet hotDeployingContexts = new HashSet<>(); private ApplicationContext beanFactory; private String baseLocation; @@ -158,6 +161,7 @@ public static Router init(String resource, ClassLoader classLoader) { return (Router) beanFactory.getBean("router"); } + @SuppressWarnings("NullableProblems") @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { beanFactory = applicationContext; @@ -202,7 +206,7 @@ public HttpClientConfiguration getHttpClientConfig() { return resolverMap.getHTTPSchemaResolver().getHttpClientConfig(); } - @MCChildElement(order=0) + @MCChildElement() public void setHttpClientConfig(HttpClientConfiguration httpClientConfig) { resolverMap.getHTTPSchemaResolver().setHttpClientConfig(httpClientConfig); } @@ -270,14 +274,12 @@ public void init() throws Exception { } private void initRemainingRules() throws Exception { - List otherRules = getRuleManager().getRules().stream().filter(r -> !(r instanceof InternalProxy)).collect(Collectors.toList()); - for (Rule rule : otherRules) + for (Rule rule : getRuleManager().getRules().stream().filter(r -> !(r instanceof InternalProxy)).collect(toList())) rule.init(this); } private void initInternalProxies() throws Exception { - List internalProxies = getRuleManager().getRules().stream().filter(r -> r instanceof InternalProxy).collect(Collectors.toList()); - for (Rule rule : internalProxies) + for (Rule rule : getRuleManager().getRules().stream().filter(r -> r instanceof InternalProxy).collect(toList())) rule.init(this); } @@ -321,12 +323,9 @@ public void start() { private void startJmx() { if(getBeanFactory() != null) { try{ - Object exporterObj = getBeanFactory().getBean(JmxExporter.JMX_EXPORTER_NAME); - if (exporterObj != null) { - ((JmxExporter) exporterObj).initAfterBeansAdded(); - } + ((JmxExporter) getBeanFactory().getBean(JMX_EXPORTER_NAME)).initAfterBeansAdded(); }catch(NoSuchBeanDefinitionException ignored){ - // If bean is not available, then dont start jmx + // If bean is not available, then don't start jmx } } } @@ -334,13 +333,9 @@ private void startJmx() { private void initJmx() { if (beanFactory != null) { try { - Object exporterObj = beanFactory.getBean(JmxExporter.JMX_EXPORTER_NAME); - if (exporterObj != null) { - JmxExporter exporter = (JmxExporter) exporterObj; - String prefix = "org.membrane-soa:00=routers, name="; - //exporter.removeBean(prefix + jmxRouterName); - exporter.addBean(prefix + jmxRouterName, new JmxRouter(this, exporter)); - } + JmxExporter exporter = (JmxExporter) beanFactory.getBean(JMX_EXPORTER_NAME); + //exporter.removeBean(prefix + jmxRouterName); + exporter.addBean("org.membrane-soa:00=routers, name=" + jmxRouterName, new JmxRouter(this, exporter)); }catch(NoSuchBeanDefinitionException ignored){ // If bean is not available, then dont init jmx } @@ -459,7 +454,7 @@ public boolean isRunning() { * is created by a Spring Application Context which supports monitoring. *

* @default true - * @param hotDeploy + * @param hotDeploy If true the hot deploy feature is activated */ @MCAttribute public void setHotDeploy(boolean hotDeploy) { @@ -490,7 +485,7 @@ public void setRetryInitInterval(int retryInitInterval) { } private ArrayList getInactiveRules() { - ArrayList inactive = new ArrayList(); + ArrayList inactive = new ArrayList<>(); for (Rule rule : getRuleManager().getRules()) if (!rule.isActive()) inactive.add(rule); @@ -558,6 +553,7 @@ public String getJmx(){ return jmxRouterName; } + @SuppressWarnings("NullableProblems") @Override public void setBeanName(String s) { this.id = s; diff --git a/core/src/main/java/com/predic8/membrane/core/RouterCLI.java b/core/src/main/java/com/predic8/membrane/core/RouterCLI.java index 5e39c14f87..fee2d12d96 100755 --- a/core/src/main/java/com/predic8/membrane/core/RouterCLI.java +++ b/core/src/main/java/com/predic8/membrane/core/RouterCLI.java @@ -17,6 +17,7 @@ import java.io.File; import com.predic8.membrane.core.kubernetes.KubernetesWatcher; +import com.predic8.membrane.core.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException; @@ -31,100 +32,122 @@ public class RouterCLI { private static final Logger LOG = LoggerFactory.getLogger(RouterCLI.class); - public static void main(String[] args) { - - MembraneCommandLine cl = new MembraneCommandLine(); - Router router = null; - try { - cl.parse(args); - if (cl.needHelp()) { - cl.printUsage(); - return; - } - - try { - router = Router.init(getRulesFile(cl), RouterCLI.class.getClassLoader()); - } catch (XmlBeanDefinitionStoreException e) { - TrackingFileSystemXmlApplicationContext.handleXmlBeanDefinitionStoreException(e); - } - } catch (InvalidConfigurationException e) { - System.err.println("Fatal error: " + e.getMessage()); - System.exit(1); - } catch (Exception ex) { - ex.printStackTrace(); - System.exit(1); - } - - try { - if (router != null) - router.waitFor(); - } catch (InterruptedException e) { - // do nothing - } - } - - private static String getRulesFile(MembraneCommandLine line) { - ResolverMap rm = new ResolverMap(); - if (line.hasConfiguration()) { - String s = line.getConfiguration().replaceAll("\\\\", "/"); - if (s.startsWith("file:") || s.startsWith("/") || s.length() > 3 && s.substring(1, 3).equals(":/")) { - // absolute - try { - rm.resolve(s); - return s; - } catch (ResourceRetrievalException e) { - System.err.println("Could not open Membrane's configuration file: " + s + " not found."); - System.exit(1); - } - } - return getRulesFileFromRelativeSpec(rm, s, ""); - } else { - String errorNotice = "Please specify the location of Membrane's proxies.xml configuration file using the -c command line option."; - if (System.getenv("MEMBRANE_HOME") != null) { - errorNotice += " Or create the file in MEMBRANE_HOME/conf (" + System.getenv("MEMBRANE_HOME") + "/conf/proxies.xml)."; - } else { - errorNotice += " You can also point the MEMBRANE_HOME environment variable to Membrane's distribution root directory "+ - "and ensure that MEMBRANE_HOME/conf/proxies.xml exists."; - } - return getRulesFileFromRelativeSpec(rm, "conf/proxies.xml", errorNotice); - } - } - - private static String getRulesFileFromRelativeSpec(ResolverMap rm, String relativeFile, String errorNotice) { - String membraneHome = System.getenv("MEMBRANE_HOME"); - String userDir = System.getProperty("user.dir").replaceAll("\\\\", "/"); - if (!userDir.endsWith("/")) - userDir += "/"; - String try1 = ResolverMap.combine(prefix(userDir), relativeFile); - try { - rm.resolve(try1); - return try1; - } catch (ResourceRetrievalException e) { - } - String try2 = null; - if (membraneHome != null) { - try2 = ResolverMap.combine(prefix(membraneHome), relativeFile); - try { - rm.resolve(try2); - return try2; - } catch (ResourceRetrievalException e) { - } - } - System.err.println("Could not find Membrane's configuration file at " + try1 + (try2 == null ? "" : " and not at " + try2) + " . " + errorNotice); - System.exit(1); - throw new RuntimeException(); - } - - private static String prefix(String dir) { - - String result = dir; - - File file = new File(dir); - if (file.isAbsolute()) { - result = file.toURI().toString(); - } - - return result; - } - + public static void main(String[] args) { + + MembraneCommandLine cl = new MembraneCommandLine(); + Router router = null; + try { + cl.parse(args); + if (cl.needHelp()) { + cl.printUsage(); + return; + } + + try { + router = Router.init(getRulesFile(cl), RouterCLI.class.getClassLoader()); + } catch (XmlBeanDefinitionStoreException e) { + TrackingFileSystemXmlApplicationContext.handleXmlBeanDefinitionStoreException(e); + } + } catch (InvalidConfigurationException e) { + System.err.println("Fatal error: " + e.getMessage()); + System.exit(1); + } catch (Exception ex) { + handleExitException(ex); + ex.printStackTrace(); + System.exit(1); + } + + try { + if (router != null) + router.waitFor(); + } catch (InterruptedException e) { + // do nothing + } + } + + private static void handleExitException(Exception ex) { + ExitException exitException = extractExitExcetpion(ex); + if (exitException == null) + return; + + System.err.println("**********************************************************************************"); + System.err.println(); + System.err.println(exitException.getMessage()); + System.err.println(); + System.err.println("**********************************************************************************"); + System.exit(1); + } + + private static ExitException extractExitExcetpion(Throwable ex) { + if (ex instanceof ExitException) + return (ExitException) ex; + if (ex.getCause() == null) + return null; + if (ex.getCause() instanceof ExitException) + return (ExitException) ex.getCause(); + return extractExitExcetpion(ex.getCause()); + } + + private static String getRulesFile(MembraneCommandLine line) { + ResolverMap rm = new ResolverMap(); + if (line.hasConfiguration()) { + String s = line.getConfiguration().replaceAll("\\\\", "/"); + if (s.startsWith("file:") || s.startsWith("/") || s.length() > 3 && s.startsWith(":/", 1)) { + // absolute + try { + rm.resolve(s); + return s; + } catch (ResourceRetrievalException e) { + System.err.println("Could not open Membrane's configuration file: " + s + " not found."); + System.exit(1); + } + } + return getRulesFileFromRelativeSpec(rm, s, ""); + } else { + String errorNotice = "Please specify the location of Membrane's proxies.xml configuration file using the -c command line option."; + if (System.getenv("MEMBRANE_HOME") != null) { + errorNotice += " Or create the file in MEMBRANE_HOME/conf (" + System.getenv("MEMBRANE_HOME") + "/conf/proxies.xml)."; + } else { + errorNotice += " You can also point the MEMBRANE_HOME environment variable to Membrane's distribution root directory " + + "and ensure that MEMBRANE_HOME/conf/proxies.xml exists."; + } + return getRulesFileFromRelativeSpec(rm, "conf/proxies.xml", errorNotice); + } + } + + private static String getRulesFileFromRelativeSpec(ResolverMap rm, String relativeFile, String errorNotice) { + String membraneHome = System.getenv("MEMBRANE_HOME"); + String userDir = System.getProperty("user.dir").replaceAll("\\\\", "/"); + if (!userDir.endsWith("/")) + userDir += "/"; + String try1 = ResolverMap.combine(prefix(userDir), relativeFile); + try { + rm.resolve(try1); + return try1; + } catch (ResourceRetrievalException e) { + // ignored + } + String try2 = null; + if (membraneHome != null) { + try2 = ResolverMap.combine(prefix(membraneHome), relativeFile); + try { + rm.resolve(try2); + return try2; + } catch (ResourceRetrievalException e) { + // ignored + } + } + System.err.println("Could not find Membrane's configuration file at " + try1 + (try2 == null ? "" : " and not at " + try2) + " . " + errorNotice); + System.exit(1); + throw new RuntimeException(); + } + + private static String prefix(String dir) { + File file = new File(dir); + if (file.isAbsolute()) { + return file.toURI().toString(); + } + + return dir; + } } diff --git a/core/src/main/java/com/predic8/membrane/core/http/MimeType.java b/core/src/main/java/com/predic8/membrane/core/http/MimeType.java index 7edcd1fe08..cc1f8d7c44 100644 --- a/core/src/main/java/com/predic8/membrane/core/http/MimeType.java +++ b/core/src/main/java/com/predic8/membrane/core/http/MimeType.java @@ -22,9 +22,12 @@ */ public class MimeType { + public static final String APPLICATION = "application"; + public static final String APPLICATION_SOAP = "application/soap+xml"; public static final String APPLICATION_XML = "application/xml"; public static final String TEXT_XML = "text/xml"; + public static final String TEXT_HTML = "text/html"; public static final String TEXT_XML_UTF8 = TEXT_XML + ";charset=UTF-8"; public static final String TEXT_HTML_UTF8 = "text/html;charset=UTF-8"; @@ -46,9 +49,13 @@ public class MimeType { public static final String APPLICATION_APPLY_PATCH_YAML = "application/apply-patch+yaml"; public static final String APPLICATION_GRAPHQL = "application/graphql"; + public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded"; + + public static final ContentType APPLICATION_JSON_CONTENT_TYPE = new ContentType(APPLICATION,"json",null); + + - public static final ContentType APPLICATION_JSON_CONTENT_TYPE = new ContentType("application","json",null); - public static final ContentType APPLICATION_X_WWW_FORM_URLENCODED_CONTENT_TYPE = new ContentType("application","x-www-form-urlencoded",null); + public static final ContentType APPLICATION_X_WWW_FORM_URLENCODED_CONTENT_TYPE = new ContentType(APPLICATION,APPLICATION_X_WWW_FORM_URLENCODED,null); public static boolean isXML(String mediaType) { try { @@ -67,7 +74,7 @@ public static boolean isXML(String mediaType) { public static boolean isWWWFormUrlEncoded(String mediaType) { try { - return new ContentType(mediaType).match(APPLICATION_X_WWW_FORM_URLENCODED_CONTENT_TYPE); + return new ContentType(mediaType).match(APPLICATION_X_WWW_FORM_URLENCODED); } catch (ParseException e) { // ignore } diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ConditionalInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ConditionalInterceptor.java index 3515aaa1bc..834baa7ed2 100644 --- a/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ConditionalInterceptor.java +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ConditionalInterceptor.java @@ -65,7 +65,7 @@ public ConditionalInterceptor() { @Override public void init(Router router) throws Exception { super.init(router); - condition = ((LanguageSupport) new GroovyLanguageSupport()).compileExpression(router, test); + condition = new GroovyLanguageSupport().compileExpression(router.getBackgroundInitializator(), null, test); } private boolean testCondition(Exchange exc) { diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptor.java index 079fa2865c..a5335e13bc 100644 --- a/core/src/main/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptor.java +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptor.java @@ -15,139 +15,67 @@ package com.predic8.membrane.core.interceptor.groovy; import com.predic8.membrane.annot.*; -import com.predic8.membrane.core.exchange.*; -import com.predic8.membrane.core.http.*; -import com.predic8.membrane.core.interceptor.*; +import com.predic8.membrane.core.lang.*; import com.predic8.membrane.core.lang.groovy.*; import com.predic8.membrane.core.rules.*; -import com.predic8.membrane.core.util.*; -import org.apache.commons.lang3.*; +import org.apache.commons.text.*; import org.codehaus.groovy.control.*; import org.slf4j.*; import java.util.*; -import java.util.function.*; + +import static com.predic8.membrane.core.util.TextUtil.removeCommonLeadingIndentation; +import static com.predic8.membrane.core.util.TextUtil.removeFinalChar; +import static org.apache.commons.text.StringEscapeUtils.escapeHtml4; /** * @topic 4. Interceptors/Features */ @MCElement(name = "groovy", mixed = true) -public class GroovyInterceptor extends AbstractInterceptor { - Logger log = LoggerFactory.getLogger(GroovyInterceptor.class); - private String src = ""; - - private Function, Object> script; - - public GroovyInterceptor() { - name = "Groovy"; - } - - @Override - public Outcome handleRequest(Exchange exc) throws Exception { - return runScript(exc, Flow.REQUEST); - } - - @Override - public Outcome handleResponse(Exchange exc) throws Exception { - return runScript(exc, Flow.RESPONSE); - } - - @Override - public void handleAbort(Exchange exc) { - try { - runScript(exc, Flow.ABORT); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @Override - public void init() { - if (router == null) - return; - if ("".equals(src)) - return; - - try { - script = new GroovyLanguageSupport().compileScript(router, src); - }catch (MultipleCompilationErrorsException e){ - logGroovyException(null,e); - throw new RuntimeException(e); - } - - } - - private Outcome runScript(Exchange exc, Flow flow) throws InterruptedException { - HashMap parameters = new HashMap(); - parameters.put("exc", exc); - parameters.put("flow", flow); - parameters.put("spring", router.getBeanFactory()); - Object res = null; - try { - res = script.apply(parameters); - }catch (Exception e){ - logGroovyException(flow, e); - return Outcome.ABORT; - } - - if (res instanceof Outcome) { - return (Outcome) res; - } - - if (res instanceof Response) { - exc.setResponse((Response) res); - return Outcome.RETURN; - } - - if (res instanceof Request) { - exc.setRequest((Request) res); - } - return Outcome.CONTINUE; - - } - - private void logGroovyException(Flow flow, Exception e) { - try { - Rule rule = getRule(); - if(rule instanceof ServiceProxy){ - ServiceProxy sp = (ServiceProxy) rule; - log.error("Exception in Groovy script in service proxy '" + sp.getName() + "' on port " + sp.getPort() + " with path " + (sp.getPath() != null ? sp.getPath().getValue() : "*")); - } else - log.error("Exception in Groovy script in service proxy '" + rule.getName() + "'"); - - if (flow != null) - log.error("Flow: " + flow.name()); - else - log.error("There is possibly a syntax error in the groovy script (compilation error)"); - }catch (NoSuchElementException e2){ - //ignore - logging should not break anything - }finally{ - e.printStackTrace(); - } - } - - public String getSrc() { - return src; - } - - @MCTextContent - public void setSrc(String src) { - this.src = src; - } - - @Override - public String getShortDescription() { - return "Executes a groovy script."; - } - - @Override - public String getLongDescription() { - StringBuilder sb = new StringBuilder(); - sb.append(TextUtil.removeFinalChar(getShortDescription())); - sb.append(":
");
-		sb.append(StringEscapeUtils.escapeHtml4(TextUtil.removeCommonLeadingIndentation(src)));
-		sb.append("
"); - return sb.toString(); - } - +public class GroovyInterceptor extends AbstractScriptInterceptor { + + Logger log = LoggerFactory.getLogger(GroovyInterceptor.class); + + public GroovyInterceptor() { + name = "Groovy"; + } + + @Override + protected void initInternal() { + try { + script = new GroovyLanguageSupport().compileScript(router.getBackgroundInitializator(), null, src); + } catch (MultipleCompilationErrorsException e) { + logGroovyException(e); + throw new RuntimeException(e); + } + } + + private void logGroovyException(Exception e) { + try { + Rule rule = getRule(); + if (rule instanceof ServiceProxy sp) { + log.error("Exception in Groovy script in service proxy '" + sp.getName() + "' on port " + sp.getPort() + " with path " + (sp.getPath() != null ? sp.getPath().getValue() : "*")); + } else + log.error("Exception in Groovy script in service proxy '" + rule.getName() + "'"); + + log.error("There is possibly a syntax error in the groovy script (compilation error)"); + } catch (NoSuchElementException e2) { + //ignore - logging should not break anything + } finally { + e.printStackTrace(); + } + } + + @Override + public String getShortDescription() { + return "Executes a groovy script."; + } + + @Override + public String getLongDescription() { + return removeFinalChar(getShortDescription()) + + ":
" +
+               escapeHtml4(removeCommonLeadingIndentation(src)) +
+               "
"; + } } diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/GraalVMJavascriptLanguageAdapter.java b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/GraalVMJavascriptLanguageAdapter.java new file mode 100644 index 0000000000..8855ff0103 --- /dev/null +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/GraalVMJavascriptLanguageAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.interceptor.javascript; + +import com.predic8.membrane.core.*; +import com.predic8.membrane.core.lang.javascript.*; + +public class GraalVMJavascriptLanguageAdapter extends LanguageAdapter { + + public GraalVMJavascriptLanguageAdapter(Router router) { + super(router); + languageSupport = new GraalVMJavascriptSupport(); + } + + protected String prepareScript(String script) { + return """ +var FileClass = Java.type("java.io.File"); +var Request = Java.type("com.predic8.membrane.core.http.Request"); +var Response = Java.type("com.predic8.membrane.core.http.Response"); + """ + script; + } +} diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/JavascriptInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/JavascriptInterceptor.java index ff6a168d58..0a23bbfcb3 100644 --- a/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/JavascriptInterceptor.java +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/JavascriptInterceptor.java @@ -14,151 +14,44 @@ package com.predic8.membrane.core.interceptor.javascript; import com.predic8.membrane.annot.*; -import com.predic8.membrane.core.exchange.*; -import com.predic8.membrane.core.http.*; -import com.predic8.membrane.core.interceptor.*; -import com.predic8.membrane.core.lang.javascript.*; +import com.predic8.membrane.core.lang.*; import com.predic8.membrane.core.util.*; -import org.apache.commons.lang3.*; +import org.slf4j.*; import java.io.*; -import java.util.*; -import java.util.function.*; -import static com.predic8.membrane.core.interceptor.Interceptor.Flow.ABORT; -import static com.predic8.membrane.core.interceptor.Outcome.*; +import static com.predic8.membrane.core.util.TextUtil.*; +import static org.apache.commons.text.StringEscapeUtils.*; @MCElement(name = "javascript", mixed = true) -public class JavascriptInterceptor extends AbstractInterceptor { +public class JavascriptInterceptor extends AbstractScriptInterceptor { - private String src = ""; + private static final Logger log = LoggerFactory.getLogger(JavascriptInterceptor.class); - private Function, Object> script; - private JavascriptLanguageSupport jls; - private HashMap implicitClasses; + protected LanguageAdapter adapter; public JavascriptInterceptor() { name = "Javascript"; } - @Override - public Outcome handleRequest(Exchange exc) throws Exception { - return runScript(exc, Flow.REQUEST); - } - - @Override - public Outcome handleResponse(Exchange exc) throws Exception { - return runScript(exc, Flow.RESPONSE); - } - - @Override - public void handleAbort(Exchange exc) { - try { - runScript(exc, ABORT); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - - @Override - public void init() throws IOException, ClassNotFoundException { - if (router == null) - return; - if ("".equals(src)) - return; - - jls = new JavascriptLanguageSupport(); - implicitClasses = getJavascriptTypesForHttpClasses(); - script = jls.compileScript(router, src); - - } - - private Outcome runScript(Exchange exc, Flow flow) throws InterruptedException, IOException, ClassNotFoundException { - HashMap parameters = new HashMap<>(); - parameters.put("exc", exc); - parameters.put("flow", flow); - parameters.put("spring", router.getBeanFactory()); - addOutcomeObjects(parameters); - - parameters.putAll(implicitClasses); - Object res = script.apply(parameters); - - if (res instanceof Outcome) { - return (Outcome) res; - } - - if (res instanceof Response) { - exc.setResponse((Response) res); - return RETURN; - } - - if (res instanceof Request) { - exc.setRequest((Request) res); - } - return CONTINUE; - - } - - private HashMap getJavascriptTypesForHttpClasses() throws IOException, ClassNotFoundException { - return getJavascriptTypesForClasses(getHttpPackageClasses()); - } - - private HashMap getJavascriptTypesForClasses(HashMap classes) { - HashMap result = new HashMap<>(); - for(Object clazz : classes.values()){ - Class clazzz = (Class) clazz; - String scriptSrc = clazzz.getSimpleName() + ".static;"; - //TODO this is hacky, do this differently ( maybe do this one time at startup ) - Object jsType = jls.compileScript(router, scriptSrc).apply(classes); - - result.put(clazzz.getSimpleName(),jsType); - } - return result; - } - - private void addOutcomeObjects(HashMap parameters) { - parameters.put("Outcome", Outcome.class); - parameters.put("RETURN", RETURN); - parameters.put("CONTINUE", CONTINUE); - parameters.put("ABORT", Outcome.ABORT); - } - - private HashMap getHttpPackageClasses() throws IOException, ClassNotFoundException { - String httpPackage = "com.predic8.membrane.core.http"; - HashMap result = new HashMap<>(); - List> classes = ClassFinder.find(router.getBeanFactory().getClassLoader(), httpPackage); - for(Class c : classes) { - if(c.getPackage().getName().equals(httpPackage) && !c.getSimpleName().isEmpty()) - result.put(c.getSimpleName(), c); - } - return result; - } - - public String getSrc() { - return src; - } + protected void initInternal() throws IOException, ClassNotFoundException { + // For tests to set an adapter from outside. + if (adapter == null) + adapter = LanguageAdapter.instance(router); - @MCTextContent - public void setSrc(String src) { - this.src = src; + script = adapter.compileScript(src); } @Override public String getShortDescription() { - return "Executes a Javascript script."; + return "Executes Javascript."; } @Override public String getLongDescription() { - StringBuilder sb = new StringBuilder(); - sb.append(TextUtil.removeFinalChar(getShortDescription())); - sb.append(":
");
-        sb.append(StringEscapeUtils.escapeHtml4(TextUtil.removeCommonLeadingIndentation(src)));
-        sb.append("
"); - return sb.toString(); + return removeFinalChar(getShortDescription()) + + ":
" +
+               escapeHtml4(TextUtil.removeCommonLeadingIndentation(src)) +
+               "
"; } -} +} \ No newline at end of file diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/LanguageAdapter.java b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/LanguageAdapter.java new file mode 100644 index 0000000000..9d2f15a835 --- /dev/null +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/LanguageAdapter.java @@ -0,0 +1,80 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.interceptor.javascript; + +import com.predic8.membrane.core.*; +import com.predic8.membrane.core.lang.*; +import com.predic8.membrane.core.util.*; +import org.slf4j.*; + +import java.io.*; +import java.util.*; +import java.util.function.*; + +public abstract class LanguageAdapter { + + private static final Logger log = LoggerFactory.getLogger(JavascriptInterceptor.class); + + protected LanguageSupport languageSupport; + protected Router router; + + public LanguageAdapter(Router router) { + this.router = router; + } + + public static LanguageAdapter instance(Router router) { + try { + Class.forName("org.graalvm.polyglot.Context"); + log.info("Found GraalVM Javascript engine."); + return new GraalVMJavascriptLanguageAdapter(router); + } catch (Exception e) { + // Ignore + } + try { + Class.forName("org.mozilla.javascript.engine.RhinoScriptEngine"); + log.info("Found Rhino Javascript engine."); + return new RhinoJavascriptLanguageAdapter(router); + } catch (Exception e) { + // Ignore + } + throw new ExitException(""" + Fatal Error: No Javascript Engine! + + Membrane is configured to use Javascript, maybe in the proxies.xml file. + The needed Javascript engine is not shipped with Membrane to spare size + and to avoid security risks. However you can easiliy install an engine. + + We recommend to install the GraalVM Javascript Engine: + + 1.) Download: + + https://repo1.maven.org/maven2/org/graalvm/js/js-scriptengine/22.3.0/js-scriptengine-22.3.0-javadoc.jar + + 2.) Drop the JAR-file into MEMBRANE_HOME/libs + 3.) Start Membrane. + + But you can also use the old Rhino Engine: + + https://repo1.maven.org/maven2/org/mozilla/rhino-engine/"""); + } + + public Function, Object> compileScript(String script) throws IOException, ClassNotFoundException { + return languageSupport.compileScript(router.getBackgroundInitializator(), router.getBeanFactory().getClassLoader(), prepareScript(script)); + } + + protected abstract String prepareScript(String src); +} diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/RhinoJavascriptLanguageAdapter.java b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/RhinoJavascriptLanguageAdapter.java new file mode 100644 index 0000000000..37f219d255 --- /dev/null +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/javascript/RhinoJavascriptLanguageAdapter.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.interceptor.javascript; + +import com.predic8.membrane.core.*; +import com.predic8.membrane.core.lang.javascript.*; + +public class RhinoJavascriptLanguageAdapter extends LanguageAdapter { + + public RhinoJavascriptLanguageAdapter(Router router) { + super(router); + languageSupport = new RhinoJavascriptLanguageSupport(); + } + + protected String prepareScript(String script) { + return "var imports = new JavaImporter(com.predic8.membrane.core.interceptor.Outcome," + + "com.predic8.membrane.core.http" + + ")\n" + + "with(imports){\n" + + script + + "\n}"; + } +} diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/json/JsonProtectionException.java b/core/src/main/java/com/predic8/membrane/core/interceptor/json/JsonProtectionException.java deleted file mode 100644 index 0c1e64ed74..0000000000 --- a/core/src/main/java/com/predic8/membrane/core/interceptor/json/JsonProtectionException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.predic8.membrane.core.interceptor.json; - -public class JsonProtectionException extends Exception { - - public JsonProtectionException(String message) { - super(message); - } -} diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitInterceptor.java index c645038f21..4ec12e13fa 100644 --- a/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitInterceptor.java +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitInterceptor.java @@ -76,9 +76,9 @@ public void setResponseToServiceUnavailable(Exchange exc) { private Header createHeaderFields(Exchange exc) { Header hd = new Header(); hd.add("Date", dateFormatter.print(DateTime.now())); - hd.add("X-LimitDuration", PeriodFormat.getDefault().print(rateLimitStrategy.requestLimitDuration.toPeriod())); + hd.add("X-LimitDuration", rateLimitStrategy.getLimitDurationPeriod()); hd.add("X-LimitRequests", Integer.toString(rateLimitStrategy.requestLimit)); - hd.add("X-LimitReset", Long.toString(rateLimitStrategy.getServiceAvailableAgainTime(exc.getRemoteAddrIp()).getMillis())); + hd.add("X-LimitReset", rateLimitStrategy.getLimitReset(exc.getRemoteAddrIp())); return hd; } diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitStrategy.java b/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitStrategy.java index f563d14254..f120dcba9d 100644 --- a/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitStrategy.java +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/ratelimit/RateLimitStrategy.java @@ -16,6 +16,7 @@ import org.joda.time.DateTime; import org.joda.time.Duration; +import org.joda.time.format.*; public abstract class RateLimitStrategy { @@ -40,6 +41,14 @@ public void setRequestLimit(int requestLimit) { updateAfterConfigChange(); } + public String getLimitDurationPeriod() { + return PeriodFormat.getDefault().print(requestLimitDuration.toPeriod()); + } + + public String getLimitReset(String ip) { + return Long.toString(getServiceAvailableAgainTime(ip).getMillis()); + } + public abstract boolean isRequestLimitReached(String ip); public abstract DateTime getServiceAvailableAgainTime(String ip); diff --git a/core/src/main/java/com/predic8/membrane/core/lang/AbstractScriptInterceptor.java b/core/src/main/java/com/predic8/membrane/core/lang/AbstractScriptInterceptor.java new file mode 100644 index 0000000000..47eafd553c --- /dev/null +++ b/core/src/main/java/com/predic8/membrane/core/lang/AbstractScriptInterceptor.java @@ -0,0 +1,126 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.lang; + +import com.predic8.membrane.annot.*; +import com.predic8.membrane.core.exchange.*; +import com.predic8.membrane.core.http.*; +import com.predic8.membrane.core.interceptor.*; + +import java.io.*; +import java.util.*; +import java.util.function.*; + +import static com.predic8.membrane.core.interceptor.Interceptor.Flow.*; +import static com.predic8.membrane.core.interceptor.Outcome.*; + +public abstract class AbstractScriptInterceptor extends AbstractInterceptor { + + protected String src; + protected Function, Object> script; + + @Override + public Outcome handleRequest(Exchange exc) throws Exception { + return runScript(exc, REQUEST); + } + + @Override + public Outcome handleResponse(Exchange exc) throws Exception { + return runScript(exc, RESPONSE); + } + + public void init() throws IOException, ClassNotFoundException { + if (router == null) + return; + if ("".equals(src)) + return; + initInternal(); + } + + protected abstract void initInternal() throws IOException, ClassNotFoundException; + + protected Outcome runScript(Exchange exc, Flow flow) throws InterruptedException, IOException, ClassNotFoundException { + + Object res = script.apply(getParameterBindings(exc, flow)); + + if (res instanceof Outcome) { + return (Outcome) res; + } + + if (res instanceof Response) { + exc.setResponse((Response) res); + return RETURN; + } + + if (res instanceof Request) { + exc.setRequest((Request) res); + } + + return CONTINUE; + } + + @Override + public void handleAbort(Exchange exc) { + try { + runScript(exc, Flow.ABORT); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + + private HashMap getParameterBindings(Exchange exc, Flow flow) { + HashMap parameters = new HashMap<>(); + parameters.put("exc", exc); + parameters.put("flow", flow); + + Message msg = getMessage(exc, flow); + if (msg != null) { + parameters.put("message", msg); + parameters.put("header", msg.getHeader()); + parameters.put("body", msg.getBody()); + } + parameters.put("spring", router.getBeanFactory()); + addOutcomeObjects(parameters); + return parameters; + } + + private void addOutcomeObjects(HashMap parameters) { + parameters.put("Outcome", Outcome.class); + parameters.put("RETURN", RETURN); + parameters.put("CONTINUE", CONTINUE); + parameters.put("ABORT", Outcome.ABORT); + } + + protected Message getMessage(Exchange exc, Flow flow) { + return switch (flow) { + case REQUEST -> exc.getRequest(); + case RESPONSE -> exc.getResponse(); + default -> null; + }; + } + + public String getSrc() { + return src; + } + + @MCTextContent + public void setSrc(String src) { + this.src = src; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/predic8/membrane/core/lang/LanguageSupport.java b/core/src/main/java/com/predic8/membrane/core/lang/LanguageSupport.java index aa35707ea1..7584024ef7 100644 --- a/core/src/main/java/com/predic8/membrane/core/lang/LanguageSupport.java +++ b/core/src/main/java/com/predic8/membrane/core/lang/LanguageSupport.java @@ -15,14 +15,17 @@ package com.predic8.membrane.core.lang; import com.predic8.membrane.core.*; +import com.predic8.membrane.core.util.*; +import java.io.*; import java.util.*; +import java.util.concurrent.*; import java.util.function.*; public abstract class LanguageSupport { - public abstract Function, Boolean> compileExpression(Router router, String expression); + public abstract Function, Boolean> compileExpression(ExecutorService executorService, ClassLoader classLoader, String expression) throws IOException, ClassNotFoundException; - public abstract Function, Object> compileScript(Router router, String script); + public abstract Function, Object> compileScript(ExecutorService executorService, ClassLoader classLoader, String script) throws IOException, ClassNotFoundException; } diff --git a/core/src/main/java/com/predic8/membrane/core/lang/ScriptExecutorPool.java b/core/src/main/java/com/predic8/membrane/core/lang/ScriptExecutorPool.java index fa421ee385..a930d8b7d3 100644 --- a/core/src/main/java/com/predic8/membrane/core/lang/ScriptExecutorPool.java +++ b/core/src/main/java/com/predic8/membrane/core/lang/ScriptExecutorPool.java @@ -14,32 +14,26 @@ package com.predic8.membrane.core.lang; -import java.util.Map; -import java.util.concurrent.ArrayBlockingQueue; +import org.slf4j.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Function; -import com.predic8.membrane.core.Router; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; public abstract class ScriptExecutorPool implements Function, R> { private static final Logger log = LoggerFactory.getLogger(ScriptExecutorPool.class); private static final int concurrency = Runtime.getRuntime().availableProcessors() * 2; - ArrayBlockingQueue scripts = new ArrayBlockingQueue(concurrency); + ArrayBlockingQueue scripts = new ArrayBlockingQueue<>(concurrency); - public void init(Router router) { + public void init(ExecutorService executorService) { scripts.add(createOneScript()); - router.getBackgroundInitializator().execute(new Runnable() { - @Override - public void run() { - try { - for (int i = 1; i < concurrency; i++) - scripts.add(createOneScript()); - } catch (Exception e) { - log.error("Error compiling script:", e); - } + executorService.execute(() -> { + try { + for (int i = 1; i < concurrency; i++) + scripts.add(createOneScript()); + } catch (Exception e) { + log.error("Error compiling script:", e); } }); } diff --git a/core/src/main/java/com/predic8/membrane/core/lang/groovy/GroovyLanguageSupport.java b/core/src/main/java/com/predic8/membrane/core/lang/groovy/GroovyLanguageSupport.java index a3c3e4e0be..681bda20a2 100644 --- a/core/src/main/java/com/predic8/membrane/core/lang/groovy/GroovyLanguageSupport.java +++ b/core/src/main/java/com/predic8/membrane/core/lang/groovy/GroovyLanguageSupport.java @@ -18,7 +18,9 @@ import com.predic8.membrane.core.lang.*; import groovy.lang.*; +import java.io.*; import java.util.*; +import java.util.concurrent.*; import java.util.function.*; public class GroovyLanguageSupport extends LanguageSupport { @@ -27,9 +29,9 @@ private abstract class GroovyScriptExecutorPool extends ScriptExecutorPool { private final String groovyCode; - private GroovyScriptExecutorPool(Router router, String expression) { + private GroovyScriptExecutorPool(ExecutorService executorService, String expression) { this.groovyCode = expression; - init(router); + init(executorService); } @Override @@ -53,8 +55,8 @@ protected Object invoke(Script script, Map parameters) { private static final GroovyShell shell = new GroovyShell(); @Override - public Function, Boolean> compileExpression(Router router, String src) { - return new GroovyScriptExecutorPool<>(router, addImports(src)) { + public Function, Boolean> compileExpression(ExecutorService executorService, ClassLoader classLoader, String src) { + return new GroovyScriptExecutorPool<>(executorService, addImports(src)) { @Override public Boolean apply(Map parameters) { Object result = this.execute(parameters); @@ -66,8 +68,8 @@ public Boolean apply(Map parameters) { } @Override - public Function, Object> compileScript(Router router, String script) { - return new GroovyScriptExecutorPool<>(router, addImports(script)) { + public Function, Object> compileScript(ExecutorService executorService, ClassLoader classLoader, String script) { + return new GroovyScriptExecutorPool<>(executorService, addImports(script)) { @Override public Object apply(Map parameters) { return this.execute(parameters); @@ -81,5 +83,4 @@ private String addImports(String src) { "import com.predic8.membrane.core.http.*\n" + src; } - } diff --git a/core/src/main/java/com/predic8/membrane/core/lang/javascript/GraalVMJavascriptSupport.java b/core/src/main/java/com/predic8/membrane/core/lang/javascript/GraalVMJavascriptSupport.java new file mode 100644 index 0000000000..6890dd32af --- /dev/null +++ b/core/src/main/java/com/predic8/membrane/core/lang/javascript/GraalVMJavascriptSupport.java @@ -0,0 +1,105 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.lang.javascript; + +import com.predic8.membrane.core.lang.*; +import org.graalvm.polyglot.*; +import org.slf4j.*; + +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; + +public class GraalVMJavascriptSupport extends LanguageSupport { + + private static final Logger log = LoggerFactory.getLogger(GraalVMJavascriptSupport.class); + + private abstract static class GraalVMJavascriptExecutorPool extends ScriptExecutorPool { + + // Permissions are needed to access the Java Host from Javascript e.g. access to Exchange + private static final Context context = Context.newBuilder() + .allowHostAccess(HostAccess.ALL) + .allowHostClassLookup(s -> true) + .allowPolyglotAccess(PolyglotAccess.ALL).build(); + + private final String javascriptCode; + + private GraalVMJavascriptExecutorPool(ExecutorService executorService, String expression) { + this.javascriptCode = expression; + init(executorService); + } + + @Override + protected Object invoke(Source source, Map parameters) { + try { + synchronized (context) { + for (String name : parameters.keySet()) { + context.getBindings("js").putMember(name, parameters.get(name)); + } + + // Eval caches the compiled script internally. No need to call parse and try to + // cache it in Membrane. + Value js = context.eval(source); + + if (js.isHostObject()) + return js.asHostObject(); + return js; + } + } catch (PolyglotException e) { + if (e.isSyntaxError()) { + SourceSection location = e.getSourceLocation(); + log.warn("Syntax error compiling Javascript at {} line {} position {}", location.getSource(), location.getStartLine(), location.getCharIndex()); + log.warn("Location " + location); + } else { + log.warn(""); + } + throw e; + } catch (Exception e) { + log.error("Error compiling script:", e); + throw new RuntimeException("Error compiling script:", e); + } + } + + @Override + protected Source createOneScript() { + return Source.create("js", javascriptCode); + } + } + + @Override + public Function, Boolean> compileExpression(ExecutorService executorService, ClassLoader cl, String src) { + return new GraalVMJavascriptSupport.GraalVMJavascriptExecutorPool<>(executorService, src) { + @Override + public Boolean apply(Map parameters) { + Object result = this.execute(parameters); + if (result instanceof Boolean) + return (Boolean) result; + return false; + } + }; + } + + @Override + public Function, Object> compileScript(ExecutorService executorService, ClassLoader cl, String script) { + return new GraalVMJavascriptSupport.GraalVMJavascriptExecutorPool<>(executorService, script) { + @Override + public Object apply(Map parameters) { + return this.execute(parameters); + } + }; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/predic8/membrane/core/lang/javascript/JavascriptLanguageSupport.java b/core/src/main/java/com/predic8/membrane/core/lang/javascript/RhinoJavascriptLanguageSupport.java similarity index 64% rename from core/src/main/java/com/predic8/membrane/core/lang/javascript/JavascriptLanguageSupport.java rename to core/src/main/java/com/predic8/membrane/core/lang/javascript/RhinoJavascriptLanguageSupport.java index 0567714a9b..f5433b4079 100644 --- a/core/src/main/java/com/predic8/membrane/core/lang/javascript/JavascriptLanguageSupport.java +++ b/core/src/main/java/com/predic8/membrane/core/lang/javascript/RhinoJavascriptLanguageSupport.java @@ -18,23 +18,30 @@ import org.slf4j.*; import javax.script.*; +import java.io.*; import java.util.*; +import java.util.concurrent.*; import java.util.function.*; -public class JavascriptLanguageSupport extends LanguageSupport { +public class RhinoJavascriptLanguageSupport extends LanguageSupport { - private static final Logger log = LoggerFactory.getLogger(JavascriptLanguageSupport.class); + private static final Logger log = LoggerFactory.getLogger(RhinoJavascriptLanguageSupport.class); - private abstract class JavascriptScriptExecutorPool extends ScriptExecutorPool{ + + private abstract static class JavascriptScriptExecutorPool extends ScriptExecutorPool{ private final String javascriptCode; - final ScriptEngineManager sce; - final static String javascriptEngineName = "JavaScript"; + protected final ScriptEngineManager sce; + protected final static String javascriptEngineName = "rhino"; - private JavascriptScriptExecutorPool(Router router, String expression) { + private JavascriptScriptExecutorPool(ExecutorService executorService, ClassLoader classLoader, String expression) { this.javascriptCode = expression; - sce = new ScriptEngineManager(); - init(router); + + // The ScriptEngineManager should search the engine in the classloader of the router + // otherwise the engine will not be found + sce = new ScriptEngineManager(classLoader); + + init(executorService); } @Override @@ -58,8 +65,8 @@ protected ScriptEngine createOneScript() { } @Override - public Function, Boolean> compileExpression(Router router, String src) { - return new JavascriptScriptExecutorPool<>(router, getScriptWithImports(src)) { + public Function, Boolean> compileExpression(ExecutorService executorService, ClassLoader classLoader, String src) { + return new JavascriptScriptExecutorPool<>(executorService, classLoader, src) { @Override public Boolean apply(Map parameters) { Object result = this.execute(parameters); @@ -71,21 +78,12 @@ public Boolean apply(Map parameters) { } @Override - public Function, Object> compileScript(Router router, String script) { - return new JavascriptScriptExecutorPool<>(router, getScriptWithImports(script)) { + public Function, Object> compileScript(ExecutorService executorService, ClassLoader classLoader, String script) { + return new JavascriptScriptExecutorPool<>(executorService, classLoader, script) { @Override public Object apply(Map parameters) { return this.execute(parameters); } }; } - - private String getScriptWithImports(String src) { - return "var imports = new JavaImporter(com.predic8.membrane.core.interceptor.Outcome," + - "com.predic8.membrane.core.http" + - ")\n" + - "with(imports){\n" + - src + - "\n}"; - } } diff --git a/core/src/main/java/com/predic8/membrane/core/openapi/validators/AbstractBodyValidator.java b/core/src/main/java/com/predic8/membrane/core/openapi/validators/AbstractBodyValidator.java index 0c7aa78fe4..a025682aa1 100644 --- a/core/src/main/java/com/predic8/membrane/core/openapi/validators/AbstractBodyValidator.java +++ b/core/src/main/java/com/predic8/membrane/core/openapi/validators/AbstractBodyValidator.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.openapi.validators; import com.predic8.membrane.core.http.*; @@ -5,7 +21,7 @@ import io.swagger.v3.oas.models.*; import io.swagger.v3.oas.models.media.*; -import static com.predic8.membrane.core.http.MimeType.APPLICATION_JSON_CONTENT_TYPE; +import static com.predic8.membrane.core.http.MimeType.*; public class AbstractBodyValidator { @@ -24,9 +40,9 @@ protected void validateBodyAccordingToMediaType(ValidationContext ctx, String me ctx.schemaType(mediaTypeObj.getSchema().get$ref()); } errors.add(new SchemaValidator(api, mediaTypeObj.getSchema()).validate(ctx.statusCode(statusCode), message.getBody())); - } else if(MimeType.isXML(mediaType)) { + } else if(isXML(mediaType)) { errors.add(ctx.statusCode(statusCode),"Validation of XML messages is not implemented yet!"); - } else if(MimeType.isWWWFormUrlEncoded(mediaType)) { + } else if(isWWWFormUrlEncoded(mediaType)) { errors.add(ctx.statusCode(statusCode),"Validation of 'application/x-www-form-urlencoded' messages is not implemented yet!"); } // Other types that can't be validated against OpenAPI are Ok. diff --git a/core/src/main/java/com/predic8/membrane/core/transport/http/HttpEndpointListener.java b/core/src/main/java/com/predic8/membrane/core/transport/http/HttpEndpointListener.java index c5151eb4ae..1db53f75dc 100644 --- a/core/src/main/java/com/predic8/membrane/core/transport/http/HttpEndpointListener.java +++ b/core/src/main/java/com/predic8/membrane/core/transport/http/HttpEndpointListener.java @@ -14,26 +14,17 @@ package com.predic8.membrane.core.transport.http; -import java.io.IOException; +import com.predic8.membrane.core.transport.*; +import com.predic8.membrane.core.transport.ssl.*; +import com.predic8.membrane.core.util.*; +import org.slf4j.*; + +import javax.annotation.*; +import java.io.*; import java.net.*; -import java.net.BindException; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.security.InvalidParameterException; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.atomic.AtomicInteger; - -import com.predic8.membrane.core.util.TimerManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.predic8.membrane.core.transport.PortOccupiedException; -import com.predic8.membrane.core.transport.ssl.SSLProvider; - -import javax.annotation.Nullable; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; public class HttpEndpointListener extends Thread { @@ -43,14 +34,14 @@ public class HttpEndpointListener extends Thread { private final ServerSocket serverSocket; private final HttpTransport transport; private final SSLProvider sslProvider; - private final ConcurrentHashMap idleSockets = new ConcurrentHashMap(); - private final ConcurrentHashMap openSockets = new ConcurrentHashMap(); + private final ConcurrentHashMap idleSockets = new ConcurrentHashMap<>(); + private final ConcurrentHashMap openSockets = new ConcurrentHashMap<>(); private final ConcurrentHashMap ipConnectionCount = new ConcurrentHashMap<>(); private TimerManager timerManager; // a TimerManager we have created ourselves private volatile boolean closed; - private class ClientInfo { + private static class ClientInfo { public AtomicInteger count; public volatile long lastUse; @@ -212,16 +203,12 @@ void setIdleStatus(Socket socket, boolean isIdle) throws IOException { } } - void setOpenStatus(Socket socket, boolean isOpen) { - if (isOpen) - throw new InvalidParameterException("isOpen"); + void setOpenStatus(Socket socket) { openSockets.remove(socket); - InetAddress remoteIp = getRemoteIp(socket); - ClientInfo clientInfo = ipConnectionCount.get(remoteIp); + ClientInfo clientInfo = ipConnectionCount.get(getRemoteIp(socket)); if (clientInfo != null) { - AtomicInteger connectionCount = clientInfo.count; - connectionCount.decrementAndGet(); + clientInfo.count.decrementAndGet(); } } @@ -251,16 +238,19 @@ private String constructLogMessage(StringBuilder sb, InetAddress ip, AbstractMap .append("Concurrent connection limit reached for IP: ").append(ip.toString()).append(System.lineSeparator()) .append("Received the following content").append(System.lineSeparator()) .append("===START===").append(System.lineSeparator()) - .append(new String(receivedContent.getKey(),0,receivedContent.getValue().intValue())).append(System.lineSeparator()) + .append(new String(receivedContent.getKey(),0, receivedContent.getValue())).append(System.lineSeparator()) .append("===END===").toString(); } + @SuppressWarnings("ResultOfMethodCallIgnored") private AbstractMap.SimpleEntry readUpTo1KbOfDataFrom(Socket sourceSocket, byte[] buffer) throws IOException { int available = sourceSocket.getInputStream().available(); int offset = 0; while(available > 0){ if(available > buffer.length-offset){ available = buffer.length-offset; + + //noinspection ResultOfMethodCallIgnored sourceSocket.getInputStream().read(buffer,offset,available); offset += available; break; diff --git a/core/src/main/java/com/predic8/membrane/core/transport/http/HttpServerHandler.java b/core/src/main/java/com/predic8/membrane/core/transport/http/HttpServerHandler.java index c29dc6b178..ea2fa33b48 100644 --- a/core/src/main/java/com/predic8/membrane/core/transport/http/HttpServerHandler.java +++ b/core/src/main/java/com/predic8/membrane/core/transport/http/HttpServerHandler.java @@ -142,16 +142,16 @@ public void run() { } catch (SocketException se) { log.debug("client socket closed"); } catch (SSLException s) { + SSLException ex = s; if(showSSLExceptions) { - if (s.getCause() instanceof SSLException) - s = (SSLException) s.getCause(); - if (s.getCause() instanceof SocketException) + if (ex.getCause() instanceof SSLException cause) { + ex = cause; + } + if (ex.getCause() instanceof SocketException) log.debug("ssl socket closed"); else - log.error("", s); + log.error("", ex); } - } catch (IOException e) { - log.error("", e); } catch (EndOfStreamException e) { log.debug("stream closed"); } catch (AbortException e) { @@ -165,10 +165,8 @@ public void run() { + e.getLineSoFar() + ")"); } catch (Exception e) { log.error("", e); - } - - finally { - endpointListener.setOpenStatus(rawSourceSocket, false); + } finally { + endpointListener.setOpenStatus(rawSourceSocket); if (boundConnection != null) try { @@ -183,7 +181,6 @@ public void run() { updateThreadName(false); } - } private void closeConnections() { @@ -266,7 +263,7 @@ private void updateThreadName(boolean fromConnection) { sb.append(" "); InetAddress ia = sourceSocket.getInetAddress(); if (ia != null) - sb.append(ia.toString()); + sb.append(ia); sb.append(":"); sb.append(sourceSocket.getPort()); Thread.currentThread().setName(sb.toString()); diff --git a/core/src/main/java/com/predic8/membrane/core/transport/http/HttpTransport.java b/core/src/main/java/com/predic8/membrane/core/transport/http/HttpTransport.java index c9411ae5db..69d54ac2f7 100644 --- a/core/src/main/java/com/predic8/membrane/core/transport/http/HttpTransport.java +++ b/core/src/main/java/com/predic8/membrane/core/transport/http/HttpTransport.java @@ -39,6 +39,11 @@ import javax.annotation.Nullable; +import static com.google.common.base.Objects.equal; +import static java.lang.Integer.MAX_VALUE; +import static java.lang.String.format; +import static java.util.concurrent.TimeUnit.SECONDS; + /** * @description

* The transport receives messages from clients and invokes interceptors in the request and response flow. @@ -59,14 +64,12 @@ public class HttpTransport extends Transport { private int forceSocketCloseOnHotDeployAfter = 30000; private boolean tcpNoDelay = true; - private final Map> portListenerMapping - = new HashMap>(); - private final List> stillRunning - = new ArrayList>(); + private final Map> portListenerMapping = new HashMap<>(); + private final List> stillRunning = new ArrayList<>(); - private ThreadPoolExecutor executorService = new ThreadPoolExecutor(20, - Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, - new SynchronousQueue(), new HttpServerThreadFactory()); + private final ThreadPoolExecutor executorService = new ThreadPoolExecutor(20, + MAX_VALUE, 60L, SECONDS, + new SynchronousQueue<>(), new HttpServerThreadFactory()); @Override public void init(Router router) throws Exception { @@ -97,7 +100,7 @@ public synchronized void closePort(IpPort p) throws IOException { if (mih.isEmpty()) { portListenerMapping.remove(p.getPort()); } - stillRunning.add(new WeakReference(plt)); + stillRunning.add(new WeakReference<>(plt)); for (IPortChangeListener listener : menuListeners) { listener.removePort(p.getPort()); @@ -109,7 +112,7 @@ public synchronized void closePort(IpPort p) throws IOException { public synchronized void closeAll(boolean waitForCompletion) throws IOException { log.debug("Closing all network server sockets."); - List all = new ArrayList(); + List all = new ArrayList<>(); for (Map v : portListenerMapping.values()) { all.addAll(v.keySet()); } @@ -129,7 +132,7 @@ public synchronized void closeAll(boolean waitForCompletion) throws IOException while (true) { boolean onlyIdle = System.currentTimeMillis() - now <= forceSocketCloseOnHotDeployAfter; closeConnections(onlyIdle); - if (executorService.awaitTermination(5, TimeUnit.SECONDS)) + if (executorService.awaitTermination(5, SECONDS)) break; log.warn("Still waiting for running exchanges to finish. (Set to a lower value to forcibly close connections more quickly."); } @@ -140,7 +143,7 @@ public synchronized void closeAll(boolean waitForCompletion) throws IOException } private void closeConnections(boolean onlyIdle) throws IOException { - ArrayList> remove = new ArrayList>(); + ArrayList> remove = new ArrayList<>(); for (WeakReference whel : stillRunning) { HttpEndpointListener hel = whel.get(); if (hel == null) @@ -154,27 +157,23 @@ private void closeConnections(boolean onlyIdle) throws IOException { } /** - * @param port - * @param timerManager - * @throws IOException + * @param port Port to open + * @param timerManager timerManager + * @throws IOException If port can not be opened */ @Override public synchronized void openPort(String ip, int port, SSLProvider sslProvider, @Nullable TimerManager timerManager) throws IOException { if (port == -1) throw new RuntimeException("The port-attribute is missing (probably on a element)."); - Map mih = portListenerMapping.get(port); - if (mih == null) { - mih = new HashMap(); - portListenerMapping.put(port, mih); - } - IpPort p = new IpPort(ip, port); + Map mih = portListenerMapping.computeIfAbsent(port, k -> new HashMap<>()); + IpPort p = new IpPort(ip, port); HttpEndpointListener hel = mih.get(p); if (hel != null) { // already listen on the same "ip:port" - if (Objects.equal(sslProvider, hel.getSslProvider())) { + if (equal(sslProvider, hel.getSslProvider())) { return; // O.K. both use the equivalent ssl provider } - throw new RuntimeException("Lister thread on " + p.toShortString() + " should use the same SSL config"); + throw new RuntimeException(format("Lister thread on %s should use the same SSL config", p.toShortString())); } if ((ip == null && !mih.isEmpty()) // '*:port' vs 'XXX:port' || (ip != null && mih.containsKey(new IpPort(null, port))) // 'XXX:port' vs '*:port' diff --git a/core/src/main/java/com/predic8/membrane/core/util/ErrorUtil.java b/core/src/main/java/com/predic8/membrane/core/util/ErrorUtil.java index 35415e1f39..0323590cc2 100644 --- a/core/src/main/java/com/predic8/membrane/core/util/ErrorUtil.java +++ b/core/src/main/java/com/predic8/membrane/core/util/ErrorUtil.java @@ -1,10 +1,25 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.util; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.predic8.membrane.core.exchange.*; import com.predic8.membrane.core.http.*; -import com.predic8.membrane.core.interceptor.*; import org.slf4j.*; import java.util.*; @@ -23,7 +38,7 @@ public class ErrorUtil { public static void createAndSetErrorResponse(Exchange exc, int statusCode, String message) { Response.ResponseBuilder builder = Response.ResponseBuilder.newInstance(). status(statusCode, getMessageForStatusCode(statusCode)); - if (exc.getRequest().getHeader().getAccept() != null && exc.getRequest().getHeader().getAccept().contains("html")) { + if (requestsAcceptsHtmlMimeType(exc)) { builder .contentType(TEXT_HTML_UTF8) .body(htmlMessage(getMessageForStatusCode(statusCode), message)).build(); @@ -41,4 +56,8 @@ public static void createAndSetErrorResponse(Exchange exc, int statusCode, Strin } exc.setResponse(builder.build()); } + + private static boolean requestsAcceptsHtmlMimeType(Exchange exc) { + return exc.getRequest().getHeader().getAccept() != null && exc.getRequest().getHeader().getAccept().contains("html"); + } } diff --git a/core/src/main/java/com/predic8/membrane/core/util/ExitException.java b/core/src/main/java/com/predic8/membrane/core/util/ExitException.java new file mode 100644 index 0000000000..79f0ae9a1a --- /dev/null +++ b/core/src/main/java/com/predic8/membrane/core/util/ExitException.java @@ -0,0 +1,29 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.util; + +/** + * Exception with text to display to user before terminating Membraen + */ +public class ExitException extends RuntimeException { + + private String message; + + public ExitException(String message) { + super(message); + } +} diff --git a/core/src/main/java/com/predic8/membrane/core/util/MimeTypeUtil.java b/core/src/main/java/com/predic8/membrane/core/util/MimeTypeUtil.java deleted file mode 100644 index 02d3c2a7fb..0000000000 --- a/core/src/main/java/com/predic8/membrane/core/util/MimeTypeUtil.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.predic8.membrane.core.util; - -import jakarta.mail.internet.*; - -public class MimeTypeUtil { - -} diff --git a/core/src/test/java/com/predic8/membrane/core/SimpleTest.java b/core/src/test/java/com/predic8/membrane/core/SimpleTest.java index feaa6cf21f..8457b4ae62 100644 --- a/core/src/test/java/com/predic8/membrane/core/SimpleTest.java +++ b/core/src/test/java/com/predic8/membrane/core/SimpleTest.java @@ -19,10 +19,10 @@ public class SimpleTest { - private Router router; + private static Router router; @BeforeAll - public void setUp() throws Exception { + static void setUp() throws Exception { router = Router.init("classpath:/test-proxies.xml"); } @@ -32,7 +32,7 @@ public void test() { } @AfterAll - public void tearDown() throws Exception { + static void tearDown() throws Exception { router.shutdown(); } diff --git a/core/src/test/java/com/predic8/membrane/core/UnitTests.java b/core/src/test/java/com/predic8/membrane/core/UnitTests.java index e956394f7d..217fa9842b 100644 --- a/core/src/test/java/com/predic8/membrane/core/UnitTests.java +++ b/core/src/test/java/com/predic8/membrane/core/UnitTests.java @@ -27,6 +27,7 @@ import com.predic8.membrane.core.interceptor.cbr.XPathCBRInterceptorTest; import com.predic8.membrane.core.interceptor.formvalidation.FormValidationInterceptorTest; import com.predic8.membrane.core.interceptor.groovy.GroovyInterceptorTest; +import com.predic8.membrane.core.interceptor.javascript.*; import com.predic8.membrane.core.interceptor.json.JsonPointerExtractorInterceptorTest; import com.predic8.membrane.core.interceptor.oauth2.OAuth2UnitTests; import com.predic8.membrane.core.interceptor.ratelimit.RateLimitInterceptorTest; @@ -110,7 +111,8 @@ Xml2JsonInterceptorTest.class, Json2XmlInterceptorTest.class, TemplateInterceptorTest.class, XmlPathExtractorInterceptorTest.class, JsonPointerExtractorInterceptorTest.class, AcmeStepTest.class, AcmeRenewTest.class, KubernetesClientTest.class, - ProxyTest.class, Http2ClientServerTest.class, ChunkedBodyTest.class + ProxyTest.class, Http2ClientServerTest.class, ChunkedBodyTest.class, + JavascriptInterceptor.class }) @SelectPackages("com.predic8.membrane.core.openapi") diff --git a/core/src/test/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptorTest.java b/core/src/test/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptorTest.java index 3e57d58c0e..20b65cee6d 100644 --- a/core/src/test/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptorTest.java +++ b/core/src/test/java/com/predic8/membrane/core/interceptor/groovy/GroovyInterceptorTest.java @@ -13,6 +13,7 @@ limitations under the License. */ package com.predic8.membrane.core.interceptor.groovy; +import static com.predic8.membrane.core.interceptor.Outcome.CONTINUE; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -38,12 +39,13 @@ public void testRequest() throws Exception { exc.setRequest(new Request()); GroovyInterceptor i = new GroovyInterceptor(); - i.setSrc("exc.setProperty('foo', 'bar')\n"+ - "def b = spring.getBean('abc')\n"+ - "CONTINUE"); + i.setSrc(""" + exc.setProperty('foo', 'bar') + def b = spring.getBean('abc') + CONTINUE"""); i.init(r); - assertEquals(Outcome.CONTINUE, i.handleRequest(exc)); + assertEquals(CONTINUE, i.handleRequest(exc)); assertEquals("bar", exc.getProperty("foo")); verify(applicationContext, times(1)).getBean("abc"); } diff --git a/core/src/test/java/com/predic8/membrane/core/interceptor/javascript/JavascriptInterceptorTest.java b/core/src/test/java/com/predic8/membrane/core/interceptor/javascript/JavascriptInterceptorTest.java new file mode 100644 index 0000000000..0b06e150d2 --- /dev/null +++ b/core/src/test/java/com/predic8/membrane/core/interceptor/javascript/JavascriptInterceptorTest.java @@ -0,0 +1,165 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.interceptor.javascript; + +import com.predic8.membrane.core.*; +import com.predic8.membrane.core.exchange.*; +import com.predic8.membrane.core.http.*; +import com.predic8.membrane.core.interceptor.*; +import com.predic8.membrane.core.lang.*; +import com.predic8.membrane.core.lang.javascript.*; +import org.graalvm.polyglot.*; +import org.junit.jupiter.api.*; +import org.junit.jupiter.params.*; +import org.junit.jupiter.params.provider.*; +import org.springframework.context.support.*; + +import static com.predic8.membrane.core.interceptor.Outcome.*; +import static org.junit.jupiter.api.Assertions.*; + +class JavascriptInterceptorTest { + + Router router = new Router(); + JavascriptInterceptor interceptor; + Exchange exc; + + @BeforeEach + public void setup() throws Exception { + router.setApplicationContext(new GenericApplicationContext()); + interceptor = new JavascriptInterceptor(); + + exc = new Exchange(null); + exc.setRequest(new Request.Builder().header("foo", "42").build()); + } + + /** + * GraalVM JS should be in the Test dependencies + */ + @Test + void isGraalVMPresent() throws ClassNotFoundException { + Class.forName("org.graalvm.polyglot.Context"); + assertTrue(true); + } + + @Test + void isRhinoPresent() throws ClassNotFoundException { + Class.forName("org.mozilla.javascript.engine.RhinoScriptEngine"); + assertTrue(true); + } + + @Test + void error() { + try (Context context = Context.create()) { + assertThrows(Exception.class, () -> context.eval("js", "var i =;")); + } + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + public void simpleScript(Class engine) throws Exception { + executeSript("var x = 1", engine); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + public void scriptWithError(Class engine) { + assertThrows(Exception.class, () -> executeSript("var x=;", engine)); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + public void exchangeAccess(Class engine) throws Exception { + executeSript("var e = exc;", engine); + executeSript("var e = flow;", engine); + executeSript("var e = spring;", engine); + executeSript("var e = message;", engine); + executeSript("var e = header;", engine); + executeSript("var e = body;", engine); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void wrongScript(Class engine) throws Exception { + assertEquals(CONTINUE, executeSript("var x = 1/0;", engine)); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void outcomeContinue(Class engine) throws Exception { + assertEquals(CONTINUE, executeSript("CONTINUE", engine)); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void outcomeReturn(Class engine) throws Exception { + assertEquals(RETURN, executeSript("RETURN;", engine)); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void setRequestHeader(Class engine) throws Exception { + executeSript("header.setValue('baz','7');", engine); + assertEquals("7", exc.getRequest().getHeader().getFirstValue("baz")); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void setRequest(Class engine) throws Exception { + executeSript("exc.setRequest(new Request.Builder().body('foo').build());", engine); + assertEquals("foo", exc.getRequest().getBodyAsStringDecoded()); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void setReturnRequest(Class engine) throws Exception { + executeSript("new Request.Builder().body('foo').build();", engine); + assertEquals("foo", exc.getRequest().getBodyAsStringDecoded()); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void setResponse(Class engine) throws Exception { + executeSript("exc.setResponse(Response.ok('baz').build())", engine); + assertEquals("baz", exc.getResponse().getBodyAsStringDecoded()); + } + + @ParameterizedTest + @ValueSource(classes = {GraalVMJavascriptSupport.class, RhinoJavascriptLanguageSupport.class}) + void setReturnResponse(Class engine) throws Exception { + executeSript("Response.ok('baz').build()", engine); + assertEquals("baz", exc.getResponse().getBodyAsStringDecoded()); + } + + @SafeVarargs + private Outcome executeSript(String src, Class... engine) throws Exception { + interceptor.setSrc(src); + + // Needed because GraalVMJavascriptSupport is not found using Class.forname() in the Interceptor! + if (engine.length == 0 || engine[0].equals(GraalVMJavascriptSupport.class)) { + interceptor.adapter = new GraalVMJavascriptLanguageAdapter(router); + interceptor.adapter.languageSupport = new GraalVMJavascriptSupport(); // Must come before init! + } else if (engine[0].equals(RhinoJavascriptLanguageSupport.class)) { + interceptor.adapter = new RhinoJavascriptLanguageAdapter(router); + interceptor.adapter.languageSupport = new RhinoJavascriptLanguageSupport(); + } else { + fail("No Javascript Engine"); + } + + interceptor.init(router); + return interceptor.handleRequest(exc); + } +} \ No newline at end of file diff --git a/core/src/test/java/com/predic8/membrane/core/openapi/model/RequestTest.java b/core/src/test/java/com/predic8/membrane/core/openapi/model/RequestTest.java index 25e4b18d4d..7f93792a7a 100644 --- a/core/src/test/java/com/predic8/membrane/core/openapi/model/RequestTest.java +++ b/core/src/test/java/com/predic8/membrane/core/openapi/model/RequestTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.openapi.model; import org.junit.jupiter.api.*; diff --git a/core/src/test/java/com/predic8/membrane/core/openapi/model/ResponseTest.java b/core/src/test/java/com/predic8/membrane/core/openapi/model/ResponseTest.java index 04298aabf4..5dfac8ad33 100644 --- a/core/src/test/java/com/predic8/membrane/core/openapi/model/ResponseTest.java +++ b/core/src/test/java/com/predic8/membrane/core/openapi/model/ResponseTest.java @@ -1,10 +1,25 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.openapi.model; -import com.predic8.membrane.core.http.*; import jakarta.mail.internet.*; import org.junit.jupiter.api.*; -import static com.predic8.membrane.core.http.MimeType.APPLICATION_JSON; +import static com.predic8.membrane.core.http.MimeType.*; import static org.junit.jupiter.api.Assertions.*; class ResponseTest { diff --git a/core/src/test/java/com/predic8/membrane/core/openapi/validators/AbstractValidatorTest.java b/core/src/test/java/com/predic8/membrane/core/openapi/validators/AbstractValidatorTest.java index 51dc3f9980..d902ab1bf3 100644 --- a/core/src/test/java/com/predic8/membrane/core/openapi/validators/AbstractValidatorTest.java +++ b/core/src/test/java/com/predic8/membrane/core/openapi/validators/AbstractValidatorTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.openapi.validators; import com.fasterxml.jackson.databind.*; diff --git a/core/src/test/java/com/predic8/membrane/core/openapi/validators/MimeTypesRequestResponseTest.java b/core/src/test/java/com/predic8/membrane/core/openapi/validators/MimeTypesRequestResponseTest.java index d11efc9ca0..7cf55c604b 100644 --- a/core/src/test/java/com/predic8/membrane/core/openapi/validators/MimeTypesRequestResponseTest.java +++ b/core/src/test/java/com/predic8/membrane/core/openapi/validators/MimeTypesRequestResponseTest.java @@ -1,9 +1,31 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.openapi.validators; +import com.predic8.membrane.core.http.*; import com.predic8.membrane.core.openapi.model.*; +import com.predic8.membrane.core.openapi.model.Request; +import com.predic8.membrane.core.openapi.model.Response; import jakarta.mail.internet.*; import org.junit.jupiter.api.*; +import org.junit.jupiter.params.*; +import org.junit.jupiter.params.provider.*; +import static com.predic8.membrane.core.http.MimeType.*; import static org.junit.jupiter.api.Assertions.*; public class MimeTypesRequestResponseTest extends AbstractValidatorTest { @@ -15,9 +37,9 @@ String getOpenAPIFileName() { @Test public void notImplementedResponse() throws ParseException { - testNotImplementedResponse(200, "application/xml"); - testNotImplementedResponse(201, "text/xml"); - testNotImplementedResponse(202, "application/x-www-form-urlencoded"); + testNotImplementedResponse(200, APPLICATION_XML); + testNotImplementedResponse(201, TEXT_XML); + testNotImplementedResponse(202, APPLICATION_X_WWW_FORM_URLENCODED); } private void testNotImplementedResponse(int statusCode, String mimeType) throws ParseException { @@ -31,13 +53,9 @@ private void testNotImplementedResponse(int statusCode, String mimeType) throws @Test public void notImplementedRequest() throws ParseException { - testNotImplementedRequest("application/xml","/application-xml"); - testNotImplementedRequest("text/xml", "/text-xml"); - testNotImplementedRequest("application/x-www-form-urlencoded", "/x-www-form-urlencoded"); - } - - private void testNotImplementedRequest(String mimeType) throws ParseException { - testNotImplementedRequest(mimeType,"/mimetypes" ); + testNotImplementedRequest(APPLICATION_XML,"/application-xml"); + testNotImplementedRequest(TEXT_XML, "/text-xml"); + testNotImplementedRequest(APPLICATION_X_WWW_FORM_URLENCODED, "/x-www-form-urlencoded"); } private void testNotImplementedRequest(String mimeType, String path) throws ParseException { diff --git a/core/src/test/java/com/predic8/membrane/core/util/MimeTypeUtilTest.java b/core/src/test/java/com/predic8/membrane/core/util/MimeTypeUtilTest.java index 82970093c5..d9451d208d 100644 --- a/core/src/test/java/com/predic8/membrane/core/util/MimeTypeUtilTest.java +++ b/core/src/test/java/com/predic8/membrane/core/util/MimeTypeUtilTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 predic8 GmbH, www.predic8.com + * + * 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.predic8.membrane.core.util; import org.junit.jupiter.api.*; diff --git a/distribution/examples/basic-auth/service-proxy.sh b/distribution/examples/basic-auth/service-proxy.sh index 132618c349..cf97366a97 100644 --- a/distribution/examples/basic-auth/service-proxy.sh +++ b/distribution/examples/basic-auth/service-proxy.sh @@ -12,13 +12,16 @@ homeSet() { terminate() { echo "Starting of Membrane Router failed." echo "Please execute this script from the appropriate subfolder of MEMBRANE_HOME/examples/" - } homeNotSet() { echo "MEMBRANE_HOME variable is not set" + echo "In $(pwd)" + echo "ls $(ls)" + echo "---" + echo "ls $(ls ../..)" - if [ -f "`pwd`/../../starter.jar" ] + if [ -f "$(pwd)/../../starter.jar" ] then export MEMBRANE_HOME="`pwd`/../.." homeSet diff --git a/distribution/examples/basic-xml-interceptor/proxies.xml b/distribution/examples/basic-xml-interceptor/proxies.xml index eb7e2eeaf9..386e416719 100644 --- a/distribution/examples/basic-xml-interceptor/proxies.xml +++ b/distribution/examples/basic-xml-interceptor/proxies.xml @@ -28,7 +28,6 @@ - diff --git a/distribution/examples/cbr/README.md b/distribution/examples/cbr/README.md index b4e4c2c10d..4caa95b209 100644 --- a/distribution/examples/cbr/README.md +++ b/distribution/examples/cbr/README.md @@ -12,16 +12,33 @@ http://curl.haxx.se/download.html To run the example execute the following steps: -1. Execute `examples/cbr/service-proxy.bat` +1. Go to the folder `examples/cbr` -2. Execute `examples/curl -d @order.xml localhost/shop` +2. Start Membrane: -3. Take a look at the output of the console. You should see the line: `"Normal order received."` +`service-proxy.sh` or +`service-proxy.bat` -4. Execute `examples/curl -d @express.xml localhost/shop` +3. Send an order XML document to the API: -5. This time the following line should be printed to the console:`"Express order received."` +```sh +curl -d @order.xml localhost:2000 +``` -6. Execute `examples/curl -d @import.xml localhost/shop` +4. Take a look at the output of the console. You should see the line: -7. The final output should look like this:`"Order contains import items."` +`"Normal order received."` + +5. Send an express order to the API: + +```sh +curl -d @express.xml localhost:2000 +Express order received. +``` + +6. Send an import document: + +```sh +curl -d @import.xml localhost:2000 +Order contains import items. +``` diff --git a/distribution/examples/cbr/proxies.xml b/distribution/examples/cbr/proxies.xml index b7b04871b4..69fd6b8af2 100644 --- a/distribution/examples/cbr/proxies.xml +++ b/distribution/examples/cbr/proxies.xml @@ -14,19 +14,19 @@ - + Response.ok("Order contains import items.").build() - + Response.ok("Normal order received.").build() - + Response.ok("Express order received.").build() diff --git a/distribution/examples/groovy/proxies.xml b/distribution/examples/groovy/proxies.xml index f76e2effbe..d5f4c71be2 100755 --- a/distribution/examples/groovy/proxies.xml +++ b/distribution/examples/groovy/proxies.xml @@ -26,7 +26,7 @@ exc.response.header.add("X-Groovy", "42") // Set Header - + println "X-Groovy header added with value :" + value CONTINUE diff --git a/distribution/examples/loadbalancing/1-static/README.md b/distribution/examples/loadbalancing/1-static/README.md index 843d100ed9..bbed7ae620 100644 --- a/distribution/examples/loadbalancing/1-static/README.md +++ b/distribution/examples/loadbalancing/1-static/README.md @@ -12,7 +12,7 @@ This example sets up a loadbalancer to distribute requests to 3 different nodes. Execute the following steps: -1. Go to the `examples/loadbalancing/static` directory. +1. Go to the `examples/loadbalancing/1-static` directory. 2. Run `service-proxy.sh` or `service-proxy.bat` in a terminal. 3. Open the URL: diff --git a/distribution/examples/loadbalancing/1-static/proxies.xml b/distribution/examples/loadbalancing/1-static/proxies.xml index be2c4b2e06..b5c76bb857 100644 --- a/distribution/examples/loadbalancing/1-static/proxies.xml +++ b/distribution/examples/loadbalancing/1-static/proxies.xml @@ -21,15 +21,15 @@ - + - + - + diff --git a/distribution/examples/loadbalancing/1-static/service-proxy.sh b/distribution/examples/loadbalancing/1-static/service-proxy.sh index 8a1d059585..2c6c5d0d66 100755 --- a/distribution/examples/loadbalancing/1-static/service-proxy.sh +++ b/distribution/examples/loadbalancing/1-static/service-proxy.sh @@ -20,7 +20,7 @@ homeNotSet() { if [ -f "`pwd`/../../../starter.jar" ] then - export MEMBRANE_HOME="`pwd`/../.." + export MEMBRANE_HOME="`pwd`/../../.." homeSet else terminate diff --git a/distribution/examples/loadbalancing/2-dynamic/README.md b/distribution/examples/loadbalancing/2-dynamic/README.md index 2280b901e1..eaf0d2750f 100644 --- a/distribution/examples/loadbalancing/2-dynamic/README.md +++ b/distribution/examples/loadbalancing/2-dynamic/README.md @@ -12,7 +12,7 @@ In this example we will distribute requests to 3 different nodes. To run the example execute the following steps: -1. Go to the `examples/loadbalancing/loadbalancer-1-basic` directory. +1. Go to the `examples/loadbalancing/2-dynamic` directory. 2. Execute `service-proxy.bat` or `service-proxy.sh` 3. Open the URL http://localhost:4000 in your browser. You will see a simple web app that counts how often it was called. There are 2 more web apps of the same kind @@ -45,4 +45,6 @@ Nodes can also be registered, turned off and on using a simple API. http://localhost:9010/clustermanager/down?balancer=default&host=localhost&port=4001 ``` -You find more balancer configurations at the [Loadbalancing](..) page. \ No newline at end of file +You find more balancer configurations at the [Loadbalancing](..) page. + +Note that the `adminConsole` and the `clusterNotification` are optional, you can take them out of the `proxies.xml` if you want to. \ No newline at end of file diff --git a/distribution/examples/loadbalancing/2-dynamic/proxies.xml b/distribution/examples/loadbalancing/2-dynamic/proxies.xml index 0509b88442..30189d0840 100644 --- a/distribution/examples/loadbalancing/2-dynamic/proxies.xml +++ b/distribution/examples/loadbalancing/2-dynamic/proxies.xml @@ -22,10 +22,16 @@ - + + + + + + + diff --git a/distribution/examples/loadbalancing/2-dynamic/service-proxy.sh b/distribution/examples/loadbalancing/2-dynamic/service-proxy.sh index da2075049c..f10f5e82f9 100755 --- a/distribution/examples/loadbalancing/2-dynamic/service-proxy.sh +++ b/distribution/examples/loadbalancing/2-dynamic/service-proxy.sh @@ -20,7 +20,7 @@ homeNotSet() { if [ -f "`pwd`/../../../starter.jar" ] then - export MEMBRANE_HOME="`pwd`/../.." + export MEMBRANE_HOME="`pwd`/../../.." homeSet else terminate diff --git a/distribution/examples/loadbalancing/3-client/lbclient.sh b/distribution/examples/loadbalancing/3-client/lbclient.sh index ca891b40e5..cbd178f261 100755 --- a/distribution/examples/loadbalancing/3-client/lbclient.sh +++ b/distribution/examples/loadbalancing/3-client/lbclient.sh @@ -20,7 +20,7 @@ homeNotSet() { echo "MEMBRANE_HOME variable is not set" if [ -f "`pwd`/../../../starter.jar" ] ; then - export MEMBRANE_HOME="`pwd`/../.." + export MEMBRANE_HOME="`pwd`/../../.." homeSet else terminate diff --git a/distribution/examples/logging/console/proxies.xml b/distribution/examples/logging/console/proxies.xml index ff47dbe596..3b44a4efc4 100644 --- a/distribution/examples/logging/console/proxies.xml +++ b/distribution/examples/logging/console/proxies.xml @@ -7,7 +7,7 @@ - + diff --git a/distribution/examples/oauth2/api/OAuth2TrustedClient.java b/distribution/examples/oauth2/api/OAuth2TrustedClient.java index dfceb7743c..eaa16c4b3f 100644 --- a/distribution/examples/oauth2/api/OAuth2TrustedClient.java +++ b/distribution/examples/oauth2/api/OAuth2TrustedClient.java @@ -23,7 +23,7 @@ public class OAuth2TrustedClient { static String clientId = "abc"; static String clientSecret = "def"; - static String tokenEndpoint = "http://localhost:7000/oauth2/token"; + static String tokenEndpoint = "http://localhost:700//oauth2/token"; static String target = "http://localhost:2000"; static String username = "john"; @@ -91,6 +91,4 @@ private static void sendPostData(HttpURLConnection connection, String urlParamet private static String createTokenRequestParameters() { return "grant_type=password&username=" + username + "&password=" + password + "&client_id=" + clientId + "&client_secret=" + clientSecret; } - - } diff --git a/distribution/examples/oauth2/api/authorization_server/proxies.xml b/distribution/examples/oauth2/api/authorization_server/proxies.xml index 622b317869..7d5fa2d25c 100644 --- a/distribution/examples/oauth2/api/authorization_server/proxies.xml +++ b/distribution/examples/oauth2/api/authorization_server/proxies.xml @@ -6,9 +6,9 @@ - + - + diff --git a/distribution/examples/oauth2/api/client.ps1 b/distribution/examples/oauth2/api/client.ps1 index 3a8a8c2fef..d0391bb88d 100644 --- a/distribution/examples/oauth2/api/client.ps1 +++ b/distribution/examples/oauth2/api/client.ps1 @@ -9,7 +9,7 @@ param ( $clientId = "abc" $clientSecret = "def" -$tokenEndpoint = "http://localhost:7000/oauth2/token" +$tokenEndpoint = "http://localhost:7007/oauth2/token" $target = "http://localhost:2000" function getToken{ diff --git a/distribution/examples/oauth2/api/client.sh b/distribution/examples/oauth2/api/client.sh index 4399db5f7c..effe3329f1 100644 --- a/distribution/examples/oauth2/api/client.sh +++ b/distribution/examples/oauth2/api/client.sh @@ -1,24 +1,23 @@ clientId="abc" clientSecret="def" -tokenEndpoint="http://localhost:7000/oauth2/token" +tokenEndpoint="http://localhost:7007/oauth2/token" target="http://localhost:2000" username=$1 password=$2 parseResponse(){ - IFS='"' read -ra ADDR <<< "$1" authHeader="Authorization: ${ADDR[7]} ${ADDR[3]}" } getToken(){ - call=$(curl --data "grant_type=password&username=${username}&password=${password}&client_id=${clientId}&client_secret=${clientSecret}" $tokenEndpoint) + call=$(curl -o - -v --data "grant_type=password&username=${username}&password=${password}&client_id=${clientId}&client_secret=${clientSecret}" $tokenEndpoint) parseResponse $call } sendRequestToTarget(){ - targetResult=$(curl -v -s -H "$authHeader" $target 1> /dev/null) + targetResult=$(curl -v -o - -H "$authHeader" $target) } getToken diff --git a/distribution/examples/oauth2/api/token_validator/proxies.xml b/distribution/examples/oauth2/api/token_validator/proxies.xml index 9ca0938fae..17d09a13f0 100644 --- a/distribution/examples/oauth2/api/token_validator/proxies.xml +++ b/distribution/examples/oauth2/api/token_validator/proxies.xml @@ -10,7 +10,7 @@ - + @@ -19,7 +19,7 @@ - exc.setResponse(Response.ok("You accessed the protected resource!").build()) + exc.setResponse(Response.ok('{"success":"true"}\n').contentType("application/json").build()) RETURN diff --git a/distribution/router/service-proxy.sh b/distribution/router/service-proxy.sh index 3712e75432..85ce058e9e 100644 --- a/distribution/router/service-proxy.sh +++ b/distribution/router/service-proxy.sh @@ -29,12 +29,5 @@ CLASSPATH="$CLASSPATH:$MEMBRANE_HOME/starter.jar" export CLASSPATH cd "$MEMBRANE_HOME" -major=$(java -version 2>&1 | head -n 1 | cut -d'"' -f2 | cut -d'.' -f2) - -if [ "$major" -lt "8" ] -then - echo "You are running Java $major. Membrane needs atleast Java 8. Please install a newer Java version from http://www.oracle.com/technetwork/java/javase/downloads/index.html" -fi - echo Membrane Router running... exec java $JAVA_OPTS -classpath "$CLASSPATH" com.predic8.membrane.core.Starter "$@" diff --git a/distribution/src/main/java/com/predic8/membrane/core/ClassloaderUtil.java b/distribution/src/main/java/com/predic8/membrane/core/ClassloaderUtil.java index 15e86294f1..3a6b289f1a 100644 --- a/distribution/src/main/java/com/predic8/membrane/core/ClassloaderUtil.java +++ b/distribution/src/main/java/com/predic8/membrane/core/ClassloaderUtil.java @@ -26,53 +26,36 @@ public static List getJarUrls(String folder) { File file = new File(folder); if (!file.isDirectory()) - return new ArrayList(); + return new ArrayList<>(); - String[] jars = file.list(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.endsWith(".jar"); - } - }); - - List urls = new ArrayList(); - - for (int i = 0; i < jars.length; i++) { + List urls = new ArrayList<>(); + for (String jar : getJarFilenames(file)) { try { - urls.add(new URL("file:" + folder + jars[i])); + urls.add(new URL("file:" + folder + jar)); } catch (MalformedURLException e) { e.printStackTrace(); } } - return urls; - } - public static boolean fileExists(String configFileName) - throws MalformedURLException, IOException { - if (configFileName.startsWith("file:")) - return new File(new URL(configFileName).getPath()).exists(); - return new File(configFileName).exists(); + private static String[] getJarFilenames(File file) { + return file.list((dir, name) -> name.endsWith(".jar")); } - public static String getFullQualifiedFolderName(String rootDir, - String folder) throws IOException { - return rootDir + System.getProperty("file.separator") + folder - + System.getProperty("file.separator"); + public static String getFullQualifiedFolderName(String rootDir, String folder) { + return rootDir + System.getProperty("file.separator") + folder + System.getProperty("file.separator"); } public static URLClassLoader getExternalClassloader(String rootDir) { try { - List urls = getJarUrls(getFullQualifiedFolderName(rootDir, - "lib")); + List urls = getJarUrls(getFullQualifiedFolderName(rootDir, "lib")); urls.add(new URL(getFullQualifiedFolderName(rootDir, "classes"))); - return new URLClassLoader(urls.toArray(new URL[urls.size()]), - ClassloaderUtil.class.getClassLoader()); + return new URLClassLoader(urls.toArray(new URL[0]), ClassloaderUtil.class.getClassLoader()); } catch (Exception e) { e.printStackTrace(); System.exit(1); } return null; } - } diff --git a/distribution/src/main/java/com/predic8/membrane/core/IDEStarter.java b/distribution/src/main/java/com/predic8/membrane/core/IDEStarter.java index 58e5b08404..75ad0ded91 100644 --- a/distribution/src/main/java/com/predic8/membrane/core/IDEStarter.java +++ b/distribution/src/main/java/com/predic8/membrane/core/IDEStarter.java @@ -29,12 +29,10 @@ public static void main(String[] args) { // for testing or development purposes // Start in "distribution" folder try { - File file = new File("conf/log4j2.xml"); - Configurator.initialize(null, new ConfigurationSource(new FileInputStream(file))); + Configurator.initialize(null, new ConfigurationSource(new FileInputStream("conf/log4j2.xml"))); } catch (IOException e) { LoggerFactory.getLogger(IDEStarter.class).error("Error loading log configuration."); } - RouterCLI.main(args); } diff --git a/distribution/src/main/java/com/predic8/membrane/core/Starter.java b/distribution/src/main/java/com/predic8/membrane/core/Starter.java index 9e14059ee9..2e6aac162f 100644 --- a/distribution/src/main/java/com/predic8/membrane/core/Starter.java +++ b/distribution/src/main/java/com/predic8/membrane/core/Starter.java @@ -49,8 +49,7 @@ public static void main(String[] args) throws Exception { getMainMethod().invoke(null, new Object[]{args}); } - private static Method getMainMethod() throws NoSuchMethodException, - ClassNotFoundException { + private static Method getMainMethod() throws NoSuchMethodException, ClassNotFoundException { return getRouterCLIClass().getDeclaredMethod("main", String[].class); } @@ -59,8 +58,7 @@ private static Class getRouterCLIClass() throws ClassNotFoundException { } private static URLClassLoader getLoader() { - return ClassloaderUtil.getExternalClassloader("file:" - + System.getenv("MEMBRANE_HOME")); + return ClassloaderUtil.getExternalClassloader("file:" + System.getenv("MEMBRANE_HOME")); } private static int getJavaVersion() { diff --git a/distribution/src/test/java/com/predic8/membrane/examples/config/ConfigSerializationTest.java b/distribution/src/test/java/com/predic8/membrane/examples/ConfigSerializationTest.java similarity index 97% rename from distribution/src/test/java/com/predic8/membrane/examples/config/ConfigSerializationTest.java rename to distribution/src/test/java/com/predic8/membrane/examples/ConfigSerializationTest.java index 622874c869..8c1fc26e9f 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/config/ConfigSerializationTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/ConfigSerializationTest.java @@ -11,7 +11,7 @@ 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.predic8.membrane.examples.config; +package com.predic8.membrane.examples; import com.predic8.beautifier.PlainBeautifierFormatter; import com.predic8.beautifier.XMLBeautifier; @@ -91,9 +91,6 @@ public void doit(String configFile) throws Exception { String xml = readConfigFileAsXML(configFile); prettyPrint(xml); - //System.out.println(xml); - - System.out.println("ConfigFile: " + configFile); AssertUtils.assertContainsNot("incomplete serialization", xml); diff --git a/distribution/src/test/java/com/predic8/membrane/examples/DistributionExtractingTestcase.java b/distribution/src/test/java/com/predic8/membrane/examples/DistributionExtractingTestcase.java deleted file mode 100644 index 2ca70f7658..0000000000 --- a/distribution/src/test/java/com/predic8/membrane/examples/DistributionExtractingTestcase.java +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright 2012 predic8 GmbH, www.predic8.com - - 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.predic8.membrane.examples; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; - -/** - * Extracts the .zip distribution built by Maven. - */ -public class DistributionExtractingTestcase { - private File targetDir, unzipDir, membraneHome; - - @BeforeEach - public void init() throws IOException, InterruptedException { - targetDir = new File("target").getCanonicalFile(); - if (!targetDir.exists()) - throw new RuntimeException("membraneHome " + targetDir.getName() + " does not exist."); - - File zip = null; - { - File[] files = targetDir.listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.startsWith("membrane-service-proxy") && name.endsWith(".zip"); - } - }); - if (files.length > 1) - throw new RuntimeException("found more than one service-proxy*.zip"); - if (files.length == 1) - zip = files[0]; - } - - if (zip == null) - throw new RuntimeException("TODO: calling 'ant dist-router' automatically is not implemented."); - - unzipDir = new File(targetDir, "examples-automatic"); - if (unzipDir.exists()) { - recursiveDelete(unzipDir); - Thread.sleep(1000); - } - if (!unzipDir.mkdir()) - throw new RuntimeException("Could not mkdir " + unzipDir.getAbsolutePath()); - - System.out.println("unzipping router distribution [" + getClass().getSimpleName() + "]..."); - unzip(zip, unzipDir); - - membraneHome = unzipDir.listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.startsWith("membrane-service-proxy"); - } - })[0]; - - replaceLog4JConfig(); - - System.out.println("running test..."); - } - - private void replaceLog4JConfig() throws IOException { - File log4jproperties = new File(membraneHome, "conf" + File.separator + "log4j2.xml"); - if (!log4jproperties.exists()) - throw new RuntimeException("log4j2.xml does not exits."); - - FileUtils.writeStringToFile( - log4jproperties, - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - ""); - } - - public File getExampleDir(String name) { - File exampleDir = new File(membraneHome, "examples" + File.separator + name); - if (!exampleDir.exists()) - throw new RuntimeException("Example dir " + exampleDir.getAbsolutePath() + " does not exist."); - return exampleDir; - } - - public File getMembraneHome() { - return membraneHome; - } - - @AfterEach - public void done() { - System.out.println("cleaning up..."); - recursiveDelete(unzipDir); - System.out.println("done."); - } - - private void recursiveDelete(File file) { - if (file.isDirectory()) - for (File child : file.listFiles()) - recursiveDelete(child); - if (!file.delete()) - throw new RuntimeException("could not delete " + file.getAbsolutePath()); - } - - public static final void unzip(File zip, File target) throws IOException { - ZipFile zipFile = new ZipFile(zip); - Enumeration entries = zipFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if (entry.isDirectory()) { - // Assume directories are stored parents first then children. - // This is not robust, just for demonstration purposes. - new File(target, entry.getName()).mkdir(); - } else { - final File zipEntryFile = new File(target, entry.getName()); - if (!zipEntryFile.toPath().normalize().startsWith(target.toPath().normalize())) { - throw new IOException("Bad zip entry"); - } - FileOutputStream fos = new FileOutputStream(zipEntryFile); - try { - copyInputStream(zipFile.getInputStream(entry), - new BufferedOutputStream(fos)); - } finally { - fos.close(); - } - } - } - zipFile.close(); - } - - public static final void copyInputStream(InputStream in, OutputStream out) - throws IOException { - byte[] buffer = new byte[1024]; - int len; - - while ((len = in.read(buffer)) >= 0) - out.write(buffer, 0, len); - - in.close(); - out.close(); - } - -} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/ExampleTests.java b/distribution/src/test/java/com/predic8/membrane/examples/ExampleTests.java index 2b909ffef6..d6c4b7d78b 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/ExampleTests.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/ExampleTests.java @@ -13,8 +13,11 @@ limitations under the License. */ package com.predic8.membrane.examples; +import com.predic8.membrane.examples.config.*; import com.predic8.membrane.examples.env.*; import com.predic8.membrane.examples.tests.*; +import com.predic8.membrane.examples.tests.loadbalancing.*; +import com.predic8.membrane.examples.tests.ssl.*; import com.predic8.membrane.examples.tests.validation.FormValidationTest; import com.predic8.membrane.examples.tests.validation.JSONSchemaValidationTest; import com.predic8.membrane.examples.tests.validation.XMLValidationTest; @@ -23,53 +26,57 @@ import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; +/** + * If some Java processes are not cleaned up after a test run you can remove them with: + *

+ * Mac OS: + * sudo kill -9 $(lsof -i -n -P | grep LISTEN | grep "2000" | tr -s " " | cut -f 2 -d " ") + */ @Suite @SelectClasses({ - AntInPath.class, - ConsistentVersionNumbers.class, - DefaultConfigTest.class, - HelpLinkExistenceTest.class, - JavaLicenseInfoTest.class, + AntInPath.class, + ConsistentVersionNumbers.class, + DefaultConfigTest.class, + HelpLinkExistenceTest.class, + JavaLicenseInfoTest.class, - ACLTest.class, - BasicAuthTest.class, - CBRTest.class, - FileExchangeStoreTest.class, - GroovyTest.class, - LoadBalancerBasic1Test.class, - LoadBalancerClient2Test.class, - LoadBalancerMultiple4Test.class, - LoadBalancerSession3Test.class, - LoadBalancerStaticTest.class, - LoggingCSVTest.class, - LoggingJDBCTest.class, - LoggingTest.class, - LoginTest.class, - QuickstartRESTTest.class, - QuickstartSOAPTest.class, - REST2SOAPTest.class, - REST2SOAPJSONTest.class, - RewriterTest.class, - SSLServer.class, - SSLClient.class, - ThrottleTest.class, - XSLTTest.class, + ACLTest.class, + BasicAuthTest.class, + CBRTest.class, + FileExchangeStoreTest.class, + GroovyTest.class, + Loadbalancing_1_static_Test.class, + Loadbalancing_3_client_Test.class, + Loadbalancing_5_multiple_Test.class, + Loadbalancing_4_xml_session_Test.class, + LoggingCSVTest.class, + LoggingJDBCTest.class, + LoggingTest.class, + LoginTest.class, +// QuickstartRESTTest.class, +// QuickstartSOAPTest.class, + REST2SOAPTest.class, + REST2SOAPJSONTest.class, + RewriterTest.class, + SSLServerApiWithTlsTest.class, + ToBackendTest.class, + ThrottleTest.class, + XSLTTest.class, - FormValidationTest.class, - JSONSchemaValidationTest.class, - XMLValidationTest.class, + FormValidationTest.class, + JSONSchemaValidationTest.class, + XMLValidationTest.class, - CustomInterceptorTest.class, - StaxExampleInterceptorTest.class, - AddSoapHeaderTest.class, - BasicXmlInterceptorTest.class, - Xml2JsonTest.class, - Json2XmlTest.class, - RoutingTest.class, - XsltExampleTest.class, - - - - RoutingTest.class + CustomInterceptorTest.class, + StaxExampleInterceptorTest.class, + AddSoapHeaderTest.class, + BasicXmlInterceptorTest.class, + Xml2JsonTest.class, + Json2XmlTest.class, + RoutingTest.class, + XsltExampleTest.class, + RoutingTest.class, + OAuth2ApiTest.class }) -public class ExampleTests {} +public class ExampleTests { +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/ExampleUnitTests.java b/distribution/src/test/java/com/predic8/membrane/examples/ExampleUnitTests.java index 82ad9d27b0..4c88926e0f 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/ExampleUnitTests.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/ExampleUnitTests.java @@ -17,8 +17,6 @@ import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; -import com.predic8.membrane.examples.config.ConfigSerializationTest; - @Suite @SelectClasses({ ConfigSerializationTest.class, diff --git a/distribution/src/test/java/com/predic8/membrane/examples/env/DefaultConfigTest.java b/distribution/src/test/java/com/predic8/membrane/examples/config/DefaultConfigTest.java similarity index 69% rename from distribution/src/test/java/com/predic8/membrane/examples/env/DefaultConfigTest.java rename to distribution/src/test/java/com/predic8/membrane/examples/config/DefaultConfigTest.java index 3231e4baeb..90f0fc36c2 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/env/DefaultConfigTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/config/DefaultConfigTest.java @@ -12,29 +12,40 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.predic8.membrane.examples.env; +package com.predic8.membrane.examples.config; import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; import static com.predic8.membrane.test.AssertUtils.replaceInFile; import static com.predic8.membrane.test.AssertUtils.setupHTTPAuthentication; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.readFileToString; import java.io.File; import java.io.IOException; +import java.nio.charset.*; -import com.predic8.membrane.examples.util.ConsoleLogger; import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.ProxiesXmlUtil; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; +import com.predic8.membrane.examples.util.ProxiesXmlUtil; public class DefaultConfigTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return ".."; + } + + @BeforeEach + void setup() { + baseDir = getMembraneHome(); + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getMembraneHome(); + public void test() throws Exception { File proxies = new File(baseDir, "conf/proxies.xml"); File proxiesFull = new File(baseDir, "conf/proxies-full-sample.xml"); @@ -42,19 +53,14 @@ public void test() throws IOException, InterruptedException { replaceInFile(proxies, "9000", "2003"); replaceInFile(proxiesFull, "9000", "2003"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + try(Process2 sl = startServiceProxyScript()) { setupHTTPAuthentication("localhost", 2003, "admin", "membrane"); assertContains("Membrane Service Proxy Administration", getAndAssert200("http://localhost:2003/admin/")); - ProxiesXmlUtil pxu = new ProxiesXmlUtil(proxies); - pxu.updateWith(FileUtils.readFileToString(proxiesFull), sl); + new ProxiesXmlUtil(proxies).updateWith(readFileToString(proxiesFull, UTF_8), sl); setupHTTPAuthentication("localhost", 2001, "admin", "membrane"); assertContains("Routing Configuration", getAndAssert200("http://localhost:2001/static/proxies.xml")); - } finally { - sl.killScript(); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/env/AntInPath.java b/distribution/src/test/java/com/predic8/membrane/examples/env/AntInPath.java index 3659e0acbd..88f672012f 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/env/AntInPath.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/env/AntInPath.java @@ -18,10 +18,11 @@ import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.BufferLogger; import com.predic8.membrane.test.AssertUtils; +import static com.predic8.membrane.test.AssertUtils.assertContains; import static org.junit.jupiter.api.Assertions.assertEquals; public class AntInPath { @@ -34,7 +35,7 @@ public void checkThatAntExecutableIsAvailable() throws IOException, InterruptedE BufferLogger antOutput = new BufferLogger(); Process2 ant = new Process2.Builder().in(new File(".")).executable("ant -version").withWatcher(antOutput).start(); assertEquals(0, ant.waitFor(20000)); - AssertUtils.assertContains("Apache Ant", antOutput.toString()); + assertContains("Apache Ant", antOutput.toString()); } } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/env/ConsistentVersionNumbers.java b/distribution/src/test/java/com/predic8/membrane/examples/env/ConsistentVersionNumbers.java index 3e35a8afd8..9a4a4ba3bb 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/env/ConsistentVersionNumbers.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/env/ConsistentVersionNumbers.java @@ -17,6 +17,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,6 +40,7 @@ import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -56,20 +58,17 @@ public void doit() throws Exception { validateBase(base); - handler = new Handler() { - @Override - public String handle(File file, String old) { - if (version == null) - version = old; - else { - try { - assertEquals(version, old); - } catch (RuntimeException e) { - throw new RuntimeException("in file " + file.getAbsolutePath(), e); - } + handler = (file, old) -> { + if (version == null) + version = old; + else { + try { + assertEquals(version, old); + } catch (RuntimeException e) { + throw new RuntimeException("in file " + file.getAbsolutePath(), e); } - return old; } + return old; }; run(base); @@ -77,30 +76,19 @@ public String handle(File file, String old) { public static void main(String[] args) throws Exception { File base = new File(".."); - //base = new File("C:\\Users\\tobias\\git\\membrane\\service-proxy"); - validateBase(base); - handler = new Handler() { - @Override - public String handle(File file, String old) { - System.out.println(old + " " + file.getAbsolutePath()); - return old; - } + handler = (file, old) -> { + System.out.println(old + " " + file.getAbsolutePath()); + return old; }; run(base); System.out.println("Please enter the new version:"); - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - final String version = br.readLine(); + final String version = new BufferedReader(new InputStreamReader(System.in)).readLine(); - handler = new Handler() { - @Override - public String handle(File file, String old) { - return version; - } - }; + handler = (file, old) -> version; run(base); } @@ -127,7 +115,7 @@ private static void validateBase(File base) throws Exception { private static void recurse(File base, int i) throws Exception { if (i == 0) return; - for (File child : base.listFiles()) { + for (File child : requireNonNull(base.listFiles())) { if (child.isFile() && child.getName().equals("pom.xml")) handlePOM(child, true); if (child.isFile() && child.getName().equals(".factorypath")) @@ -137,7 +125,7 @@ private static void recurse(File base, int i) throws Exception { } } - private static void handlePOM(File child, boolean isPartOfProject) throws XPathExpressionException, SAXException, IOException, ParserConfigurationException, TransformerConfigurationException, TransformerException, TransformerFactoryConfigurationError { + private static void handlePOM(File child, boolean isPartOfProject) throws XPathExpressionException, SAXException, IOException, ParserConfigurationException, TransformerException, TransformerFactoryConfigurationError { //System.out.println(child.getName()); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //dbf.setNamespaceAware(true); @@ -157,7 +145,7 @@ private static void handlePOM(File child, boolean isPartOfProject) throws XPathE TransformerFactory.newInstance().newTransformer().transform(new DOMSource(d), new StreamResult(child)); } - private static void handleFactoryPath(File child) throws XPathExpressionException, SAXException, IOException, ParserConfigurationException, TransformerConfigurationException, TransformerException, TransformerFactoryConfigurationError { + private static void handleFactoryPath(File child) throws XPathExpressionException, SAXException, IOException, ParserConfigurationException, TransformerException, TransformerFactoryConfigurationError { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //dbf.setNamespaceAware(true); Document d = dbf.newDocumentBuilder().parse(child); @@ -176,8 +164,7 @@ private static void handleFactoryPath(File child) throws XPathExpressionExceptio TransformerFactory.newInstance().newTransformer().transform(new DOMSource(d), new StreamResult(child)); } - private static interface Handler { - public String handle(File file, String old); + private interface Handler { + String handle(File file, String old); } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/env/HelpLinkExistenceTest.java b/distribution/src/test/java/com/predic8/membrane/examples/env/HelpLinkExistenceTest.java index 00ba68b7cd..ccf84db121 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/env/HelpLinkExistenceTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/env/HelpLinkExistenceTest.java @@ -30,6 +30,7 @@ import com.predic8.membrane.core.interceptor.Interceptor; import com.predic8.membrane.core.transport.http.HttpClient; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.Assertions.*; /** @@ -60,30 +61,35 @@ public void doit() throws Exception { StringBuilder errors = new StringBuilder(); for (Class clazz : classes) { if (Interceptor.class.isAssignableFrom(clazz)) { - Interceptor i = (Interceptor) clazz.newInstance(); + Interceptor i = (Interceptor) clazz.getDeclaredConstructor().newInstance(); String helpId = i.getHelpId(); - String url = "http://membrane-soa.org/service-proxy-doc/" + getVersion() + "/configuration/reference/" + helpId + ".htm"; - - Response r = hc.call(new Request.Builder().get(url).buildExchange()).getResponse(); + Response r = hc.call(new Request.Builder().get(getDocumentationReferenceURL(helpId)).buildExchange()).getResponse(); if (r.getStatusCode() != 200) - errors.append(url + " returned " + r.getStatusCode() + "." + System.lineSeparator()); + errors.append(getDocumentationReferenceURL(helpId)) + .append(" returned ") + .append(r.getStatusCode()) + .append(".") + .append(System.lineSeparator()); } } - assertTrue(errors.length() == 0, errors.toString()); + assertEquals(0, errors.length(), errors.toString()); + } + + private String getDocumentationReferenceURL(String helpId) { + return "http://membrane-soa.org/service-proxy-doc/" + getVersion() + "/configuration/reference/" + helpId + ".htm"; } @SuppressWarnings("unchecked") private Set> getElementClasses() { try { - HashSet> currentSet = new HashSet>(); + HashSet> currentSet = new HashSet<>(); - BufferedReader r = new BufferedReader(new InputStreamReader(Router.class.getResourceAsStream("/META-INF/membrane.cache"))); - try { + try (BufferedReader r = new BufferedReader(new InputStreamReader(requireNonNull(Router.class.getResourceAsStream("/META-INF/membrane.cache"))))) { if (!CACHE_FILE_FORMAT_VERSION.equals(r.readLine())) throw new RuntimeException(); - Class annotationClass = null; + Class annotationClass; boolean collecting = false; while (true) { String line = r.readLine(); @@ -109,13 +115,10 @@ private Set> getElementClasses() { collecting = annotationClass.equals(MCElement.class); } } - } finally { - r.close(); } return currentSet; } catch (IOException e) { throw new RuntimeException(e); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/ACLTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/ACLTest.java index 570c0e538b..aca6e2100f 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/ACLTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/ACLTest.java @@ -14,35 +14,27 @@ package com.predic8.membrane.examples.tests; -import static com.predic8.membrane.test.AssertUtils.getAndAssert; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import java.io.File; -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.test.AssertUtils; +import static com.predic8.membrane.test.AssertUtils.*; public class ACLTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "acl"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("acl"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { getAndAssert200("http://localhost:2000/"); - String result = getAndAssert(404, "http://localhost:2000/contacts/"); // this request succeeds through membrane, but fails on the backend with 404 - AssertUtils.assertContains("Tomcat", result); + assertContains("Tomcat", getAndAssert(404, "http://localhost:2000/contacts/")); getAndAssert(403, "http://localhost:2000/open-source/"); - } finally { - sl.killScript(); } } - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/AddSoapHeaderTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/AddSoapHeaderTest.java index 2c5ccd870f..7eea475d66 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/AddSoapHeaderTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/AddSoapHeaderTest.java @@ -14,51 +14,35 @@ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.util.BufferLogger; -import org.junit.jupiter.api.Test; -import org.xml.sax.SAXException; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import javax.xml.parsers.ParserConfigurationException; -import java.io.File; -import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static com.predic8.membrane.test.AssertUtils.postAndAssert; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.io.File.*; +import static java.lang.Thread.*; +import static org.junit.jupiter.api.Assertions.*; public class AddSoapHeaderTest extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "soap" + separator + "add-soap-header"; + } + @Test - public void test() throws IOException, InterruptedException, ParserConfigurationException, SAXException { - File baseDir = getExampleDir("/soap/add-soap-header"); + public void test() throws Exception { + BufferLogger logger = new BufferLogger(); - BufferLogger b = new BufferLogger(); - Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(b).start(); - try { - int exitCode = mvn.waitFor(60000); - if (exitCode != 0) - throw new RuntimeException("Maven exited with code " + exitCode + ": " + b.toString()); - } finally { - mvn.killScript(); + try(Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(logger).start()) { + if (mvn.waitFor(60000) != 0) + throw new RuntimeException("Maven exited with code " + mvn.waitFor(60000) + ": " + logger); } BufferLogger proxyWatcher = new BufferLogger(); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().withWatcher(proxyWatcher).start(); - try { - String body = new String(Files.readAllBytes(Paths.get(baseDir + FileSystems.getDefault().getSeparator() - + "soap-message-without-header.xml"))); - String[] headers = {"Content-Type", "application/xml"}; - String response = postAndAssert(200,"http://localhost:2000/", headers, body); - Thread.sleep(1000); - - - assertTrue(proxyWatcher.toString().contains("wss:Security")); - } finally { - sl.killScript(); + try(Process2 ignored = startServiceProxyScript(proxyWatcher)) { + postAndAssert(200, URL_2000, CONTENT_TYPE_APP_XML_HEADER, readFileFromBaseDir("soap-message-without-header.xml")); + sleep(500); + assertTrue(proxyWatcher.contains("wss:Security")); } } - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicAuthTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicAuthTest.java index 3b372b226b..5b7d9651f2 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicAuthTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicAuthTest.java @@ -24,18 +24,22 @@ import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class BasicAuthTest extends DistributionExtractingTestcase { public static final String CUSTOMER_HOST_LOCAL = "http://localhost:2000/"; public static final String CUSTOMER_HOST_REMOTE = "http://www.thomas-bayer.com/"; public static final String CUSTOMER_PATH = "samples/sqlrest/CUSTOMER/7/"; + + @Override + protected String getExampleDirName() { + return "basic-auth"; + } + @Test public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("basic-auth"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); + Process2 sl = startServiceProxyScript(); try { disableHTTPAuthentication(); getAndAssert(401, CUSTOMER_HOST_LOCAL + CUSTOMER_PATH); @@ -46,5 +50,4 @@ public void test() throws IOException, InterruptedException { sl.killScript(); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicXmlInterceptorTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicXmlInterceptorTest.java index d4af6da492..0c40772392 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicXmlInterceptorTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/BasicXmlInterceptorTest.java @@ -14,47 +14,31 @@ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.util.BufferLogger; -import org.junit.jupiter.api.Test; -import org.xml.sax.SAXException; - -import javax.xml.parsers.ParserConfigurationException; -import java.io.File; -import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static com.predic8.membrane.test.AssertUtils.postAndAssert; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; + +import static com.predic8.membrane.test.AssertUtils.*; import static org.junit.jupiter.api.Assertions.*; public class BasicXmlInterceptorTest extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "basic-xml-interceptor"; + } + @Test - public void test() throws IOException, InterruptedException, ParserConfigurationException, SAXException { - File baseDir = getExampleDir("basic-xml-interceptor"); - - BufferLogger b = new BufferLogger(); - Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(b).start(); - try { - int exitCode = mvn.waitFor(60000); - if (exitCode != 0) - throw new RuntimeException("Maven exited with code " + exitCode + ": " + b.toString()); - } finally { - mvn.killScript(); + public void test() throws Exception { + BufferLogger logger = new BufferLogger(); + try(Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(logger).start()) { + if (mvn.waitFor(60000) != 0) + throw new RuntimeException("Maven exited with code " + mvn.waitFor(60000) + ": " + logger); } - BufferLogger p = new BufferLogger(); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().withWatcher(p).start(); - try { - String body = new String(Files.readAllBytes(Paths.get(baseDir + FileSystems.getDefault().getSeparator() - + "example.xml"))); - postAndAssert(200,"http://localhost:2000/", new String[]{"Content-Type", "application/xml"}, body); - assertTrue(p.toString().contains("")); - } finally { - sl.killScript(); + logger = new BufferLogger(); + try(Process2 ignored = startServiceProxyScript(logger)) { + postAndAssert(200,URL_2000, CONTENT_TYPE_APP_XML_HEADER, readFileFromBaseDir("example.xml")); + assertTrue(logger.contains("")); } } - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/CBRTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/CBRTest.java index 6204910ba0..c438647da4 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/CBRTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/CBRTest.java @@ -16,35 +16,36 @@ import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.postAndAssert200; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.readFileToString; import java.io.File; import java.io.IOException; +import java.nio.charset.*; +import com.predic8.membrane.examples.util.*; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class CBRTest extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "cbr"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("cbr"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - Thread.sleep(2000); - String result = postAndAssert200("http://localhost:2000/shop", FileUtils.readFileToString(new File(baseDir, "order.xml"))); - assertContains("Normal order received.", result); - - result = postAndAssert200("http://localhost:2000/shop", FileUtils.readFileToString(new File(baseDir, "express.xml"))); - assertContains("Express order received.", result); - - result = postAndAssert200("http://localhost:2000/shop", FileUtils.readFileToString(new File(baseDir, "import.xml"))); - assertContains("Order contains import items.", result); - } finally { - sl.killScript(); + public void test() throws Exception { + + try(Process2 ignored = startServiceProxyScript()) { + sleep(1000); + assertContains("Normal order received.", postAndAssert200("http://localhost:2000", readFile("order.xml"))); + assertContains("Express order received.", postAndAssert200("http://localhost:2000", readFile("express.xml"))); + assertContains("Order contains import items.", postAndAssert200("http://localhost:2000", readFile("import.xml"))); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/CustomInterceptorTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/CustomInterceptorTest.java index 26c67a5403..dcd9a549af 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/CustomInterceptorTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/CustomInterceptorTest.java @@ -14,8 +14,7 @@ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.BufferLogger; import com.predic8.membrane.examples.util.SubstringWaitableConsoleEvent; import org.junit.jupiter.api.Test; @@ -27,29 +26,24 @@ import static org.junit.jupiter.api.Assertions.*; public class CustomInterceptorTest extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "custom-interceptor"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("custom-interceptor"); - - BufferLogger b = new BufferLogger(); - Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(b).start(); - try { - int exitCode = mvn.waitFor(60000); - if (exitCode != 0) - throw new RuntimeException("Maven exited with code " + exitCode + ": " + b.toString()); - } finally { - mvn.killScript(); + public void test() throws Exception { + BufferLogger logger = new BufferLogger(); + try(Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(logger).start()) { + if (mvn.waitFor(60000) != 0) + throw new RuntimeException("Maven exited with code " + mvn.waitFor(60000) + ": " + logger); } - - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + try(Process2 sl = startServiceProxyScript()) { SubstringWaitableConsoleEvent invoked = new SubstringWaitableConsoleEvent(sl, "MyInterceptor maven at request invoked."); - getAndAssert200("http://localhost:2000/"); + getAndAssert200(URL_2000); assertTrue(invoked.occurred()); - } finally { - sl.killScript(); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/DistributionExtractingTestcase.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/DistributionExtractingTestcase.java new file mode 100644 index 0000000000..75ea7284b1 --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/DistributionExtractingTestcase.java @@ -0,0 +1,236 @@ +/* Copyright 2012 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import com.predic8.membrane.core.http.*; +import com.predic8.membrane.examples.util.*; +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; + +import static com.predic8.membrane.core.http.MimeType.*; +import static com.predic8.membrane.test.AssertUtils.replaceInFile; +import static java.io.File.separator; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.io.FileUtils.readFileToString; +import static org.apache.commons.io.FileUtils.writeStringToFile; + +/** + * Extracts the .zip distribution built by Maven. + */ +public abstract class DistributionExtractingTestcase { + + public static final String MEMBRANE_LOG_LEVEL = "debug"; + + public static final String BLZ_SERVICE = "http://localhost:2000/bank/services/BLZService"; + public static final String BLZ_SERVICE_WSDL = BLZ_SERVICE + "?wsdl"; + + public static final String URL_2000 = "http://localhost:2000/"; + + public static final String[] CONTENT_TYPE_APP_XML_HEADER = {"Content-Type", APPLICATION_XML}; + public static final String[] CONTENT_TYPE_TEXT_XML_HEADER = {"Content-Type", TEXT_XML}; + + public static final String[] CONTENT_TYPE_SOAP_HEADER = {"Content-Type", APPLICATION_SOAP}; + + private File unzipDir; + private File membraneHome; + protected File baseDir = new File(getExampleDirName()); + + protected String getExampleDirName() { return "dummy"; } + + @BeforeEach + public void init() throws IOException, InterruptedException { + System.out.println("unzipping router distribution [" + getClass().getSimpleName() + "]..."); + + File targetDir = getTargetDir(); + + unzipDir = getUnzipDir(targetDir); + + unzip(getZipFile(targetDir), unzipDir); + + membraneHome = requireNonNull(unzipDir.listFiles((dir, name) -> name.startsWith("membrane-service-proxy")))[0]; + baseDir = getExampleDir(getExampleDirName()); + + replaceLog4JConfig(); + + System.out.println("running test..."); + } + + private File getTargetDir() throws IOException { + File targetDir = new File("target").getCanonicalFile(); + if (!targetDir.exists()) + throw new RuntimeException("membraneHome " + targetDir.getName() + " does not exist."); + return targetDir; + } + + private File getZipFile(File targetDir) { + File zip = null; + { + File[] files = targetDir.listFiles((dir, name) -> name.startsWith("membrane-service-proxy") && name.endsWith(".zip")); + if (files == null) { + throw new RuntimeException("Could not find zip file!"); + } + if (files.length > 1) + throw new RuntimeException("found more than one service-proxy*.zip"); + if (files.length == 1) + zip = files[0]; + } + if (zip == null) + throw new RuntimeException("TODO: calling 'ant dist-router' automatically is not implemented."); + return zip; + } + + private File getUnzipDir(File targetDir) throws InterruptedException { + File dir = new File(targetDir, "examples-automatic"); + if (dir.exists()) { + recursiveDelete(dir); + sleep(300); + } + if (!dir.mkdir()) + throw new RuntimeException("Could not mkdir " + dir.getAbsolutePath()); + return dir; + } + + private void replaceLog4JConfig() throws IOException { + File log4jproperties = new File(membraneHome, "conf" + separator + "log4j2.xml"); + if (!log4jproperties.exists()) + throw new RuntimeException("log4j2.xml does not exits."); + + writeStringToFile( + log4jproperties, + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "", UTF_8); + } + + public File getExampleDir(String name) { + File exampleDir = new File(membraneHome, "examples" + separator + name); + if (!exampleDir.exists()) + throw new RuntimeException("Example dir " + exampleDir.getAbsolutePath() + " does not exist."); + return exampleDir; + } + + public File getMembraneHome() { + return membraneHome; + } + + @AfterEach + public void done() { + System.out.println("cleaning up..."); + recursiveDelete(unzipDir); + System.out.println("done."); + } + + private void recursiveDelete(File file) { + if (file.isDirectory()) + //noinspection ConstantConditions + for (File child : file.listFiles()) + recursiveDelete(child); + if (!file.delete()) + throw new RuntimeException("could not delete " + file.getAbsolutePath()); + } + + public static void unzip(File zip, File target) throws IOException { + ZipFile zipFile = new ZipFile(zip); + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.isDirectory()) { + // Assume directories are stored parents first then children. + // This is not robust, just for demonstration purposes. + //noinspection ResultOfMethodCallIgnored + new File(target, entry.getName()).mkdir(); + } else { + final File zipEntryFile = new File(target, entry.getName()); + if (!zipEntryFile.toPath().normalize().startsWith(target.toPath().normalize())) { + throw new IOException("Bad zip entry"); + } + try (FileOutputStream fos = new FileOutputStream(zipEntryFile)) { + copyInputStream(zipFile.getInputStream(entry), + new BufferedOutputStream(fos)); + } + } + } + zipFile.close(); + } + + public static void copyInputStream(InputStream in, OutputStream out) + throws IOException { + byte[] buffer = new byte[1024]; + int len; + + while ((len = in.read(buffer)) >= 0) + out.write(buffer, 0, len); + + in.close(); + out.close(); + } + + protected String readFileFromBaseDir(String filename) throws IOException { + return readFileToString(new File(baseDir,filename), UTF_8); + } + + protected Process2 startServiceProxyScript() throws IOException, InterruptedException { + return startServiceProxyScript(null, "service-proxy"); + } + + protected Process2 startServiceProxyScript(ConsoleWatcher watch) throws IOException, InterruptedException { + return startServiceProxyScript(watch,"service-proxy"); + } + + protected Process2 startServiceProxyScript(ConsoleWatcher watch, String script) throws IOException, InterruptedException { + Process2.Builder builder = new Process2.Builder().in(baseDir); + if (watch != null) + builder = builder.withWatcher(watch); + return builder.script(script).waitForMembrane().start(); + } + + protected String readFile(String s) throws IOException { + return readFileToString(new File(baseDir, s), UTF_8); + } + + /** + * Replace String a with b in file + * @param a String to be replaced + * @param b String that replaces + * @throws IOException Problem accessing File + */ + protected void replaceInFile2(String filename, String a, String b) throws IOException { + replaceInFile(new File(baseDir, filename), a, b); + } +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/FileExchangeStoreTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/FileExchangeStoreTest.java index 4387395968..ac75ac5d1c 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/FileExchangeStoreTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/FileExchangeStoreTest.java @@ -15,65 +15,57 @@ package com.predic8.membrane.examples.tests; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; +import static java.io.File.createTempFile; +import static java.lang.Thread.sleep; +import static java.util.Calendar.*; import static org.junit.jupiter.api.Assertions.*; import java.io.File; import java.io.FilenameFilter; -import java.io.IOException; import java.util.Calendar; import org.junit.jupiter.api.Test; import com.predic8.membrane.core.exchangestore.FileExchangeStore; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class FileExchangeStoreTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "file-exchangestore"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("file-exchangestore"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { getAndAssert200("http://localhost:2000/"); - Thread.sleep(1000); + sleep(300); - File exchangesDir = new File(baseDir, "exchanges"); - if (!containsRecursively(exchangesDir, new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".msg"); - } - })) + if (!containsRecursively(new File(baseDir, "exchanges"), this::filterDotMsg)) throw new AssertionError("Did not find *.msg in exchanges dir."); - } finally { - sl.killScript(); } } + private boolean filterDotMsg(File dir, String name) { + return name.endsWith(".msg"); + } + @Test public void testDeleteOldFolders() throws Exception { - Calendar c = Calendar.getInstance(); - c.set(Calendar.YEAR, 2015); - c.set(Calendar.MONTH, 2); // 2 = March - c.set(Calendar.DAY_OF_MONTH, 15); + File t = createTempFile("fes", null); - File t = File.createTempFile("fes", null); + //noinspection ResultOfMethodCallIgnored t.delete(); File base = new File(t, "FileExchangeStoreTest"); - base.mkdirs(); - for (int m = 1; m<=3; m++) - for (int d = 1; d<=31; d++) - if (!(m == 2 && d > 28)) - new File(base, "2015/"+m+"/"+d).mkdirs(); + //noinspection ResultOfMethodCallIgnored + base.mkdirs(); - FileExchangeStore fes = new FileExchangeStore(); - fes.setDir(base.getAbsolutePath()); - fes.setMaxDays(30); + renameMe(base); // before for (int m = 1; m<=3; m++) @@ -81,7 +73,7 @@ public void testDeleteOldFolders() throws Exception { if (!(m == 2 && d > 28)) assertTrue(new File(base, "2015/"+m+"/"+d).exists()); - fes.deleteOldFolders(c); + getFileExchangeStore(base).deleteOldFolders(getCalendar()); // after for (int d = 1; d<=31; d++) @@ -97,16 +89,41 @@ public void testDeleteOldFolders() throws Exception { recursiveDelete(base); } + private void renameMe(File base) { + for (int m = 1; m<=3; m++) + for (int d = 1; d<=31; d++) + if (!(m == 2 && d > 28)) + //noinspection ResultOfMethodCallIgnored + new File(base, "2015/"+m+"/"+d).mkdirs(); + } + + private Calendar getCalendar() { + Calendar c = Calendar.getInstance(); + c.set(YEAR, 2015); + c.set(MONTH, 2); // 2 = March + c.set(DAY_OF_MONTH, 15); + return c; + } + + private FileExchangeStore getFileExchangeStore(File base) { + FileExchangeStore fes = new FileExchangeStore(); + fes.setDir(base.getAbsolutePath()); + fes.setMaxDays(30); + return fes; + } + private void recursiveDelete(File file) { if (file.isDirectory()) + + //noinspection ConstantConditions for (File child : file.listFiles()) recursiveDelete(child); if (!file.delete()) throw new RuntimeException("could not delete " + file.getAbsolutePath()); } - private boolean containsRecursively(File base, FilenameFilter filter) { + //noinspection ConstantConditions for (File f : base.listFiles()) { if (f.isDirectory()) if (containsRecursively(f, filter)) @@ -116,5 +133,4 @@ private boolean containsRecursively(File base, FilenameFilter filter) { } return false; } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/GroovyTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/GroovyTest.java index 57c079c2ce..c2161a17ec 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/GroovyTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/GroovyTest.java @@ -14,32 +14,25 @@ package com.predic8.membrane.examples.tests; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; +import com.predic8.membrane.examples.util.*; +import org.apache.http.*; +import org.junit.jupiter.api.*; -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.util.SubstringWaitableConsoleEvent; +import static com.predic8.membrane.test.AssertUtils.*; +import static org.junit.jupiter.api.Assertions.*; public class GroovyTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "groovy"; + } + @Test - public void test() throws IOException, InterruptedException { - Process2 sl = new Process2.Builder().in(getExampleDir("groovy")) - //.withWatcher(new com.predic8.membrane.examples.util.ConsoleLogger()) - .script("service-proxy").waitForMembrane().start(); - try { - SubstringWaitableConsoleEvent groovyCalled = - new SubstringWaitableConsoleEvent(sl, "X-Groovy header added with value :Groovy interceptor"); - getAndAssert200("http://localhost:2000/"); - assertTrue(groovyCalled.occurred()); - } finally { - sl.killScript(); + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + HttpResponse res = getAndAssertWithResponse(200,"http://localhost:2000/", null); + assertEquals("42",res.getFirstHeader("X-Groovy").getValue()); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/InternalProxyTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/InternalProxyTest.java index 9b72eb0daf..a4a935d161 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/InternalProxyTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/InternalProxyTest.java @@ -13,90 +13,67 @@ limitations under the License. */ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.core.http.*; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.SubstringWaitableConsoleEvent; -import com.predic8.membrane.test.AssertUtils; import org.junit.jupiter.api.Test; -import java.io.File; -import java.io.IOException; import java.nio.file.FileSystems; -import java.nio.file.Files; import java.nio.file.Paths; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; -import static com.predic8.membrane.test.AssertUtils.postAndAssert; -import static org.junit.jupiter.api.Assertions.*; +import static com.predic8.membrane.core.http.MimeType.TEXT_PLAIN_UTF8; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.nio.file.Files.readAllBytes; import static org.junit.jupiter.api.Assertions.*; public class InternalProxyTest extends DistributionExtractingTestcase { + final static String ENDPOINT_URL = "http://localhost:2000/axis2/services/BLZService"; + + @Override + protected String getExampleDirName() { + return "internalproxy"; + } @Test - public void testWsdl() throws IOException, InterruptedException { - File baseDir = getExampleDir("internalproxy"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - String result = getAndAssert200("http://localhost:2000/axis2/services/BLZService"); - AssertUtils.assertContains("Service Proxy: BLZService", result); - } finally { - sl.killScript(); + public void testWsdl() throws Exception { + try(Process2 sl = startServiceProxyScript()) { + assertContains("Service Proxy: BLZService", getAndAssert200(ENDPOINT_URL)); } } @Test - public void testSoapRequest() throws IOException, InterruptedException { - File baseDir = getExampleDir("internalproxy"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - - try { - String body = new String(Files.readAllBytes(Paths.get(baseDir + FileSystems.getDefault().getSeparator() - + "soap_request.xml"))); - String[] headers = {"Content-Type", "text/xml;charset=UTF-8", "SOAPAction", "Get"}; - String response = postAndAssert(200,"http://localhost:2000/axis2/services/BLZService", headers, body); - AssertUtils.assertContains("COLSDE33XXX", response); - } finally { - sl.killScript(); + public void testSoapRequest() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + assertContains("COLSDE33XXX", postAndAssert(200,ENDPOINT_URL, getSoapRequestHeader(), readFileFromBaseDir("soap_request.xml"))); } } + private String[] getSoapRequestHeader() { + return new String[]{"Content-Type", TEXT_PLAIN_UTF8, "SOAPAction", "Get"}; + } + @Test - public void testCbrRequest() throws IOException, InterruptedException { - File baseDir = getExampleDir("internalproxy"); - AssertUtils.replaceInFile(new File(baseDir, "service-proxy.sh"), "proxies_soap", "proxies_service"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); + public void testCbrRequest() throws Exception { + replaceInFile2("service-proxy.sh","proxies_soap", "proxies_service"); - try { + try(Process2 sl = startServiceProxyScript()) { SubstringWaitableConsoleEvent internalOutput = new SubstringWaitableConsoleEvent(sl, "Inside proxy mybackend"); - String body = new String(Files.readAllBytes(Paths.get(baseDir + FileSystems.getDefault().getSeparator() - + "express.xml"))); - String[] headers = {"Content-Type", "text/xml;charset=UTF-8"}; - postAndAssert(200,"http://localhost:2000", headers, body); + postAndAssert(200,"http://localhost:2000", new String[]{"Content-Type", "text/xml;charset=UTF-8"}, readFileFromBaseDir("express.xml")); assertTrue(internalOutput.occurred()); - - - } finally { - sl.killScript(); } } @Test - public void testCbrRequestWithoutInternal() throws IOException, InterruptedException { - File baseDir = getExampleDir("internalproxy"); - AssertUtils.replaceInFile(new File(baseDir, "service-proxy.sh"), "proxies_soap", "proxies_service"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); + public void testCbrRequestWithoutInternal() throws Exception { + replaceInFile2("service-proxy.sh","proxies_soap", "proxies_service"); - try { + try(Process2 sl = startServiceProxyScript()) { SubstringWaitableConsoleEvent internalOutput = new SubstringWaitableConsoleEvent(sl, "Inside proxy mybackend"); getAndAssert200("http://localhost:2000"); assertFalse(internalOutput.occurred()); - - } finally { - sl.killScript(); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/Json2XmlTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/Json2XmlTest.java index 02f53c8cec..6f60faf688 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/Json2XmlTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/Json2XmlTest.java @@ -13,8 +13,8 @@ limitations under the License. */ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.core.http.*; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.BufferLogger; import org.junit.jupiter.api.Test; @@ -24,29 +24,26 @@ import java.nio.file.Files; import java.nio.file.Paths; +import static com.predic8.membrane.core.http.MimeType.APPLICATION_JSON; import static com.predic8.membrane.test.AssertUtils.postAndAssert; +import static java.lang.Thread.sleep; import static org.junit.jupiter.api.Assertions.assertTrue; public class Json2XmlTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "json-2-xml"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("json-2-xml"); - BufferLogger b = new BufferLogger(); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().withWatcher(b).start(); - try { - String body = new String(Files.readAllBytes(Paths.get(baseDir + FileSystems.getDefault().getSeparator() - + "customers.json"))); - String[] headers = {"Content-Type", "application/json"}; - String response = postAndAssert(200,"http://localhost:2000/", headers, body); - Thread.sleep(1000); - - assertTrue(b.toString().contains("269")); - - } finally { - sl.killScript(); + public void test() throws Exception { + BufferLogger logger = new BufferLogger(); + try(Process2 ignored = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().withWatcher(logger).start()) { + sleep(1000); + postAndAssert(200,"http://localhost:2000/", new String[]{"Content-Type", APPLICATION_JSON}, readFileFromBaseDir("customers.json")); + sleep(500); + assertTrue(logger.toString().contains("269")); } } - - } \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerBasic1Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerBasic1Test.java deleted file mode 100644 index a8862709c8..0000000000 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerBasic1Test.java +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2012 predic8 GmbH, www.predic8.com - - 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.predic8.membrane.examples.tests; - -import static com.predic8.membrane.examples.tests.LoadBalancerUtil.addLBNodeViaHTML; -import static com.predic8.membrane.test.AssertUtils.getAndAssert; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.File; -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.test.AssertUtils; - -public class LoadBalancerBasic1Test extends DistributionExtractingTestcase { - - @Test - public void test() throws IOException, InterruptedException { - File base = getExampleDir("loadbalancer-1-basic"); - - AssertUtils.replaceInFile(new File(base, "proxies.xml"), "8080", "3023"); - - Process2 sl = new Process2.Builder().in(base).script("service-proxy").waitForMembrane().start(); - try { - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:4000/")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:4001/")); - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:4002/")); - - addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4000); - addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4001); - - Thread.sleep(1000); - - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - - getAndAssert(204, "http://localhost:9010/clustermanager/up?host=localhost&port=4002"); - - AssertUtils.assertContains("localhost:4002", - getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default")); - - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - - - } finally { - sl.killScript(); - } - } - - - -} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerClient2Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerClient2Test.java deleted file mode 100644 index 3d65a4f8d8..0000000000 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerClient2Test.java +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright 2012 predic8 GmbH, www.predic8.com - - 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.predic8.membrane.examples.tests; - -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; -import static com.predic8.membrane.examples.tests.LoadBalancerUtil.assertNodeStatus; -import static org.apache.commons.io.FileUtils.readFileToString; -import static org.apache.commons.io.FileUtils.writeStringToFile; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.File; -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; - -public class LoadBalancerClient2Test extends DistributionExtractingTestcase { - - @Test - public void test() throws IOException, InterruptedException { - File base = getExampleDir("loadbalancer-2-client"); - - AssertUtils.replaceInFile(new File(base, "proxies.xml"), "8080", "3023"); - AssertUtils.replaceInFile(new File(base, "lb-client-secured.proxies.xml"), "8080", "3023"); - - Process2 sl = new Process2.Builder().in(base).script("service-proxy").waitForMembrane().start(); - try { - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:4000/")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:4001/")); - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:4002/")); - - addNodeViaScript(base, "localhost", 4000); - - Thread.sleep(1000); - - assertNodeStatus( - getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default"), - "localhost", 4000, "UP"); - - addNodeViaScript(base, "localhost", 4001); - addNodeViaScript(base, "localhost", 4002); - - Thread.sleep(100); - - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - - removeNodeViaScript(base, "localhost", 4000); - - Thread.sleep(100); - - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - } finally { - sl.killScript(); - } - - sl = new Process2.Builder().in(base).script("service-proxy-secured").waitForMembrane().start(); - try { - controlNodeViaScript(1, base, "up", "localhost", 4000); // 1 indicates failure - - File propFile = new File(base, "client.properties"); - writeStringToFile(propFile, readFileToString(propFile).replace("#", "")); - - Thread.sleep(1000); - - addNodeViaScript(base, "localhost", 4000); - - Thread.sleep(1000); - - AssertUtils.setupHTTPAuthentication("localhost", 9000, "admin", "admin"); - AssertUtils.assertContains("localhost:4000", - getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default")); - - } finally { - sl.killScript(); - } - - } - - - private void addNodeViaScript(File base, String nodeHost, int nodePort) throws IOException, InterruptedException { - controlNodeViaScript(base, "up", nodeHost, nodePort); - } - - private void removeNodeViaScript(File base, String nodeHost, int nodePort) throws IOException, InterruptedException { - controlNodeViaScript(base, "down", nodeHost, nodePort); - } - - private void controlNodeViaScript(File base, String command, String nodeHost, int nodePort) throws IOException, InterruptedException { - controlNodeViaScript(0, base, command, nodeHost, nodePort); - } - - private void controlNodeViaScript(int expectedReturnCode, File base, String command, String nodeHost, int nodePort) throws IOException, InterruptedException { - String line; - if (Process2.isWindows()) - line = "cmd /c lbclient.bat " + command + " " + nodeHost + " " + nodePort; - else - line = "bash lbclient.sh " + command + " " + nodeHost + " " + nodePort; - - Process2 lbclient = new Process2.Builder().in(base).executable(line).start(); - try { - assertEquals(expectedReturnCode, lbclient.waitFor(30000)); - } finally { - lbclient.killScript(); - } - } - -} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerMultiple4Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerMultiple4Test.java deleted file mode 100644 index b40d85379a..0000000000 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerMultiple4Test.java +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2012 predic8 GmbH, www.predic8.com - - 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.predic8.membrane.examples.tests; - -import static com.predic8.membrane.test.AssertUtils.getAndAssert; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; -import static com.predic8.membrane.examples.tests.LoadBalancerUtil.assertNodeStatus; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.File; -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; - -public class LoadBalancerMultiple4Test extends DistributionExtractingTestcase { - - @Test - public void test() throws IOException, InterruptedException { - - File base = getExampleDir("loadbalancer-4-multiple"); - - AssertUtils.replaceInFile(new File(base, "proxies.xml"), "8080", "3023"); - AssertUtils.replaceInFile(new File(base, "proxies.xml"), "8081", "3024"); - - Process2 sl = new Process2.Builder().in(base).script("service-proxy").waitForMembrane().start(); - try { - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(2, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:3024/service")); - assertEquals(4, LoadBalancerUtil.getRespondingNode("http://localhost:3024/service")); - assertEquals(3, LoadBalancerUtil.getRespondingNode("http://localhost:3024/service")); - assertEquals(4, LoadBalancerUtil.getRespondingNode("http://localhost:3024/service")); - - String status = getAndAssert200("http://localhost:9000/admin/clusters/show?balancer=balancer1&cluster=Default"); - assertNodeStatus(status, "localhost", 4000, "UP"); - assertNodeStatus(status, "localhost", 4001, "UP"); - - getAndAssert(204, "http://localhost:9010/clustermanager/down?balancer=balancer1&host=localhost&port=4001"); - Thread.sleep(1000); - - status = getAndAssert200("http://localhost:9000/admin/clusters/show?balancer=balancer1&cluster=Default"); - assertNodeStatus(status, "localhost", 4000, "UP"); - assertNodeStatus(status, "localhost", 4001, "DOWN"); - - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - assertEquals(1, LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - - } finally { - sl.killScript(); - } - } - - - - -} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerSession3Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerSession3Test.java deleted file mode 100644 index 2d14e40a67..0000000000 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerSession3Test.java +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright 2012 predic8 GmbH, www.predic8.com - - 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.predic8.membrane.examples.tests; - -import java.io.File; -import java.io.IOException; -import java.util.regex.Pattern; - -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.util.BufferLogger; - -public class LoadBalancerSession3Test extends DistributionExtractingTestcase { - - /** - * The test as described in README.txt, but "wsimport" (previously called by ant) - * was removed and is run directly from this test before everything else. Thereby - * we can use a Maven dependency on wsimport and do not have to download it ourselves. - */ - @Test - public void test() throws IOException, InterruptedException { - File base = getExampleDir("loadbalancer-3-session"); - - AssertUtils.replaceInFile(new File(base, "proxies.xml"), "8080", "3023"); - AssertUtils.replaceInFile(new File(base, "src/main/java/com/predic8/chat/Client.java"), "8080", "3023"); - AssertUtils.replaceInFile(new File(base, "data/ChatService.wsdl"), "8080", "3023"); - - Process2 sl = new Process2.Builder().in(base).script("service-proxy").waitForMembrane().start(); - try { - // call "ant compile" now so that both antNodeX processes do call it at the same time - BufferLogger loggerCompile = new BufferLogger(); - Process2 antCompile = new Process2.Builder().in(base).withWatcher(loggerCompile).executable("mvn package").start(); - try { - int result = antCompile.waitFor(60000); - if (result != 0) - throw new AssertionError("'mvn package' returned non-zero " + result + ":\r\n" + loggerCompile.toString()); - } finally { - antCompile.killScript(); - } - - - BufferLogger loggerNode1 = new BufferLogger(); - BufferLogger loggerNode2 = new BufferLogger(); - Process2 antNode1 = new Process2.Builder().in(base).withWatcher(loggerNode1).executable("mvn exec:java@node1").start(); - try { - Process2 antNode2 = new Process2.Builder().in(base).withWatcher(loggerNode2).executable("mvn exec:java@node2").start(); - try { - - LoadBalancerUtil.addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4000); - LoadBalancerUtil.addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4001); - - Thread.sleep(1000); // wait for nodes to come up - - Process2 antClient = new Process2.Builder().in(base).executable("mvn exec:java@client").start(); - try { - antClient.waitFor(60000); - } finally { - antClient.killScript(); - } - - } finally { - antNode2.killScript(); - } - } finally { - antNode1.killScript(); - } - - AssertUtils.assertContains("Hallo World", loggerNode1.toString()); - AssertUtils.assertContainsNot("Hallo World", loggerNode2.toString()); - } finally { - sl.killScript(); - } - - } - -} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerStaticTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerStaticTest.java deleted file mode 100644 index 9986d3329d..0000000000 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerStaticTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright 2012 predic8 GmbH, www.predic8.com - - 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.predic8.membrane.examples.tests; - -import java.io.File; -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class LoadBalancerStaticTest extends DistributionExtractingTestcase { - - @Test - public void test() throws IOException, InterruptedException { - File base = getExampleDir("loadbalancer-static"); - - AssertUtils.replaceInFile(new File(base, "proxies.xml"), "8080", "3023"); - - Process2 sl = new Process2.Builder().in(base).script("service-proxy").waitForMembrane().start(); - try { - for (int i = 0; i < 7; i++) - assertEquals( - i % 3 + 1, - LoadBalancerUtil.getRespondingNode("http://localhost:3023/service")); - } finally { - sl.killScript(); - } - } - -} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingCSVTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingCSVTest.java index eda476d916..c477c3297c 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingCSVTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingCSVTest.java @@ -14,31 +14,33 @@ package com.predic8.membrane.examples.tests; +import static com.predic8.membrane.core.http.MimeType.TEXT_HTML; import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.commons.io.FileUtils.readFileToString; import java.io.File; import java.io.IOException; +import java.nio.charset.*; +import com.predic8.membrane.core.http.*; import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class LoggingCSVTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "logging/csv"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("logging-csv"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { getAndAssert200("http://localhost:2000/"); - } finally { - sl.killScript(); } - assertContains("text/html", readFileToString(new File(baseDir, "log.csv"))); + assertContains(TEXT_HTML, readFile("log.csv")); } - - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingJDBCTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingJDBCTest.java index a414e747ff..1adb32a065 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingJDBCTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingJDBCTest.java @@ -14,91 +14,86 @@ package com.predic8.membrane.examples.tests; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; -import static org.apache.commons.io.FileUtils.copyFileToDirectory; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import java.io.File; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.io.*; +import java.sql.*; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.io.File.separator; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.*; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.io.FileUtils.*; +import static org.junit.jupiter.api.Assertions.*; public class LoggingJDBCTest extends DistributionExtractingTestcase { - @Test - public void test() throws IOException, InterruptedException, InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException { - copyDerbyJarToMembraneLib("org.apache.derby.jdbc.EmbeddedDriver"); - copyDerbyJarToMembraneLib("org.apache.derby.iapi.jdbc.JDBCBoot"); - copyDerbyJarToMembraneLib("org.apache.derby.shared.common.error.StandardException"); - - File baseDir = getExampleDir("logging-jdbc"); - File beansConfig = new File(baseDir, "proxies.xml"); - FileUtils.writeStringToFile(beansConfig, FileUtils.readFileToString(beansConfig). - replace("org.apache.derby.jdbc.ClientDriver", "org.apache.derby.jdbc.EmbeddedDriver"). - replace("jdbc:derby://localhost:1527/membranedb;create=true", "jdbc:derby:derbyDB;create=true") - ); - - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - getAndAssert200("http://localhost:2000/"); - } finally { - sl.killScript(); - } - - assertLogToDerbySucceeded(baseDir); - } - - private void assertLogToDerbySucceeded(File baseDir) - throws InstantiationException, IllegalAccessException, - ClassNotFoundException, SQLException { - String driver = "org.apache.derby.jdbc.EmbeddedDriver"; - Class.forName(driver).newInstance(); - - File db = new File(baseDir, "derbyDB"); - Connection conn = DriverManager.getConnection("jdbc:derby:" + db.getAbsolutePath().replace("\\", "/")); - try { - Statement stmt = conn.createStatement(); - try { - ResultSet rs = stmt.executeQuery("select METHOD from MEMBRANE.STATISTIC"); - try { - assertTrue(rs.next()); - assertEquals("GET", rs.getString(1)); - } finally { - rs.close(); - } - } finally { - stmt.close(); - } - } finally { - conn.close(); - } - - try { - DriverManager.getConnection("jdbc:derby:;shutdown=true"); - } catch (SQLException e) { - // do nothing - } - } - - private void copyDerbyJarToMembraneLib(String clazz) throws IOException { - String classJar = getClass().getResource("/" + clazz.replace('.', '/') + ".class").getPath(); - File derbyJar = new File(classJar.split("!")[0].substring(Process2.isWindows() ? 6 : 5)); - - if (!derbyJar.exists()) - throw new AssertionError("derby jar not found in classpath (it's either missing or the detection logic broken). classJar=" + classJar); - - copyFileToDirectory(derbyJar, new File(getMembraneHome(), "lib")); - } - - -} + @Override + protected String getExampleDirName() { + return "logging" + separator + "jdbc-database"; + } + + @Test + public void test() throws Exception { + copyDerbyLibraries(); + + writeStringToFile(new File(baseDir, "proxies.xml"), readFileFromBaseDir("proxies.xml"). + replace("org.apache.derby.jdbc.ClientDriver", "org.apache.derby.jdbc.EmbeddedDriver"). + replace("jdbc:derby://localhost:1527/membranedb;create=true", "jdbc:derby:derbyDB;create=true"), UTF_8); + + try (Process2 ignored = startServiceProxyScript()) { + getAndAssert200("http://localhost:2000/"); + } + + assertLogToDerbySucceeded(); + } + + private void copyDerbyLibraries() throws IOException { + copyDerbyJarToMembraneLib("org.apache.derby.jdbc.EmbeddedDriver"); + copyDerbyJarToMembraneLib("org.apache.derby.iapi.jdbc.JDBCBoot"); + copyDerbyJarToMembraneLib("org.apache.derby.shared.common.error.StandardException"); + } + + private void assertLogToDerbySucceeded() throws Exception { + sleep(1000); // We have to wait till the Membrane process is terminated, otherwise the derbyDB file is still used by Membrane + Class.forName("org.apache.derby.jdbc.EmbeddedDriver").getDeclaredConstructor().newInstance(); + + try (Connection conn = getConnection()) { + try (Statement stmt = conn.createStatement()) { + //noinspection SqlResolve,SqlNoDataSourceInspection + try (ResultSet rs = stmt.executeQuery("select METHOD from MEMBRANE.STATISTIC")) { + assertTrue(rs.next()); + assertEquals("GET", rs.getString(1)); + } + } + } + } + + private Connection getConnection() throws SQLException { + return DriverManager.getConnection("jdbc:derby:" + getDBFile("derbyDB").getAbsolutePath().replace("\\", "/")); + } + + private File getDBFile(String derbyDB) { + return new File(baseDir, derbyDB); + } + + private void copyDerbyJarToMembraneLib(String clazz) throws IOException { + + File derbyJar = getDerbyJarFile(getClassJar(clazz)); + + if (!derbyJar.exists()) + throw new AssertionError("derby jar not found in classpath (it's either missing or the detection logic broken). classJar=" + getClassJar(clazz)); + + copyFileToDirectory(derbyJar, new File(getMembraneHome(), "lib")); + } + + private String getClassJar(String clazz) { + return requireNonNull(getClass().getResource("/" + clazz.replace('.', '/') + ".class")).getPath(); + } + + private File getDerbyJarFile(String classJar) { + return new File(classJar.split("!")[0].substring(Process2.isWindows() ? 6 : 5)); + } +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingTest.java index 78bd5f959b..7d6e92d7d2 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoggingTest.java @@ -14,6 +14,7 @@ package com.predic8.membrane.examples.tests; +import static com.predic8.membrane.test.AssertUtils.getAndAssert200; import static org.junit.jupiter.api.Assertions.*; import java.io.IOException; @@ -21,22 +22,22 @@ import org.junit.jupiter.api.Test; import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.SubstringWaitableConsoleEvent; public class LoggingTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "logging/console"; + } + @Test - public void test() throws IOException, InterruptedException { - Process2 sl = new Process2.Builder().in(getExampleDir("logging")).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 sl = startServiceProxyScript()) { SubstringWaitableConsoleEvent logged = new SubstringWaitableConsoleEvent(sl, "HTTP/1.1"); - AssertUtils.getAndAssert200("http://localhost:2000/"); - assertEquals(true, logged.occurred()); - } finally { - sl.killScript(); + getAndAssert200("http://localhost:2000/"); + assertTrue(logged.occurred()); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoginTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoginTest.java index dafff7a6f1..11817e1a1c 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoginTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/LoginTest.java @@ -16,48 +16,51 @@ import java.io.IOException; +import com.predic8.membrane.core.http.*; import org.junit.jupiter.api.Test; import com.predic8.membrane.core.interceptor.authentication.session.totp.OtpProvider; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.test.AssertUtils; +import static com.predic8.membrane.core.http.MimeType.APPLICATION_X_WWW_FORM_URLENCODED; +import static com.predic8.membrane.test.AssertUtils.*; + public class LoginTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "login"; + } + @Test - public void test() throws IOException, InterruptedException { - Process2 sl = new Process2.Builder().in(getExampleDir("login")).script("service-proxy").waitForMembrane().start(); - try { - String form = AssertUtils.getAndAssert200("http://localhost:2000/"); - AssertUtils.assertContains("Username:", form); - AssertUtils.assertContains("Password:", form); - - form = AssertUtils.postAndAssert(200, "http://localhost:2000/login/", + public void test() throws Exception { + try (Process2 ignored =startServiceProxyScript()) { + String form = getAndAssert200("http://localhost:2000/"); + assertContains("Username:", form); + assertContains("Password:", form); + + form = postAndAssert(200, "http://localhost:2000/login/", new String[] { "Content-Type", "application/x-www-form-urlencoded" }, "username=john&password=password"); - AssertUtils.assertContains("token:", form); + assertContains("token:", form); - String token = new OtpProvider().getNextCode("abcdefghijklmnop", System.currentTimeMillis()); - - form = AssertUtils.postAndAssert(200, "http://localhost:2000/login/", - new String[] { "Content-Type", "application/x-www-form-urlencoded" }, - "token=" + token); + form = postAndAssert(200, "http://localhost:2000/login/", + new String[] { "Content-Type", APPLICATION_X_WWW_FORM_URLENCODED }, + "token=" + getToken()); // successful login? - AssertUtils.assertContains("This page has moved to", form); + assertContains("This page has moved to", form); // access the "protected" page - form = AssertUtils.getAndAssert200("http://localhost:2000/"); - AssertUtils.assertContains("predic8.com", form); + assertContains("predic8.com", getAndAssert200("http://localhost:2000/")); // logout - form = AssertUtils.getAndAssert200("http://localhost:2000/login/logout"); - AssertUtils.assertContains("Username:", form); - - } finally { - sl.killScript(); + assertContains("Username:", getAndAssert200("http://localhost:2000/login/logout")); } } + private String getToken() { + return new OtpProvider().getNextCode("abcdefghijklmnop", System.currentTimeMillis()); + } } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2ApiTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2ApiTest.java index f6b9452eda..17cbcc3b7e 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2ApiTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2ApiTest.java @@ -13,8 +13,7 @@ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.BufferLogger; import org.junit.jupiter.api.Test; @@ -23,24 +22,27 @@ public class OAuth2ApiTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "oauth2/api"; + } + @Test public void test() throws Exception { - Process2 sl = new Process2.Builder().in(getExampleDir("oauth2/api/authorization_server")).script("service-proxy").waitForMembrane() - .start(); - - Process2 sl2 = new Process2.Builder().in(getExampleDir("oauth2/api/token_validator")).script("service-proxy").waitForMembrane() - .start(); - - BufferLogger b = new BufferLogger(); - Process2 sl3 = new Process2.Builder().in(getExampleDir("oauth2/api")).withWatcher(b).script("start").waitAfterStartFor("OK").start(); - // sl3 can fail because at least the start.sh is very fragile in parsing the response for the access token. If the number or order of the params changes then start.sh will fail. - try { - //This is kind of redundant as sl3 already waits until "OK" is written or timeouts when its not - assertTrue(b.toString().contains("OK")); - } finally { - sl.killScript(); - sl2.killScript(); - sl3.killScript(); + try (Process2 sl = new Process2.Builder().in(getExampleDir("oauth2/api/authorization_server")).script("service-proxy").waitForMembrane().start()) { + + Process2 sl2 = new Process2.Builder().in(getExampleDir("oauth2/api/token_validator")).script("service-proxy").waitForMembrane().start(); + + BufferLogger logger = new BufferLogger(); + Process2 sl3 = new Process2.Builder().in(getExampleDir("oauth2/api")).withWatcher(logger).script("client").parameters("john password").waitAfterStartFor("200 O").start(); + // sl3 can fail because at least the start.sh is very fragile in parsing the response for the access token. If the number or order of the params changes then client.sh will fail. + try { + //This is kind of redundant as sl3 already waits until "OK" is written or timeouts when its not + assertTrue(logger.toString().contains("200 O")); + } finally { + sl2.killScript(); + sl3.killScript(); + } } } } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2MembraneTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2MembraneTest.java index 68653f0484..b04b2cd261 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2MembraneTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/OAuth2MembraneTest.java @@ -13,16 +13,17 @@ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.util.BufferLogger; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.test.AssertUtils; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; +// TODO Include in Testsuite, See also OAuth2ApiTest public class OAuth2MembraneTest extends DistributionExtractingTestcase { + + @Test public void test() throws Exception { Process2 sl = new Process2.Builder().in(getExampleDir("oauth2/membrane/authorization_server")).script("service-proxy").waitForMembrane() diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/ProxyTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/ProxyTest.java index cb30e76a3c..fb980b7948 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/ProxyTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/ProxyTest.java @@ -21,22 +21,20 @@ import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class ProxyTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "proxy"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("proxy"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { getAndAssert200("http://localhost:2000/axis2/services/BLZService?wsdl"); getAndAssert200("http://localhost:2001/axis2/services/BLZService?wsdl"); - - } finally { - sl.killScript(); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartRESTTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartRESTTest.java index f4d269f458..57a76e9c27 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartRESTTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartRESTTest.java @@ -14,27 +14,31 @@ package com.predic8.membrane.examples.tests; -import static com.predic8.membrane.test.AssertUtils.assertContains; -import static com.predic8.membrane.test.AssertUtils.assertContainsNot; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.readFileToString; import java.io.File; import java.io.IOException; +import java.nio.charset.*; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.ProxiesXmlUtil; +import com.predic8.membrane.examples.util.Process2; +import com.predic8.membrane.examples.util.ProxiesXmlUtil; import com.predic8.membrane.test.AssertUtils; public class QuickstartRESTTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "quickstart-rest"; + } + @Test public void doit() throws IOException, InterruptedException { - File baseDir = getExampleDir("quickstart-rest"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); + Process2 sl = startServiceProxyScript(); try { String result = getAndAssert200("http://localhost:2000/restnames/name.groovy?name=Pia"); assertContains("Italy", result); @@ -75,15 +79,12 @@ public void doit() throws IOException, InterruptedException { assertContains("Italy, Spain", result); assertContainsNot(",<", result); - String csvLog = FileUtils.readFileToString(new File(baseDir, "log.csv")); - assertContains("Pia", csvLog); + assertContains("Pia", readFileFromBaseDir("log.csv")); - AssertUtils.setupHTTPAuthentication("localhost", 9000, "alice", "membrane"); - result = getAndAssert200("http://localhost:9000/admin/"); - assertContains("ServiceProxies", result); + setupHTTPAuthentication("localhost", 9000, "alice", "membrane"); + assertContains("ServiceProxies", getAndAssert200("http://localhost:9000/admin/")); } finally { sl.killScript(); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartSOAPTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartSOAPTest.java index 8b2d7e478b..0bfae14b97 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartSOAPTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/QuickstartSOAPTest.java @@ -18,17 +18,19 @@ import static com.predic8.membrane.test.AssertUtils.assertContainsNot; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; import static com.predic8.membrane.test.AssertUtils.postAndAssert; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; -import org.junit.jupiter.api.Test; +import org.apache.logging.log4j.core.util.*; +import org.junit.jupiter.api.*; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.ProxiesXmlUtil; +import com.predic8.membrane.examples.util.Process2; +import com.predic8.membrane.examples.util.ProxiesXmlUtil; import com.predic8.membrane.test.AssertUtils; +// TODO Remove when test for new Quickstart is written public class QuickstartSOAPTest extends DistributionExtractingTestcase { @Test @@ -78,7 +80,7 @@ public void doit() throws IOException, InterruptedException { AssertUtils.setupHTTPAuthentication("localhost", 9000, "admin", "membrane"); result = getAndAssert200("http://localhost:9000/admin/"); - result.contains("BLZService"); + assertTrue(result.contains("BLZService")); String invalidRequest = "\r\n" + @@ -152,17 +154,13 @@ public void doit() throws IOException, InterruptedException { " \r\n" + "", sl); - result = postAndAssert(400, endpoint, invalidRequest); - assertContains("Validation failed", result); + assertContains("Validation failed", postAndAssert(400, endpoint, invalidRequest)); - result = getAndAssert200("http://localhost:9000/admin/service-proxy/show?name=BLZService%3A2000"); - result.contains("1 of 1 messages have been invalid"); + assertContains("1 of 1 messages have been invalid", getAndAssert200("http://localhost:9000/admin/service-proxy/show?name=BLZService%3A2000")); - result = getAndAssert200(endpoint); - assertContains("Target Namespace", result); + assertContains("Target Namespace", getAndAssert200(endpoint)); - result = getAndAssert200(endpoint + "/operation/BLZServiceSOAP11Binding/BLZServicePortType/getBank"); - assertContains("blz>?XXX?", result); + assertContains("blz>?XXX?", getAndAssert200(endpoint + "/operation/BLZServiceSOAP11Binding/BLZServicePortType/getBank")); AssertUtils.closeConnections(); diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPJSONTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPJSONTest.java index 7933d6d867..c5ad510a3c 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPJSONTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPJSONTest.java @@ -14,36 +14,36 @@ package com.predic8.membrane.examples.tests; +import static com.predic8.membrane.core.http.MimeType.APPLICATION_JSON; import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; import java.io.File; import java.io.IOException; +import com.predic8.membrane.core.http.*; import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.test.AssertUtils; public class REST2SOAPJSONTest extends DistributionExtractingTestcase { + static final String[] ACCEPT_HEADER = new String[] { "Accept", APPLICATION_JSON}; + + @Override + protected String getExampleDirName() { + return "rest2soap-json"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("rest2soap-json"); - AssertUtils.replaceInFile(new File(baseDir, "proxies.xml"), "2000", "2043"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + replaceInFile2("proxies.xml", "2000", "2043"); + try(Process2 ignored = startServiceProxyScript()) { assertContains("\"bic\":\"COLSDE33XXX\"", - getAndAssert200("http://localhost:2043/bank/37050198", - new String[] { "Accept", "application/json" } )); + getAndAssert200("http://localhost:2043/bank/37050198",ACCEPT_HEADER)); assertContains("\"bic\":\"GENODE61KIR\"", - getAndAssert200("http://localhost:2043/bank/66762332", - new String[] { "Accept", "application/json" } )); - } finally { - sl.killScript(); + getAndAssert200("http://localhost:2043/bank/66762332", ACCEPT_HEADER )); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPTest.java index 187918e44d..db122b67a8 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/REST2SOAPTest.java @@ -14,6 +14,7 @@ package com.predic8.membrane.examples.tests; +import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; import java.io.File; @@ -22,22 +23,20 @@ import org.junit.jupiter.api.Test; import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class REST2SOAPTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "rest2soap"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("rest2soap"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - AssertUtils.assertContains("COLSDE33XXX", getAndAssert200("http://localhost:2000/bank/37050198")); - AssertUtils.assertContains("GENODE61KIR", getAndAssert200("http://localhost:2000/bank/66762332")); - } finally { - sl.killScript(); + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + assertContains("COLSDE33XXX", getAndAssert200("http://localhost:2000/bank/37050198")); + assertContains("GENODE61KIR", getAndAssert200("http://localhost:2000/bank/66762332")); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/RateLimiterTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/RateLimiterTest.java index 9cf885f6a7..5b3ba8beb1 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/RateLimiterTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/RateLimiterTest.java @@ -14,28 +14,25 @@ package com.predic8.membrane.examples.tests; -import java.io.IOException; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.test.AssertUtils; +import static com.predic8.membrane.test.AssertUtils.*; public class RateLimiterTest extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "rateLimiter"; + } + @Test - public void test() throws IOException, InterruptedException { - Process2 sl = new Process2.Builder().in(getExampleDir("rateLimiter")).script("service-proxy").waitForMembrane() - .start(); - try { - AssertUtils.getAndAssert200("http://localhost:2000/"); - AssertUtils.getAndAssert200("http://localhost:2000/"); - AssertUtils.getAndAssert200("http://localhost:2000/"); - AssertUtils.getAndAssert(429, "http://localhost:2000/"); - - } finally { - sl.killScript(); + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + getAndAssert200(URL_2000); + getAndAssert200(URL_2000); + getAndAssert200(URL_2000); + getAndAssert(429, URL_2000); } } - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/RewriterTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/RewriterTest.java index 87971143b3..6264b801bb 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/RewriterTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/RewriterTest.java @@ -14,30 +14,22 @@ package com.predic8.membrane.examples.tests; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import java.io.File; -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import static com.predic8.membrane.test.AssertUtils.*; public class RewriterTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "rewriter"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("rewriter"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - String result = getAndAssert200("http://localhost:2000/bank/services/BLZService?wsdl"); - AssertUtils.assertContains("wsdl:documentation", result); - } finally { - sl.killScript(); + public void test() throws Exception { + try(Process2 ignore = startServiceProxyScript()) { + assertContains("wsdl:documentation", getAndAssert200(BLZ_SERVICE_WSDL)); } } - - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/SSLServer.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/SSLServer.java deleted file mode 100644 index 76c7db0e7a..0000000000 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/SSLServer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright 2012 predic8 GmbH, www.predic8.com - - 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.predic8.membrane.examples.tests; - -import static com.predic8.membrane.test.AssertUtils.assertContains; -import static com.predic8.membrane.test.AssertUtils.getAndAssert200; - -import java.io.File; -import java.io.IOException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; - -public class SSLServer extends DistributionExtractingTestcase { - - @Test - public void test() throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException { - File baseDir = getExampleDir("ssl-server"); - - AssertUtils.replaceInFile(new File(baseDir, "proxies.xml"), "443", "3023"); - - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - AssertUtils.trustAnyHTTPSServer(3023); - - assertContains("wsdl:documentation", getAndAssert200("https://localhost:3023/axis2/services/BLZService?wsdl")); - } finally { - sl.killScript(); - } - } - - -} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/SpELTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/SpELTest.java index 283a32b647..aaa473771c 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/SpELTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/SpELTest.java @@ -14,25 +14,22 @@ package com.predic8.membrane.examples.tests; -import java.io.IOException; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.test.AssertUtils; +import static com.predic8.membrane.test.AssertUtils.*; public class SpELTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "spel"; + } + @Test - public void test() throws IOException, InterruptedException { - Process2 sl = new Process2.Builder().in(getExampleDir("spel")) - .script("service-proxy").waitForMembrane().start(); - try { - AssertUtils.getAndAssert200("http://localhost:2000/"); - } finally { - sl.killScript(); + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + getAndAssert200("http://localhost:2000/"); } } - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/StaxExampleInterceptorTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/StaxExampleInterceptorTest.java index 755010f9ed..ad1c1fb70b 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/StaxExampleInterceptorTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/StaxExampleInterceptorTest.java @@ -14,47 +14,33 @@ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.BufferLogger; import org.junit.jupiter.api.Test; -import org.xml.sax.SAXException; - -import javax.xml.parsers.ParserConfigurationException; -import java.io.File; -import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Paths; import static com.predic8.membrane.test.AssertUtils.postAndAssert; import static org.junit.jupiter.api.Assertions.*; public class StaxExampleInterceptorTest extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "stax-interceptor"; + } + @Test - public void test() throws IOException, InterruptedException, ParserConfigurationException, SAXException { - File baseDir = getExampleDir("stax-interceptor"); - - BufferLogger b = new BufferLogger(); - Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(b).start(); - try { - int exitCode = mvn.waitFor(60000); - if (exitCode != 0) - throw new RuntimeException("Maven exited with code " + exitCode + ": " + b.toString()); - } finally { - mvn.killScript(); + public void test() throws Exception { + + BufferLogger logger = new BufferLogger(); + try(Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn package").withWatcher(logger).start()) { + if (mvn.waitFor(60000) != 0) + throw new RuntimeException("Maven exited with code " + mvn.waitFor(60000) + ": " + logger); } BufferLogger proxyWatcher = new BufferLogger(); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().withWatcher(proxyWatcher).start(); - try { - String body = new String(Files.readAllBytes(Paths.get(baseDir + FileSystems.getDefault().getSeparator() + "example.xml"))); - String[] headers = {"Content-Type", "application/xml"}; - postAndAssert(200,"http://localhost:2000/", headers, body); - assertTrue(proxyWatcher.toString().contains("42")); - } finally { - sl.killScript(); + try(Process2 ignored = startServiceProxyScript(proxyWatcher)) { + postAndAssert(200,URL_2000, CONTENT_TYPE_APP_XML_HEADER, readFileFromBaseDir("example.xml")); + assertTrue(proxyWatcher.contains("42")); } } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/ThrottleTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/ThrottleTest.java index 95c93a8d9a..9853c2ec06 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/ThrottleTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/ThrottleTest.java @@ -22,25 +22,23 @@ import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class ThrottleTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "throttle"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("throttle"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - getAndAssert200("http://localhost:2000/"); + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + getAndAssert200(URL_2000); long start = System.currentTimeMillis(); - getAndAssert200("http://localhost:2000/"); + getAndAssert200(URL_2000); long elapsedMillis = System.currentTimeMillis() - start; assertTrue(elapsedMillis >= 1000); - } finally { - sl.killScript(); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/XSLTTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/XSLTTest.java index d6712b30b0..f9874dc289 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/XSLTTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/XSLTTest.java @@ -14,6 +14,9 @@ package com.predic8.membrane.examples.tests; +import static com.predic8.membrane.examples.tests.BasicAuthTest.*; +import static com.predic8.membrane.examples.tests.BasicAuthTest.CUSTOMER_HOST_REMOTE; +import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; import java.io.File; @@ -22,25 +25,20 @@ import org.junit.jupiter.api.Test; import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.util.Process2; public class XSLTTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "xslt"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("xslt"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - String result = getAndAssert200(BasicAuthTest.CUSTOMER_HOST_REMOTE + BasicAuthTest.CUSTOMER_PATH); - AssertUtils.assertContains("FIRSTNAME", result); - - result = getAndAssert200(BasicAuthTest.CUSTOMER_HOST_LOCAL + BasicAuthTest.CUSTOMER_PATH); - AssertUtils.assertContains("first", result); - } finally { - sl.killScript(); + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + assertContains("FIRSTNAME", getAndAssert200(CUSTOMER_HOST_REMOTE + CUSTOMER_PATH)); + assertContains("first", getAndAssert200(CUSTOMER_HOST_LOCAL + CUSTOMER_PATH)); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/Xml2JsonTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/Xml2JsonTest.java index 8ea7c4aebd..8cd9892c76 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/Xml2JsonTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/Xml2JsonTest.java @@ -13,41 +13,28 @@ limitations under the License. */ package com.predic8.membrane.examples.tests; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; -import com.predic8.membrane.examples.util.BufferLogger; -import org.junit.jupiter.api.Test; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import java.io.File; -import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static com.predic8.membrane.test.AssertUtils.postAndAssert; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.lang.Thread.*; +import static org.junit.jupiter.api.Assertions.*; public class Xml2JsonTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "xml-2-json"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("xml-2-json"); - BufferLogger b = new BufferLogger(); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().withWatcher(b).start(); - try { - String body = new String(Files.readAllBytes(Paths.get(baseDir + FileSystems.getDefault().getSeparator() - + "jobs.xml"))); - String[] headers = {"Content-Type", "application/xml"}; - Thread.sleep(2000); - String response = postAndAssert(200,"http://localhost:2000/", headers, body); - Thread.sleep(1000); - - assertTrue(b.toString().contains("{\"jobs\":{\"job\":")); - - } finally { - sl.killScript(); + public void test() throws Exception { + BufferLogger logger = new BufferLogger(); + try(Process2 ignored = startServiceProxyScript(logger)) { + sleep(2000); + postAndAssert(200,URL_2000, CONTENT_TYPE_APP_XML_HEADER, readFileFromBaseDir("jobs.xml")); + sleep(100); + assertTrue(logger.contains("{\"jobs\":{\"job\":")); } } - - } \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2RaceCondition.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2RaceCondition.java index 50bed0333b..92081acaa7 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2RaceCondition.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2RaceCondition.java @@ -55,7 +55,7 @@ public void setUp() throws MalformedURLException { } @AfterEach - public void tearDown() throws MalformedURLException { + public void tearDown() { server.stop(); client.stopAll(); } @@ -65,7 +65,6 @@ public void testSessionIdStateRaceCondition() throws Exception { HttpClient hc = HttpClientBuilder.create().build(); login(hc); - System.out.println("Logged in"); ExecutorService executor = Executors.newFixedThreadPool(2); for (int i = 0; i < 10; i++) { diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2Test.java index 788d6ece5c..932fe572a5 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2Test.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/integration/OAuth2Test.java @@ -15,6 +15,7 @@ import com.predic8.membrane.core.HttpRouter; import com.predic8.membrane.core.Router; +import com.predic8.membrane.core.http.*; import com.predic8.membrane.test.AssertUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; @@ -23,15 +24,18 @@ import java.util.Arrays; import java.util.Collection; +import static com.predic8.membrane.core.http.MimeType.APPLICATION_X_WWW_FORM_URLENCODED; +import static com.predic8.membrane.core.http.MimeType.APPLICATION_X_WWW_FORM_URLENCODED_CONTENT_TYPE; +import static com.predic8.membrane.test.AssertUtils.getAndAssert; +import static com.predic8.membrane.test.AssertUtils.getAndAssert200; +import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class OAuth2Test { - public static Collection data() throws Exception { - return Arrays.asList(new Object[][] { - testParams(), - testParamsForSubPath() - }); + public static Collection data() { + return asList(testParams(), testParamsForSubPath()); } private static Object[] testParams() { @@ -63,12 +67,16 @@ public void testGoodLoginRequest( String clientBasePath) throws Exception { setUp(proxies); - AssertUtils.getAndAssert200("http://localhost:2001" + clientBasePath); + getAndAssert200("http://localhost:2001" + clientBasePath); + AssertUtils.postAndAssert(200, "http://localhost:2000" + serverBasePath + "/login/", getWWWFormEncodedContentTypeHeader(), "target=&username=john&password=password"); + assertEquals("Hello john.", getAndAssert200("http://localhost:2000" + serverBasePath + "/")); + } + + private String[] getWWWFormEncodedContentTypeHeader() { String[] headers = new String[2]; headers[0] = "Content-Type"; - headers[1] = "application/x-www-form-urlencoded"; - AssertUtils.postAndAssert(200, "http://localhost:2000" + serverBasePath + "/login/", headers, "target=&username=john&password=password"); - assertEquals("Hello john.", AssertUtils.getAndAssert200("http://localhost:2000" + serverBasePath + "/")); + headers[1] = APPLICATION_X_WWW_FORM_URLENCODED; + return headers; } @ParameterizedTest(name = "{0}") @@ -79,12 +87,9 @@ public void testBadUserCredentials( String clientBasePath) throws Exception { setUp(proxies); - AssertUtils.getAndAssert200("http://localhost:2001" + clientBasePath); - String[] headers = new String[2]; - headers[0] = "Content-Type"; - headers[1] = "application/x-www-form-urlencoded"; - assertEquals(true, AssertUtils.postAndAssert(200, "http://localhost:2000" + serverBasePath + "/login/", headers, "target=&username=john&password=wrongPassword").contains("Invalid password.")); - AssertUtils.getAndAssert(400, "http://localhost:2000" + serverBasePath + "/"); + getAndAssert200("http://localhost:2001" + clientBasePath); + assertTrue(AssertUtils.postAndAssert(200, "http://localhost:2000" + serverBasePath + "/login/", getWWWFormEncodedContentTypeHeader(), "target=&username=john&password=wrongPassword").contains("Invalid password.")); + getAndAssert(400, "http://localhost:2000" + serverBasePath + "/"); } @ParameterizedTest(name = "{0}") @@ -95,9 +100,9 @@ public void testMissingHeader( String clientBasePath) throws Exception { setUp(proxies); - AssertUtils.getAndAssert200("http://localhost:2001" + clientBasePath); - assertEquals(true, AssertUtils.postAndAssert(200, "http://localhost:2000" + serverBasePath + "/login/", "target=&username=john&password=password").contains("Invalid password.")); - AssertUtils.getAndAssert(400, "http://localhost:2000" + serverBasePath + "/"); + getAndAssert200("http://localhost:2001" + clientBasePath); + assertTrue(AssertUtils.postAndAssert(200, "http://localhost:2000" + serverBasePath + "/login/", "target=&username=john&password=password").contains("Invalid password.")); + getAndAssert(400, "http://localhost:2000" + serverBasePath + "/"); } @ParameterizedTest(name = "{0}") @@ -108,7 +113,7 @@ public void testBypassingAuthorizationService( String clientBasePath) throws Exception { setUp(proxies); - AssertUtils.getAndAssert(400, "http://localhost:2000" + serverBasePath + "/oauth2/auth"); + getAndAssert(400, "http://localhost:2000" + serverBasePath + "/oauth2/auth"); } @ParameterizedTest(name = "{0}") @@ -120,11 +125,11 @@ public void testLogout( setUp(proxies); testGoodLoginRequest(proxies, serverBasePath, clientBasePath); - AssertUtils.getAndAssert200("http://localhost:2001" + clientBasePath + "/login/logout"); + getAndAssert200("http://localhost:2001" + clientBasePath + "/login/logout"); } @AfterEach - public void tearDown() throws Exception { + public void tearDown() { router.stopAll(); router = null; } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/BalancerClientScriptUtil.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/BalancerClientScriptUtil.java new file mode 100644 index 0000000000..ba2e9f0be7 --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/BalancerClientScriptUtil.java @@ -0,0 +1,55 @@ +/* Copyright 2012-2023 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests.loadbalancing; + +import com.predic8.membrane.examples.util.*; + +import java.io.*; + +import static com.predic8.membrane.examples.util.Process2.isWindows; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class BalancerClientScriptUtil { + + public static void addNodeViaScript(File base, String nodeHost, int nodePort) throws IOException, InterruptedException { + controlNodeViaScript(base, "up", nodeHost, nodePort); + } + + public static void removeNodeViaScript(File base, String nodeHost, int nodePort) throws IOException, InterruptedException { + controlNodeViaScript(base, "down", nodeHost, nodePort); + } + + public static void controlNodeViaScript(File base, String command, String nodeHost, int nodePort) throws IOException, InterruptedException { + controlNodeViaScript(0, base, command, nodeHost, nodePort); + } + + public static void controlNodeViaScript(int expectedReturnCode, File base, String command, String nodeHost, int nodePort) throws IOException, InterruptedException { + Process2 lbclient = new Process2.Builder().in(base) +// .withWatcher(new ConsoleLogger()) + .executable(getClientStartCommand(command, nodeHost, nodePort)).start(); + try { + assertEquals(expectedReturnCode, lbclient.waitFor(30000)); + } finally { + lbclient.killScript(); + } + } + + public static String getClientStartCommand(String command, String nodeHost, int nodePort) { + if (isWindows()) + return "cmd /c lbclient.bat " + command + " " + nodeHost + " " + nodePort; + + return "bash lbclient.sh " + command + " " + nodeHost + " " + nodePort; + } +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerUtil.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/LoadBalancerUtil.java similarity index 74% rename from distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerUtil.java rename to distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/LoadBalancerUtil.java index bd78dc3922..622cfb74c4 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/LoadBalancerUtil.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/LoadBalancerUtil.java @@ -12,7 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.predic8.membrane.examples.tests; +package com.predic8.membrane.examples.tests.loadbalancing; import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.assertStatusCode; @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; -import java.util.ArrayList; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -32,18 +32,17 @@ import org.apache.http.message.BasicNameValuePair; public class LoadBalancerUtil { - private static Pattern nodePattern = Pattern.compile("Mock Node (\\d+)"); + private static final Pattern nodePattern = Pattern.compile("Node (\\d+)"); public static int getRespondingNode(String url) throws ParseException, IOException { Matcher m = nodePattern.matcher(getAndAssert200(url)); assertTrue(m.find()); return Integer.parseInt(m.group(1)); - } - public static void addLBNodeViaHTML(String adminBaseURL, String nodeHost, int nodePort) throws ClientProtocolException, IOException { + public static void addLBNodeViaHTML(String adminBaseURL, String nodeHost, int nodePort) throws IOException { HttpPost post = new HttpPost(adminBaseURL + "node/save"); - ArrayList params = new ArrayList(); + ArrayList params = new ArrayList<>(); params.add(new BasicNameValuePair("balancer", "Default")); params.add(new BasicNameValuePair("cluster", "Default")); params.add(new BasicNameValuePair("host", nodeHost)); @@ -67,5 +66,16 @@ public static void assertNodeStatus(String adminPageHTML, String nodeHost, int n throw new AssertionError("Node " + nodeHost + ":" + nodePort + " not found in " + adminPageHTML); } + public static void checkWhatNodesAreResponding(int[] nodes) throws IOException { + List nodeNumbers = new ArrayList<>(); + nodeNumbers.add(getRespondingNode("http://localhost:3023/service")); + nodeNumbers.add(getRespondingNode("http://localhost:3023/service")); + nodeNumbers.add(getRespondingNode("http://localhost:3023/service")); + nodeNumbers.add(getRespondingNode("http://localhost:3023/service")); + nodeNumbers.add(getRespondingNode("http://localhost:3023/service")); + for (int node: nodes) { + assertTrue(nodeNumbers.contains(node)); + } + } } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_1_static_Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_1_static_Test.java new file mode 100644 index 0000000000..593997263f --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_1_static_Test.java @@ -0,0 +1,52 @@ +/* Copyright 2012 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests.loadbalancing; + +import static com.predic8.membrane.examples.tests.loadbalancing.LoadBalancerUtil.*; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.lang.Thread.sleep; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.File; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; +import com.predic8.membrane.test.AssertUtils; + +public class Loadbalancing_1_static_Test extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "loadbalancing/1-static"; + } + + @Test + public void test() throws Exception { + + replaceInFile2("proxies.xml", "8080", "3023"); + + try(Process2 ignored = startServiceProxyScript()) { + + assertEquals(1, getRespondingNode("http://localhost:4000/")); + assertEquals(2, getRespondingNode("http://localhost:4001/")); + assertEquals(3, getRespondingNode("http://localhost:4002/")); + + checkWhatNodesAreResponding(new int[]{1,2,3}); + } + } +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_2_dynamic_Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_2_dynamic_Test.java new file mode 100644 index 0000000000..a53e8b6655 --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_2_dynamic_Test.java @@ -0,0 +1,109 @@ +/* Copyright 2012 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests.loadbalancing; + +import com.predic8.membrane.examples.tests.*; +import com.predic8.membrane.examples.util.*; +import com.predic8.membrane.test.*; +import org.junit.jupiter.api.*; + +import java.io.*; + +import static com.predic8.membrane.examples.tests.loadbalancing.LoadBalancerUtil.*; +import static com.predic8.membrane.test.AssertUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +public class Loadbalancing_2_dynamic_Test extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "loadbalancing/2-dynamic"; + } + + @Test + public void addingNodesDynamicallyUsingTheAdminConsole() throws Exception { + replaceInFile2("proxies.xml", "8080", "3023"); + + try(Process2 sl = startServiceProxyScript()) { + + // Make sure backends are running + assertEquals(1, getRespondingNode("http://localhost:4000/")); + assertEquals(2, getRespondingNode("http://localhost:4001/")); + assertEquals(3, getRespondingNode("http://localhost:4002/")); + + // Add dynamically a node on port 4000 + addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4000); + + assertNodeStatus( + getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default"), + "localhost", 4000, "UP"); + + // Because just one node is running we should get always the same node + checkWhatNodesAreResponding(new int[]{1}); + + // Add dynamically a node on port 4001 + addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4001); + + assertNodeStatus( + getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default"), + "localhost", 4001, "UP"); + + checkWhatNodesAreResponding(new int[]{1,2}); + } + } + + @Test + public void addingNodesDynamicallyUsingTheCluserAPI() throws Exception { + replaceInFile2("proxies.xml", "8080", "3023"); + + try(Process2 ignored = startServiceProxyScript()) { + + // Make sure backends are running + assertEquals(1, getRespondingNode("http://localhost:4000/")); + assertEquals(2, getRespondingNode("http://localhost:4001/")); + assertEquals(3, getRespondingNode("http://localhost:4002/")); + + // Start Node 1 + getAndAssert(204, "http://localhost:9010/clustermanager/up?host=localhost&port=4000"); + + assertNodeStatus( + getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default"), + "localhost", 4000, "UP"); + + // Because just one node is running we should get always the same node + assertEquals(1, getRespondingNode("http://localhost:3023/service")); + + // Start Node 2 + getAndAssert(204, "http://localhost:9010/clustermanager/up?host=localhost&port=4001"); + checkWhatNodesAreResponding(new int[]{1,2}); + + // Start Node 3 + getAndAssert(204, "http://localhost:9010/clustermanager/up?host=localhost&port=4002"); + checkWhatNodesAreResponding(new int[]{1,2,3}); + + // Stop Node 3 + getAndAssert(204, "http://localhost:9010/clustermanager/down?host=localhost&port=4002"); + checkWhatNodesAreResponding(new int[]{1,2}); + + // Stop Node 2 + getAndAssert(204, "http://localhost:9010/clustermanager/down?host=localhost&port=4001"); + checkWhatNodesAreResponding(new int[]{1}); + + // Stop Node 1 + getAndAssert(204, "http://localhost:9010/clustermanager/down?host=localhost&port=4000"); + getAndAssert(500,"http://localhost:3023/service"); + } + } +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_3_client_Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_3_client_Test.java new file mode 100644 index 0000000000..6db2d47d28 --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_3_client_Test.java @@ -0,0 +1,90 @@ +/* Copyright 2012 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests.loadbalancing; + +import com.predic8.membrane.examples.tests.*; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; + +import java.io.*; + +import static com.predic8.membrane.examples.tests.loadbalancing.BalancerClientScriptUtil.*; +import static com.predic8.membrane.examples.tests.loadbalancing.LoadBalancerUtil.*; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +public class Loadbalancing_3_client_Test extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "loadbalancing/3-client"; + } + + @Test + public void test() throws Exception { + + replaceInFile2("proxies.xml", "8080", "3023"); + replaceInFile2("lb-client-secured.proxies.xml", "8080", "3023"); + + try(Process2 ignored = startServiceProxyScript()) { + assertEquals(1, getRespondingNode("http://localhost:4000/")); + assertEquals(2, getRespondingNode("http://localhost:4001/")); + assertEquals(3, getRespondingNode("http://localhost:4002/")); + + addNodeViaScript(baseDir, "localhost", 4000); + + sleep(1000); + + assertNodeStatus( + getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default"), + "localhost", 4000, "UP"); + + addNodeViaScript(baseDir, "localhost", 4001); + addNodeViaScript(baseDir, "localhost", 4002); + + sleep(100); + + assertEquals(1, getRespondingNode("http://localhost:3023/service")); + assertEquals(2, getRespondingNode("http://localhost:3023/service")); + assertEquals(3, getRespondingNode("http://localhost:3023/service")); + + removeNodeViaScript(baseDir, "localhost", 4000); + + sleep(100); + + assertEquals(2, getRespondingNode("http://localhost:3023/service")); + assertEquals(3, getRespondingNode("http://localhost:3023/service")); + } + + try(Process2 ignored = startServiceProxyScript(null,"service-proxy-secured")) { + controlNodeViaScript(1, baseDir, "up", "localhost", 4000); // 1 indicates failure + + File propFile = new File(baseDir, "client.properties"); + writeStringToFile(propFile, readFileToString(propFile, UTF_8).replace("#", ""), UTF_8); + + sleep(100); + + addNodeViaScript(baseDir, "localhost", 4000); + + sleep(100); + + setupHTTPAuthentication("localhost", 9000, "admin", "admin"); + assertContains("localhost:4000", getAndAssert200("http://localhost:9000/admin/clusters/show?cluster=Default")); + } + } +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_4_xml_session_Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_4_xml_session_Test.java new file mode 100644 index 0000000000..b79af76eda --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_4_xml_session_Test.java @@ -0,0 +1,74 @@ +/* Copyright 2012 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests.loadbalancing; + +import com.predic8.membrane.examples.tests.*; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; + +import java.io.*; + +import static com.predic8.membrane.examples.tests.loadbalancing.LoadBalancerUtil.*; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.lang.Thread.sleep; + +public class Loadbalancing_4_xml_session_Test extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "loadbalancing/4-xml-session"; + } + + /** + * The test as described in README.txt, but "wsimport" (previously called by ant) + * was removed and is run directly from this test before everything else. Thereby + * we can use a Maven dependency on wsimport and do not have to download it ourselves. + */ + @Test + public void test() throws Exception { + replaceInFile2("proxies.xml", "8080", "3023"); + replaceInFile2("src/main/java/com/predic8/chat/Client.java", "8080", "3023"); + replaceInFile2("data/ChatService.wsdl", "8080", "3023"); + + try(Process2 sl = startServiceProxyScript()) { + // call "ant compile" now so that both antNodeX processes do call it at the same time + BufferLogger loggerCompile = new BufferLogger(); + try(Process2 antCompile = new Process2.Builder().in(baseDir).withWatcher(loggerCompile).executable("mvn package").start()) { + int result = antCompile.waitFor(40000); + if (result != 0) + throw new AssertionError("'mvn package' returned non-zero " + result + ":\r\n" + loggerCompile); + } + + BufferLogger loggerNode1 = new BufferLogger(); + BufferLogger loggerNode2 = new BufferLogger(); + try(Process2 ignored1 = new Process2.Builder().in(baseDir).withWatcher(loggerNode1).executable("mvn exec:java@node1").start()) { + try(Process2 ignored2 = new Process2.Builder().in(baseDir).withWatcher(loggerNode2).executable("mvn exec:java@node2").start()) { + + addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4000); + addLBNodeViaHTML("http://localhost:9000/admin/", "localhost", 4001); + + sleep(300); // wait for nodes to come up + + try(Process2 antClient = new Process2.Builder().in(baseDir).executable("mvn exec:java@client").start()) { + antClient.waitFor(30000); + } + } + } + + assertContains("Hallo World", loggerNode1.toString()); + assertContainsNot("Hallo World", loggerNode2.toString()); + } + } +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_5_multiple_Test.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_5_multiple_Test.java new file mode 100644 index 0000000000..70994e002a --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/loadbalancing/Loadbalancing_5_multiple_Test.java @@ -0,0 +1,66 @@ +/* Copyright 2012 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests.loadbalancing; + +import static com.predic8.membrane.examples.tests.loadbalancing.LoadBalancerUtil.*; +import static com.predic8.membrane.test.AssertUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.File; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; + +public class Loadbalancing_5_multiple_Test extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "loadbalancing/5-multiple"; + } + + @Test + public void test() throws Exception { + + replaceInFile2("proxies.xml","8080", "3023"); + replaceInFile2("proxies.xml","8081", "3024"); + + try(Process2 ignored = startServiceProxyScript()) { + checkWhatNodesAreResponding(new int[]{1,2}); + + assertEquals(3, getRespondingNode("http://localhost:3024/service")); + assertEquals(4, getRespondingNode("http://localhost:3024/service")); + assertEquals(3, getRespondingNode("http://localhost:3024/service")); + assertEquals(4, getRespondingNode("http://localhost:3024/service")); + + String status = getAndAssert200("http://localhost:9000/admin/clusters/show?balancer=balancer1&cluster=Default"); + assertNodeStatus(status, "localhost", 4000, "UP"); + assertNodeStatus(status, "localhost", 4001, "UP"); + + getAndAssert(204, "http://localhost:9010/clustermanager/down?balancer=balancer1&host=localhost&port=4001"); + Thread.sleep(1000); + + status = getAndAssert200("http://localhost:9000/admin/clusters/show?balancer=balancer1&cluster=Default"); + assertNodeStatus(status, "localhost", 4000, "UP"); + assertNodeStatus(status, "localhost", 4001, "DOWN"); + + assertEquals(1, getRespondingNode("http://localhost:3023/service")); + assertEquals(1, getRespondingNode("http://localhost:3023/service")); + } + } + +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsTest.java new file mode 100644 index 0000000000..2939326568 --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsTest.java @@ -0,0 +1,46 @@ +/* Copyright 2012 predic8 GmbH, www.predic8.com + + 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.predic8.membrane.examples.tests.ssl; + +import java.io.File; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import org.junit.jupiter.api.Test; + +import com.predic8.membrane.test.AssertUtils; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; + +import static com.predic8.membrane.test.AssertUtils.*; + +public class SSLServerApiWithTlsTest extends DistributionExtractingTestcase { + + @Override + protected String getExampleDirName() { + return "ssl/api-with-tls"; + } + + @Test + public void test() throws Exception { + replaceInFile2("proxies.xml", "443", "3023"); + + try(Process2 ignored = startServiceProxyScript()) { + trustAnyHTTPSServer(3023); + assertContains("success", getAndAssert200("https://localhost:3023/axis2/services/BLZService?wsdl")); + } + } +} diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/SSLClient.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/ToBackendTest.java similarity index 54% rename from distribution/src/test/java/com/predic8/membrane/examples/tests/SSLClient.java rename to distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/ToBackendTest.java index 6cd601acef..b4f2f46282 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/SSLClient.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/ToBackendTest.java @@ -12,8 +12,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.predic8.membrane.examples.tests; +package com.predic8.membrane.examples.tests.ssl; +import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.getAndAssert200; import java.io.File; @@ -21,27 +22,28 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import com.predic8.membrane.test.AssertUtils; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; -public class SSLClient extends DistributionExtractingTestcase { +public class ToBackendTest extends DistributionExtractingTestcase { - @Test - public void test() throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException { - File baseDir = getExampleDir("ssl-client"); + @Override + protected String getExampleDirName() { + return "ssl/to-backend"; + } - AssertUtils.replaceInFile(new File(baseDir, "proxies.xml"), "8080", "3023"); + @BeforeEach + void setup() throws IOException { + replaceInFile2("proxies.xml", "2000", "3023"); + } - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - AssertUtils.assertContains("Google", getAndAssert200("http://localhost:3023/")); - } finally { - sl.killScript(); + @Test + public void test() throws Exception { + try(Process2 ingore = startServiceProxyScript()) { + assertContains("shop", getAndAssert200("http://localhost:3023/")); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/FormValidationTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/FormValidationTest.java index 01eb033788..98bd6c619e 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/FormValidationTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/FormValidationTest.java @@ -15,28 +15,28 @@ package com.predic8.membrane.examples.tests.validation; import static com.predic8.membrane.test.AssertUtils.getAndAssert; +import static java.io.File.separator; import java.io.File; import java.io.IOException; import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; public class FormValidationTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "validation" + separator + "form"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("validation" + File.separator + "form"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { getAndAssert(400, "http://localhost:2000/?name=Abcde0"); getAndAssert(200, "http://localhost:2000/?name=Abcde"); - } finally { - sl.killScript(); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/JSONSchemaValidationTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/JSONSchemaValidationTest.java index 3fa330792e..8da58de19c 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/JSONSchemaValidationTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/JSONSchemaValidationTest.java @@ -14,34 +14,29 @@ package com.predic8.membrane.examples.tests.validation; -import static com.predic8.membrane.test.AssertUtils.postAndAssert; -import static org.apache.commons.io.FileUtils.readFileToString; +import com.predic8.membrane.examples.tests.*; +import com.predic8.membrane.examples.util.*; +import org.junit.jupiter.api.*; -import java.io.File; -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import static com.predic8.membrane.test.AssertUtils.*; +import static java.io.File.*; +import static java.lang.Thread.sleep; public class JSONSchemaValidationTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "validation" + separator + "json-schema"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("validation" + File.separator + "json-schema"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { for (int port : new int[] { 2000, 2001 }) { - Thread.sleep(1000); - postAndAssert(200, "http://localhost:" + port + "/", readFileToString(new File(baseDir, "good" + port + ".json"))); - postAndAssert(400, "http://localhost:" + port + "/", readFileToString(new File(baseDir, "bad" + port + ".json"))); + sleep(1000); + postAndAssert(200, "http://localhost:" + port + "/",readFileFromBaseDir("good" + port + ".json")); + postAndAssert(400, "http://localhost:" + port + "/",readFileFromBaseDir("bad" + port + ".json")); } - - } finally { - sl.killScript(); } } - - -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java index 005bdb81b0..e544a1f30a 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/SOAPProxyValidationTest.java @@ -14,32 +14,35 @@ package com.predic8.membrane.examples.tests.validation; +import static com.predic8.membrane.core.http.MimeType.APPLICATION_SOAP; import static com.predic8.membrane.test.AssertUtils.postAndAssert; +import static java.io.File.separator; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.commons.io.FileUtils.readFileToString; import java.io.File; import java.io.IOException; +import java.nio.charset.*; +import com.predic8.membrane.core.http.*; import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; public class SOAPProxyValidationTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "validation" + separator + "soap-Proxy"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("validation" + File.separator + "soap-Proxy"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { + public void test() throws Exception { + try(Process2 igored = startServiceProxyScript()) { String url = "http://localhost:2000/axis2/services/BLZService/getBankResponse"; - String[] headers = new String[] { "Content-Type", "application/soap+xml" }; - postAndAssert(200, url, headers, readFileToString(new File(baseDir, "blz-soap.xml"))); - postAndAssert(400, url, headers, readFileToString(new File(baseDir, "invalid-blz-soap.xml"))); - } finally { - sl.killScript(); + postAndAssert(200, url, CONTENT_TYPE_SOAP_HEADER, readFile("blz-soap.xml")); + postAndAssert(400, url, CONTENT_TYPE_SOAP_HEADER, readFile("invalid-blz-soap.xml")); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/XMLValidationTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/XMLValidationTest.java index d826867506..d2b92693d0 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/XMLValidationTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/validation/XMLValidationTest.java @@ -15,31 +15,34 @@ package com.predic8.membrane.examples.tests.validation; import static com.predic8.membrane.test.AssertUtils.postAndAssert; +import static java.io.File.separator; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.commons.io.FileUtils.readFileToString; import java.io.File; import java.io.IOException; +import java.net.*; +import java.nio.charset.*; import org.junit.jupiter.api.Test; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; public class XMLValidationTest extends DistributionExtractingTestcase { + @Override + protected String getExampleDirName() { + return "validation" + separator + "xml"; + } + @Test - public void test() throws IOException, InterruptedException { - File baseDir = getExampleDir("validation" + File.separator + "xml"); - Process2 sl = new Process2.Builder().in(baseDir).script("service-proxy").waitForMembrane().start(); - try { - String url = "http://localhost:2000/"; - Thread.sleep(2000); - postAndAssert(200, url, readFileToString(new File(baseDir, "year.xml"))); - postAndAssert(400, url, readFileToString(new File(baseDir, "invalid-year.xml"))); - } finally { - sl.killScript(); + public void test() throws Exception { + try(Process2 ignored = startServiceProxyScript()) { + sleep(1000); + postAndAssert(200, URL_2000, readFileFromBaseDir("year.xml")); + postAndAssert(400, URL_2000, readFileFromBaseDir("invalid-year.xml")); } } - - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/RoutingTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/RoutingTest.java index 2ef954a985..47ee9321b5 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/RoutingTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/RoutingTest.java @@ -13,69 +13,69 @@ limitations under the License. */ package com.predic8.membrane.examples.tests.versioning; +import static com.predic8.membrane.core.http.MimeType.TEXT_XML; import static com.predic8.membrane.test.AssertUtils.assertContains; import static com.predic8.membrane.test.AssertUtils.postAndAssert; import static com.predic8.membrane.test.AssertUtils.replaceInFile; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.UTF_8; import java.io.File; import java.io.IOException; +import java.nio.charset.*; +import com.predic8.membrane.core.http.*; import com.predic8.membrane.examples.util.BufferLogger; import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; public class RoutingTest extends DistributionExtractingTestcase { - @Test - public void test() throws IOException, InterruptedException { - File base = getExampleDir("versioning/routing"); - String header[] = new String[] { "Content-Type", "text/xml" }; - String request_v11 = FileUtils.readFileToString(new File(base, "request_v11.xml")); - String request_v20 = FileUtils.readFileToString(new File(base, "request_v20.xml")); + String request_v11; + String request_v20; + + @BeforeEach + void setup() throws IOException { + request_v11 = readFileFromBaseDir("request_v11.xml"); + request_v20 = readFileFromBaseDir("request_v20.xml"); + } + + @Override + protected String getExampleDirName() { + return "versioning/routing"; + } - replaceInFile(new File(base, "proxies.xml"), "8080", "3024"); - replaceInFile(new File(base, "proxies.xml"), "2000", "3025"); - replaceInFile(new File(base, "src/main/java/com/predic8/contactservice/Launcher.java"), "8080", "3024"); + @Test + public void test() throws Exception { + replaceInFile2("proxies.xml", "8080", "3024"); + replaceInFile2("proxies.xml", "2000", "3025"); + replaceInFile2("src/main/java/com/predic8/contactservice/Launcher.java", "8080", "3024"); BufferLogger b = new BufferLogger(); - Process2 mvn = new Process2.Builder().in(base).executable("mvn clean compile assembly:single").withWatcher(b).start(); - try { - int exitCode = mvn.waitFor(60000); - if (exitCode != 0) - throw new RuntimeException("Maven exited with code " + exitCode + ": " + b.toString()); - } finally { - mvn.killScript(); + try(Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn clean compile assembly:single").withWatcher(b).start()) { + if (mvn.waitFor(60000) != 0) + throw new RuntimeException("Maven exited with code " + mvn.waitFor(60000) + ": " + b); } - - Process2 sl = new Process2.Builder().in(base).script("service-proxy").waitForMembrane().start(); - try { - Process2 jarNode1 = new Process2.Builder().in(base).waitAfterStartFor("ContactService v11 and v20 up.") - .executable("java -jar ./target/routing-maven-1.0-SNAPSHOT.jar").start(); - try { - Thread.sleep(2000); // wait for Endpoints to start + try(Process2 ignored1 = startServiceProxyScript()) { + try( Process2 ignored2 = new Process2.Builder().in(baseDir).waitAfterStartFor("ContactService v11 and v20 up.") + .executable("java -jar ./target/routing-maven-1.0-SNAPSHOT.jar").start()) { + sleep(2000); // wait for Endpoints to start // directly talk to versioned endpoints - assertContains("1.1", postAndAssert(200, "http://localhost:3024/ContactService/v11", header, request_v11)); - assertContains("2.0", postAndAssert(200, "http://localhost:3024/ContactService/v20", header, request_v20)); + assertContains("1.1", postAndAssert(200, "http://localhost:3024/ContactService/v11", CONTENT_TYPE_TEXT_XML_HEADER, request_v11)); + assertContains("2.0", postAndAssert(200, "http://localhost:3024/ContactService/v20", CONTENT_TYPE_TEXT_XML_HEADER, request_v20)); // talk to wrong endpoint - postAndAssert(500, "http://localhost:3024/ContactService/v20", header, request_v11); + postAndAssert(500, "http://localhost:3024/ContactService/v20", CONTENT_TYPE_TEXT_XML_HEADER, request_v11); // talk to proxy - assertContains("1.1", postAndAssert(200, "http://localhost:3025/ContactService", header, request_v11)); - assertContains("2.0", postAndAssert(200, "http://localhost:3025/ContactService", header, request_v20)); - - } finally { - jarNode1.killScript(); + assertContains("1.1", postAndAssert(200, "http://localhost:3025/ContactService", CONTENT_TYPE_TEXT_XML_HEADER, request_v11)); + assertContains("2.0", postAndAssert(200, "http://localhost:3025/ContactService", CONTENT_TYPE_TEXT_XML_HEADER, request_v20)); } - - } finally { - sl.killScript(); } - } } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/XsltExampleTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/XsltExampleTest.java index f54ca23aa2..eb2a4437b0 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/XsltExampleTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/versioning/XsltExampleTest.java @@ -13,66 +13,64 @@ limitations under the License. */ package com.predic8.membrane.examples.tests.versioning; -import com.predic8.membrane.examples.DistributionExtractingTestcase; -import com.predic8.membrane.examples.Process2; +import com.predic8.membrane.examples.tests.DistributionExtractingTestcase; +import com.predic8.membrane.examples.util.Process2; import com.predic8.membrane.examples.util.BufferLogger; import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import java.io.File; import java.io.IOException; +import java.nio.charset.*; import static com.predic8.membrane.test.AssertUtils.*; import static com.predic8.membrane.test.AssertUtils.postAndAssert; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.readFileToString; public class XsltExampleTest extends DistributionExtractingTestcase { - @Test - public void test() throws IOException, InterruptedException { - File base = getExampleDir("versioning/xslt"); + String request_v11; + String request_v20; - String header[] = new String[] { "Content-Type", "text/xml" }; - String request_v11 = FileUtils.readFileToString(new File(base, "request_v11.xml")); - String request_v20 = FileUtils.readFileToString(new File(base, "request_v20.xml")); + @BeforeEach + void setup() throws IOException { + request_v11 = readFileFromBaseDir("request_v11.xml"); + request_v20 = readFileFromBaseDir("request_v20.xml"); + } - replaceInFile(new File(base, "proxies.xml"), "8080", "3027"); - replaceInFile(new File(base, "proxies.xml"), "2000", "3028"); - replaceInFile(new File(base, "src/main/java/com/predic8/contactservice/Launcher.java"), "8080", "3027"); + @Override + protected String getExampleDirName() { + return "versioning/xslt"; + } + + @Test + public void test() throws Exception { + replaceInFile2("proxies.xml", "8080", "3027"); + replaceInFile2("proxies.xml", "2000", "3028"); + replaceInFile2("src/main/java/com/predic8/contactservice/Launcher.java", "8080", "3027"); - BufferLogger b = new BufferLogger(); - Process2 mvn = new Process2.Builder().in(base).executable("mvn clean compile assembly:single").withWatcher(b).start(); - try { + BufferLogger logger = new BufferLogger(); + try(Process2 mvn = new Process2.Builder().in(baseDir).executable("mvn clean compile assembly:single").withWatcher(logger).start()) { int exitCode = mvn.waitFor(60000); if (exitCode != 0) - throw new RuntimeException("Maven exited with code " + exitCode + ": " + b.toString()); - } finally { - mvn.killScript(); + throw new RuntimeException("Maven exited with code " + exitCode + ": " + logger); } + try(Process2 jarNode1 = new Process2.Builder().in(baseDir).waitAfterStartFor("ContactService v20 up.") + .executable("java -jar ./target/xslt-maven-1.0-SNAPSHOT.jar").start()) { + sleep(2000); + assertContains("404", postAndAssert(404, "http://localhost:3027/ContactService/v11", CONTENT_TYPE_TEXT_XML_HEADER, request_v11)); - Process2 jarNode1 = new Process2.Builder().in(base).waitAfterStartFor("ContactService v20 up.") - .executable("java -jar ./target/xslt-maven-1.0-SNAPSHOT.jar").start(); - try { - Thread.sleep(2000); - assertContains("404", postAndAssert(404, "http://localhost:3027/ContactService/v11", header, request_v11)); - - Process2 sl = new Process2.Builder().in(base).script("service-proxy").waitForMembrane().start(); - - try { - Thread.sleep(2000); // wait for Endpoints to start + try(Process2 ignored = startServiceProxyScript()) { + sleep(1000); // wait for Endpoints to start // talk to proxy - assertContains("Hello John", postAndAssert(200, "http://localhost:3028/ContactService/v20", header, request_v11)); - assertContains("Hello John", postAndAssert(200, "http://localhost:3028/ContactService/v20", header, request_v20)); + assertContains("Hello John", postAndAssert(200, "http://localhost:3028/ContactService/v20", CONTENT_TYPE_TEXT_XML_HEADER, request_v11)); + assertContains("Hello John", postAndAssert(200, "http://localhost:3028/ContactService/v20", CONTENT_TYPE_TEXT_XML_HEADER, request_v20)); - } finally { - sl.killScript(); } - - } finally { - jarNode1.killScript(); - } - } -} +} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/util/BufferLogger.java b/distribution/src/test/java/com/predic8/membrane/examples/util/BufferLogger.java index 1c2242521f..7366fe9127 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/util/BufferLogger.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/BufferLogger.java @@ -14,12 +14,14 @@ package com.predic8.membrane.examples.util; -import com.predic8.membrane.examples.AbstractConsoleWatcher; +public class BufferLogger implements ConsoleWatcher { -public class BufferLogger extends AbstractConsoleWatcher { + private final StringBuffer b = new StringBuffer(); + private final String newline = System.getProperty("line.separator"); - private StringBuffer b = new StringBuffer(); - private String newline = System.getProperty("line.separator"); + public boolean contains(String s) { + return b.toString().contains(s); + } @Override public void outputLine(boolean error, String line) { diff --git a/distribution/src/test/java/com/predic8/membrane/examples/util/ConsoleLogger.java b/distribution/src/test/java/com/predic8/membrane/examples/util/ConsoleLogger.java index d0fa62baba..b5e11e0a38 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/util/ConsoleLogger.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/ConsoleLogger.java @@ -14,9 +14,7 @@ package com.predic8.membrane.examples.util; -import com.predic8.membrane.examples.AbstractConsoleWatcher; - -public class ConsoleLogger extends AbstractConsoleWatcher { +public class ConsoleLogger implements ConsoleWatcher { @Override public void outputLine(boolean error, String line) { diff --git a/distribution/src/test/java/com/predic8/membrane/examples/AbstractConsoleWatcher.java b/distribution/src/test/java/com/predic8/membrane/examples/util/ConsoleWatcher.java similarity index 83% rename from distribution/src/test/java/com/predic8/membrane/examples/AbstractConsoleWatcher.java rename to distribution/src/test/java/com/predic8/membrane/examples/util/ConsoleWatcher.java index 25a70e4678..86e62c7c4d 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/AbstractConsoleWatcher.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/ConsoleWatcher.java @@ -12,16 +12,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.predic8.membrane.examples; +package com.predic8.membrane.examples.util; /** * Watches what happens on a client process's console. */ -public abstract class AbstractConsoleWatcher { +public interface ConsoleWatcher { /** * @param error whether the line was printed on stdout or stderr * @param line the line */ - public abstract void outputLine(boolean error, String line); - + void outputLine(boolean error, String line); } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/Process2.java b/distribution/src/test/java/com/predic8/membrane/examples/util/Process2.java similarity index 76% rename from distribution/src/test/java/com/predic8/membrane/examples/Process2.java rename to distribution/src/test/java/com/predic8/membrane/examples/util/Process2.java index 503e1ba119..bb54369dad 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/Process2.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/Process2.java @@ -12,15 +12,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.predic8.membrane.examples; - -import com.predic8.membrane.examples.util.SubstringWaitableConsoleEvent; +package com.predic8.membrane.examples.util; import java.io.*; -import java.nio.charset.Charset; +import java.nio.charset.*; import java.util.*; import java.util.concurrent.TimeoutException; +import static java.lang.String.format; +import static java.lang.Thread.sleep; +import static java.nio.charset.StandardCharsets.UTF_16; + /** * Starts a shell script (Windows batch file or Linux shell script) or * executable and later kills it. @@ -33,14 +35,20 @@ * * Note that ProcessStuff is not synchronized, only ProcessStuff.watchers. */ -public class Process2 { +public class Process2 implements AutoCloseable { + + @Override + public void close() throws Exception { + killScript(); + } public static class Builder { private File baseDir; private String id; private String line; private String waitAfterStartFor; - private ArrayList<AbstractConsoleWatcher> watchers = new ArrayList<AbstractConsoleWatcher>(); + private String parameters = ""; + private final ArrayList<ConsoleWatcher> watchers = new ArrayList<>(); public Builder() {} @@ -49,6 +57,11 @@ public Builder in(File baseDir) { return this; } + public Builder parameters(String parameters) { + this.parameters = parameters; + return this; + } + public Builder executable(String line) { if (id != null) throw new IllegalStateException("executable or script is already set."); @@ -65,7 +78,7 @@ public Builder script(String script) { return this; } - public Builder withWatcher(AbstractConsoleWatcher watcher) { + public Builder withWatcher(ConsoleWatcher watcher) { watchers.add(watcher); return this; } @@ -87,9 +100,10 @@ public Process2 start() throws IOException, InterruptedException { throw new IllegalStateException("id not set"); if (line == null) throw new IllegalStateException("line not set"); + + line += " " + parameters; return new Process2(baseDir, id, line, watchers, waitAfterStartFor); } - } private final class OutputWatcher extends Thread { @@ -111,11 +125,11 @@ public void run() { String l = br.readLine(); if (l == null) break; - ArrayList<AbstractConsoleWatcher> watchers; + ArrayList<ConsoleWatcher> watchers; synchronized(ps.watchers) { - watchers = new ArrayList<AbstractConsoleWatcher>(ps.watchers); + watchers = new ArrayList<>(ps.watchers); } - for (AbstractConsoleWatcher watcher : watchers) + for (ConsoleWatcher watcher : watchers) watcher.outputLine(error, l); } } catch (Exception e) { @@ -128,7 +142,7 @@ private class ProcessStuff { public final Process p; public Integer pid; public Thread inputReader, errorReader; - public final List<AbstractConsoleWatcher> watchers = new ArrayList<AbstractConsoleWatcher>(); + public final List<ConsoleWatcher> watchers = new ArrayList<>(); public ProcessStuff(Process p) { this.p = p; @@ -149,11 +163,14 @@ public int waitFor(long timeout) throws InterruptedException { } } - private ProcessStuff stuff; + private final ProcessStuff stuff; + + private static final Random random = new Random(System.currentTimeMillis()); - private static Random random = new Random(System.currentTimeMillis()); + private Process2(File exampleDir, String id, String startCommand, List<ConsoleWatcher> consoleWatchers, String waitAfterStartFor) throws IOException, InterruptedException { + + System.out.println("exampleDir = " + exampleDir + ", id = " + id + ", startCommand = " + startCommand + ", consoleWatchers = " + consoleWatchers + ", waitAfterStartFor = " + waitAfterStartFor); - private Process2(File exampleDir, String id, String startCommand, List<AbstractConsoleWatcher> consoleWatchers, String waitAfterStartFor) throws IOException, InterruptedException { if (!exampleDir.exists()) throw new RuntimeException("Example dir " + exampleDir.getAbsolutePath() + " does not exist."); @@ -162,28 +179,31 @@ private Process2(File exampleDir, String id, String startCommand, List<AbstractC pidFile = id + "-" + random.nextInt() + ".pid"; } - ArrayList<String> command = new ArrayList<String>(); + ArrayList<String> command = new ArrayList<>(); Charset charset; Map<String, String> envVarAdditions = new HashMap<>(); if (isWindows()) { File ps1 = new File(exampleDir, id + ".ps1"); FileWriter fw = new FileWriter(ps1); - fw.write("\"\" + [System.Diagnostics.Process]::GetCurrentProcess().Id > \""+pidFile+"\"\r\n" + - startCommand+"\r\n"+ - "exit $LASTEXITCODE"); + fw.write(createStartCommand(startCommand, pidFile)); fw.close(); - charset = Charset.forName("UTF-16"); // powershell writes UTF-16 files by default + charset = UTF_16; // powershell writes UTF-16 files by default command.add("powershell"); command.add(ps1.getAbsolutePath()); } else { + // Linux and Mac OS + // On Mac OS the setsid command must be installed: brew install util-linux File ps1 = new File(exampleDir, id + "_launcher.sh"); FileWriter fw = new FileWriter(ps1); fw.write("#!/bin/bash\n"); fw.write("echo $$ > \""+pidFile+"\"\n" + startCommand); fw.close(); + + //noinspection ResultOfMethodCallIgnored ps1.setExecutable(true); + charset = Charset.defaultCharset(); // on Linux, the file is probably using some 8-bit charset command.add("setsid"); // start new process group so we can kill it at once command.add(ps1.getAbsolutePath()); @@ -196,22 +216,16 @@ private Process2(File exampleDir, String id, String startCommand, List<AbstractC pb.environment().remove("MEMBRANE_HOME"); pb.environment().putAll(envVarAdditions); //pb.redirectError(ProcessBuilder.Redirect.PIPE).redirectOutput(Redirect.PIPE).redirectInput(Redirect.PIPE); + final Process p = pb.start(); p.getOutputStream().close(); ProcessStuff ps = new ProcessStuff(p); stuff = ps; -// consoleWatchers.add(new AbstractConsoleWatcher() { -// @Override -// public void outputLine(boolean error, String line) { -// System.out.println(line); -// } -// }); - + consoleWatchers.add((error, line) -> System.out.println(line)); - for (AbstractConsoleWatcher acw : consoleWatchers) - ps.watchers.add(acw); + ps.watchers.addAll(consoleWatchers); SubstringWaitableConsoleEvent afterStartWaiter = null; if (waitAfterStartFor != null) @@ -230,12 +244,11 @@ private Process2(File exampleDir, String id, String startCommand, List<AbstractC } if (i == 1000) throw new RuntimeException("could not read PID file"); - Thread.sleep(100); + sleep(100); File f = new File(exampleDir, pidFile); if (!f.exists()) continue; - FileInputStream fr = new FileInputStream(f); - try { + try (FileInputStream fr = new FileInputStream(f)) { String line = new BufferedReader(new InputStreamReader(fr, charset)).readLine(); if (line == null) continue; @@ -243,39 +256,39 @@ private Process2(File exampleDir, String id, String startCommand, List<AbstractC break; } catch (NumberFormatException e) { // ignore - } finally { - fr.close(); } } if (afterStartWaiter != null) - afterStartWaiter.waitFor(60000); - Thread.sleep(100); + afterStartWaiter.waitFor(10000); + sleep(100); + } + + private String createStartCommand(String startCommand, String pidFile) { + return format("\"\" + [System.Diagnostics.Process]::GetCurrentProcess().Id > \"%s\"\r\n%s\r\nexit $LASTEXITCODE", pidFile, startCommand); } public static boolean isWindows() { return System.getProperty("os.name").contains("Windows"); } - public Process2 addConsoleWatcher(AbstractConsoleWatcher watcher) { + public void addConsoleWatcher(ConsoleWatcher watcher) { synchronized(stuff.watchers) { stuff.watchers.add(watcher); } - return this; } - public Process2 removeConsoleWatcher(AbstractConsoleWatcher watcher) { + public void removeConsoleWatcher(ConsoleWatcher watcher) { synchronized(stuff.watchers) { stuff.watchers.remove(watcher); } - return this; } public void killScript() throws InterruptedException, IOException { ProcessStuff ps = stuff; // start the killer - ArrayList<String> command = new ArrayList<String>(); + ArrayList<String> command = new ArrayList<>(); if (isWindows()) { command.add("taskkill"); command.add("/T"); // kill whole subtree @@ -296,10 +309,10 @@ public void killScript() throws InterruptedException, IOException { ProcessStuff killerStuff = new ProcessStuff(killer); //killerStuff.watchers.add(new ConsoleLogger()); killerStuff.startOutputWatchers(); - killerStuff.waitFor(60000); + killerStuff.waitFor(10000); // wait for membrane to terminate - ps.waitFor(60000); + ps.waitFor(10000); } private static int waitFor(Process p, long timeout) { @@ -310,17 +323,21 @@ private static int waitFor(Process p, long timeout) { } catch (IllegalThreadStateException e) { // continue waiting } - long left = timeout - (System.currentTimeMillis() - start); - if (left <= 0) + if (getTimeLeft(timeout, start) <= 0) throw new RuntimeException(new TimeoutException()); try { - Thread.sleep(500); + //noinspection BusyWait + sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } + private static long getTimeLeft(long timeout, long start) { + return timeout - (System.currentTimeMillis() - start); + } + public int waitFor(long timeout) { return waitFor(stuff.p, timeout); } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/ProxiesXmlUtil.java b/distribution/src/test/java/com/predic8/membrane/examples/util/ProxiesXmlUtil.java similarity index 73% rename from distribution/src/test/java/com/predic8/membrane/examples/ProxiesXmlUtil.java rename to distribution/src/test/java/com/predic8/membrane/examples/util/ProxiesXmlUtil.java index c3c174dab4..f164e7894c 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/ProxiesXmlUtil.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/ProxiesXmlUtil.java @@ -12,24 +12,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.predic8.membrane.examples; +package com.predic8.membrane.examples.util; import java.io.File; import java.io.IOException; +import java.nio.charset.*; +import com.predic8.membrane.examples.util.*; import org.apache.commons.io.FileUtils; -import com.predic8.membrane.examples.util.SubstringWaitableConsoleEvent; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.writeStringToFile; public class ProxiesXmlUtil { - private File proxiesXml; - - public ProxiesXmlUtil(String file) { - proxiesXml = new File(file); - if (!proxiesXml.exists()) - throw new IllegalArgumentException("File " + file + " does not exist."); - } + private final File proxiesXml; public ProxiesXmlUtil(File file) { proxiesXml = file; @@ -39,8 +36,7 @@ public ProxiesXmlUtil(File file) { public void updateWith(String proxiesXmlContent, Process2 sl) throws IOException { SubstringWaitableConsoleEvent reloaded = new SubstringWaitableConsoleEvent(sl, "Spring Hot Deployment Thread started."); - FileUtils.writeStringToFile(proxiesXml, proxiesXmlContent); - reloaded.waitFor(10000); + writeStringToFile(proxiesXml, proxiesXmlContent, UTF_8); + reloaded.waitFor(60000); } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/util/SubstringWaitableConsoleEvent.java b/distribution/src/test/java/com/predic8/membrane/examples/util/SubstringWaitableConsoleEvent.java index d99ad286e6..65dfed144e 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/util/SubstringWaitableConsoleEvent.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/SubstringWaitableConsoleEvent.java @@ -14,8 +14,7 @@ package com.predic8.membrane.examples.util; -import com.google.common.base.Predicate; -import com.predic8.membrane.examples.Process2; +import com.google.common.base.*; /** * Watches the console until "substring" is found. @@ -23,12 +22,9 @@ public class SubstringWaitableConsoleEvent extends WaitableConsoleEvent { public SubstringWaitableConsoleEvent(Process2 launcher, final String substring) { - super(launcher, new Predicate<String>() { - @Override - public boolean apply(String line) { - return line.contains(substring); - } + super(launcher, (Predicate<String>) line -> { + assert line != null; + return line.contains(substring); }); } - } diff --git a/distribution/src/test/java/com/predic8/membrane/examples/util/WaitableConsoleEvent.java b/distribution/src/test/java/com/predic8/membrane/examples/util/WaitableConsoleEvent.java index c07de6cb0e..860577a64b 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/util/WaitableConsoleEvent.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/util/WaitableConsoleEvent.java @@ -14,29 +14,23 @@ package com.predic8.membrane.examples.util; -import java.util.concurrent.TimeoutException; - -import com.google.common.base.Predicate; -import com.predic8.membrane.examples.AbstractConsoleWatcher; -import com.predic8.membrane.examples.Process2; +import java.util.concurrent.*; +import java.util.function.*; /** * Watches the console output until the predicate turns true. */ public class WaitableConsoleEvent { - private AbstractConsoleWatcher watcher; + private ConsoleWatcher watcher; private boolean event; public WaitableConsoleEvent(final Process2 scriptLauncher, final Predicate<String> predicate) { - watcher = new AbstractConsoleWatcher() { - @Override - public void outputLine(boolean error, String line) { - if (predicate.apply(line)) { - synchronized (WaitableConsoleEvent.this) { - event = true; - scriptLauncher.removeConsoleWatcher(watcher); - WaitableConsoleEvent.this.notifyAll(); - } + watcher = (error, line) -> { + if (predicate.test(line)) { + synchronized (WaitableConsoleEvent.this) { + event = true; + scriptLauncher.removeConsoleWatcher(watcher); + WaitableConsoleEvent.this.notifyAll(); } } }; diff --git a/test/src/main/java/com/predic8/membrane/test/AssertUtils.java b/test/src/main/java/com/predic8/membrane/test/AssertUtils.java index 92ccb35fcf..8d141e5a2d 100644 --- a/test/src/main/java/com/predic8/membrane/test/AssertUtils.java +++ b/test/src/main/java/com/predic8/membrane/test/AssertUtils.java @@ -16,6 +16,7 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.*; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -57,6 +58,11 @@ import org.apache.http.protocol.HttpCoreContext; import org.apache.http.util.EntityUtils; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.writeStringToFile; +import static org.apache.http.client.protocol.HttpClientContext.CREDS_PROVIDER; +import static org.apache.http.client.protocol.HttpClientContext.TARGET_AUTH_STATE; +import static org.apache.http.protocol.HttpCoreContext.HTTP_TARGET_HOST; import static org.junit.jupiter.api.Assertions.assertEquals; public class AssertUtils { @@ -88,6 +94,7 @@ public static String getAndAssert(int expectedHttpStatusCode, String url) throws } public static String getAndAssert(int expectedHttpStatusCode, String url, String[] header) throws ParseException, IOException { + HttpResponse result; if (hc == null) hc = HttpClientBuilder.create().build(); HttpGet get = new HttpGet(url); @@ -106,13 +113,37 @@ public static String getAndAssert(int expectedHttpStatusCode, String url, String } finally { get.releaseConnection(); } + + } + + public static HttpResponse getAndAssertWithResponse(int expectedHttpStatusCode, String url, String[] header) throws ParseException, IOException { + if (hc == null) + hc = HttpClientBuilder.create().build(); + HttpGet get = new HttpGet(url); + try { + if (header != null) + for (int i = 0; i < header.length; i += 2) + get.addHeader(header[i], header[i+1]); + HttpResponse res = hc.execute(get); + try { + assertEquals(expectedHttpStatusCode, res.getStatusLine().getStatusCode()); + } catch (AssertionError e) { + throw new AssertionError(e.getMessage() + " while fetching " + url); + } + System.out.println(res); + res.getEntity(); + return res; + } finally { + get.releaseConnection(); + } } - public static String postAndAssert200(String url, String body) throws ClientProtocolException, IOException { + public static String postAndAssert200(String url, String body) throws IOException { + System.out.println("url = " + url + ", body = " + body); return postAndAssert(200, url, body); } - public static String assertStatusCode(int expectedHttpStatusCode, HttpUriRequest request) throws ClientProtocolException, IOException { + public static String assertStatusCode(int expectedHttpStatusCode, HttpUriRequest request) throws IOException { if (hc == null) hc = HttpClientBuilder.create().build(); HttpResponse res = hc.execute(request); @@ -120,11 +151,11 @@ public static String assertStatusCode(int expectedHttpStatusCode, HttpUriRequest return EntityUtils.toString(res.getEntity()); } - public static String postAndAssert(int expectedHttpStatusCode, String url, String body) throws ClientProtocolException, IOException { + public static String postAndAssert(int expectedHttpStatusCode, String url, String body) throws IOException { return postAndAssert(expectedHttpStatusCode, url, new String[0], body); } - public static String postAndAssert(int expectedHttpStatusCode, String url, String[] headers, String body) throws ClientProtocolException, IOException { + public static String postAndAssert(int expectedHttpStatusCode, String url, String[] headers, String body) throws IOException { if (hc == null) hc = HttpClientBuilder.create().build(); HttpPost post = new HttpPost(url); @@ -154,26 +185,28 @@ private static HttpClient getAuthenticatingHttpClient(String host, int port, Str Credentials defaultcreds = new UsernamePasswordCredentials(user, pass); BasicCredentialsProvider bcp = new BasicCredentialsProvider(); bcp.setCredentials(new AuthScope(host, port, AuthScope.ANY_REALM), defaultcreds); - HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() { - public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { - AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE); - CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER); - HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST); - if (authState.getAuthScheme() == null) { - AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort()); - Credentials creds = credsProvider.getCredentials(authScope); - if (creds != null) { - authState.update(new BasicScheme(), creds); - } + HttpRequestInterceptor preemptiveAuth = (request, context) -> { + AuthState authState = (AuthState) context.getAttribute(TARGET_AUTH_STATE); + if (authState.getAuthScheme() == null) { + Credentials creds = getCredentials(context); + if (creds != null) { + authState.update(new BasicScheme(), creds); } } }; - HttpClient hc = HttpClientBuilder.create() + return HttpClientBuilder.create() .setDefaultCookieStore(new BasicCookieStore()) .setDefaultCredentialsProvider(bcp) .addInterceptorFirst(preemptiveAuth) .build(); - return hc; + } + + private static Credentials getCredentials(HttpContext context) { + return ((CredentialsProvider) context.getAttribute(CREDS_PROVIDER)).getCredentials(getAuthScope((HttpHost) context.getAttribute(HTTP_TARGET_HOST))); + } + + private static AuthScope getAuthScope(HttpHost targetHost) { + return new AuthScope(targetHost.getHostName(), targetHost.getPort()); } public static void trustAnyHTTPSServer(int port) throws NoSuchAlgorithmException, KeyManagementException { @@ -185,22 +218,19 @@ public X509Certificate[] getAcceptedIssuers() { } @Override - public void checkServerTrusted(X509Certificate[] arg0, String arg1) - throws CertificateException { + public void checkServerTrusted(X509Certificate[] arg0, String arg1) { } @Override - public void checkClientTrusted(X509Certificate[] arg0, String arg1) - throws CertificateException { + public void checkClientTrusted(X509Certificate[] arg0, String arg1) { } } }, new SecureRandom()); - SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE); - hc = HttpClientBuilder.create().setSSLSocketFactory(sslsf).build(); + hc = HttpClientBuilder.create().setSSLSocketFactory(new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE)).build(); } public static void replaceInFile(File file, String from, String to_) throws IOException { - FileUtils.writeStringToFile(file, FileUtils.readFileToString(file).replace(from, to_)); + writeStringToFile(file, FileUtils.readFileToString(file, UTF_8).replace(from, to_), UTF_8); } @@ -210,5 +240,4 @@ public static void closeConnections() { hc = null; } } - }