/** * Licensed to the Austrian Association for Software Tool Integration (AASTI) * under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. The AASTI licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openengsb.itests.exam; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.containsString; import static org.ops4j.pax.exam.OptionUtils.combine; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFileExtend; import java.io.ByteArrayInputStream; import java.net.URL; import javax.crypto.SecretKey; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.ws.Dispatch; import javax.xml.ws.Service; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.openengsb.core.api.remote.OutgoingPort; import org.openengsb.core.util.DefaultOsgiUtilsService; import org.openengsb.itests.util.AbstractRemoteTestHelper; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.karaf.options.configs.FeaturesCfg; import org.w3c.dom.Document; @RunWith(PaxExam.class) public class WSPortIT extends AbstractRemoteTestHelper { private static final Integer MAX_SLEEP_TIME_IN_SECONDS = 30; private String wsdlUrl; @Configuration public Option[] additionalConfiguration() throws Exception { return combine(baseConfiguration(), editConfigurationFileExtend(FeaturesCfg.BOOT, ",openengsb-ports-ws,openengsb-connector-example")); } @Before public void checkIfTestsAreReady() throws Exception { String httpPort = getConfigProperty("org.ops4j.pax.web", "org.osgi.service.http.port"); wsdlUrl = String.format("http://localhost:%s/ws/receiver/?wsdl", httpPort); waitForSiteToBeAvailable(wsdlUrl, MAX_SLEEP_TIME_IN_SECONDS); } @Test public void testWsPort_shouldBeExportedWithCorrectId() throws Exception { DefaultOsgiUtilsService utilsService = new DefaultOsgiUtilsService(getBundleContext()); OutgoingPort serviceWithId = utilsService.getServiceWithId(OutgoingPort.class, "ws-json", 60000); assertNotNull(serviceWithId); } @Test public void testStartSimpleWorkflow_ShouldReturn42() throws Exception { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Dispatch<DOMSource> dispatcher = createMessageDispatcher(); String secureRequest = prepareRequest(METHOD_CALL_STRING, "admin", "password"); SecretKey sessionKey = generateSessionKey(); String encryptedMessage = encryptMessage(secureRequest, sessionKey); DOMSource request = convertMessageToDomSource(encryptedMessage); DOMSource response = dispatchMessage(dispatcher, request); String result = transformResponseToMessage(response); verifyEncryptedResult(sessionKey, result); } @Test public void testStartSimpleWorkflowWithFilterMethohdCall_ShouldReturn42() throws Exception { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Dispatch<DOMSource> dispatcher = createMessageDispatcher(); String secureRequest = prepareRequest(METHOD_CALL_STRING_FILTER, "admin", "password"); SecretKey sessionKey = generateSessionKey(); String encryptedMessage = encryptMessage(secureRequest, sessionKey); DOMSource request = convertMessageToDomSource(encryptedMessage); DOMSource response = dispatchMessage(dispatcher, request); String result = transformResponseToMessage(response); verifyEncryptedResult(sessionKey, result); } @Test public void testSendMethodCallWithWrongAuthentication_shouldFail() throws Exception { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Dispatch<DOMSource> dispatcher = createMessageDispatcher(); String secureRequest = prepareRequest(METHOD_CALL_STRING, "admin", "wrong-password"); SecretKey sessionKey = generateSessionKey(); String encryptedMessage = encryptMessage(secureRequest, sessionKey); DOMSource request = convertMessageToDomSource(encryptedMessage); DOMSource response = dispatchMessage(dispatcher, request); String result = transformResponseToMessage(response); assertThat(result, containsString("Exception")); assertThat(result, not(containsString("The answer to life the universe and everything"))); } @Test public void testRecordAuditInCoreService_shouldReturnVoid() throws Exception { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Dispatch<DOMSource> dispatcher = createMessageDispatcher(); String secureRequest = prepareRequest(VOID_CALL_STRING, "admin", "password"); SecretKey sessionKey = generateSessionKey(); String encryptedMessage = encryptMessage(secureRequest, sessionKey); DOMSource request = convertMessageToDomSource(encryptedMessage); DOMSource response = dispatchMessage(dispatcher, request); String result = transformResponseToMessage(response); String decryptedResult = decryptResult(sessionKey, result); assertThat(decryptedResult, containsString("\"type\":\"Void\"")); assertThat(decryptedResult, not(containsString("Exception"))); } private Dispatch<DOMSource> createMessageDispatcher() throws Exception { addWorkflow("simpleFlow"); QName serviceName = new QName("http://ws.ports.openengsb.org/", "PortReceiverService"); Service service = Service.create(new URL(wsdlUrl), serviceName); QName portName = new QName("http://ws.ports.openengsb.org/", "PortReceiverPort"); Dispatch<DOMSource> disp = service.createDispatch(portName, DOMSource.class, Service.Mode.MESSAGE); return disp; } private DOMSource convertMessageToDomSource(String messageToTransport) throws Exception { StringBuilder message = new StringBuilder(); message.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" "); message.append("xmlns:ws=\"http://ws.ports.openengsb.org/\" >"); message.append("<soapenv:Header/>"); message.append("<soapenv:Body>"); message.append("<ws:receive>"); message.append("<arg0>" + messageToTransport + "</arg0>"); message.append("</ws:receive>"); message.append("</soapenv:Body>"); message.append("</soapenv:Envelope>"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder db = factory.newDocumentBuilder(); Document requestDoc = db.parse(new ByteArrayInputStream(message.toString().getBytes())); DOMSource request = new DOMSource(requestDoc); return request; } private DOMSource dispatchMessage(Dispatch<DOMSource> dispatcher, DOMSource request) { DOMSource response = dispatcher.invoke(request); return response; } private String transformResponseToMessage(DOMSource response) throws Exception { Document document = (Document) response.getNode(); XPath xpath = XPathFactory.newInstance().newXPath(); XPathExpression expression = xpath.compile("//return/text()"); String result = (String) expression.evaluate(document, XPathConstants.STRING); return result; } }