/* * This file is part of LibrePlan * * Copyright (C) 2013 St. Antoniusziekenhuis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.libreplan.importers; import java.io.File; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.soap.MessageFactory; import javax.xml.soap.Node; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPConnection; import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.cxf.common.util.Base64Utility; import org.libreplan.importers.tim.RosterResponseDTO; /** * Client to interact with Tim SOAP server. * * This client creates SOAP message, makes connection to the SOAP server and sends the request. * It is also the task of this client to convert the response(xml document) to java objects. * * @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl> */ public class TimSoapClient { private static final Log LOG = LogFactory.getLog(TimSoapClient.class); /** * Creates request message to be send to the SOAP server * * @param clazz * object to be marshaled * @param userName * the user name * @param password * the password * @return the created soap message * @throws SOAPException * if unable to create message or envelope * @throws JAXBException * if unable to marshal the clazz */ private static <T> SOAPMessage createRequest( T clazz, String userName, String password) throws SOAPException, JAXBException { SOAPMessage message = createMessage(); addAuthorization(message, userName, password); SOAPEnvelope soapEnvelope = createEnvelope(message.getSOAPPart()); SOAPBody soapBody = soapEnvelope.getBody(); marshal(clazz, soapBody); message.saveChanges(); return message; } /** * Creates SOAP message to be send to the SOAP server * * @return the created SOAP message * @throws SOAPException * if unable to create soap message */ private static SOAPMessage createMessage() throws SOAPException { MessageFactory messageFactory = MessageFactory.newInstance(); return messageFactory.createMessage(); } /** * Adds authorization to the specified parameter <code>message</code> * * @param message * the message * @param username * the user name * @param password * the password */ private static void addAuthorization(SOAPMessage message, String username, String password) { String encodeUserInfo = username + ":" + password; encodeUserInfo = Base64Utility.encode(encodeUserInfo.getBytes()); message.getMimeHeaders().setHeader("Authorization", "Basic " + encodeUserInfo); } /** * Creates SOAP envelope and adds namespace declaration and sets encoding * style * * @param soapPart * the message part * @return the SOAP envelope * @throws SOAPException */ private static SOAPEnvelope createEnvelope(SOAPPart soapPart) throws SOAPException { SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); addNamespaceDeclaration(soapEnvelope); setEncodingStyle(soapEnvelope); return soapEnvelope; } /** * Adds namespace declaration to the specified parameter * <code>soapEnvelop</code> * * @param soapEnvelope * the SOAP envelope * @throws SOAPException */ private static void addNamespaceDeclaration(SOAPEnvelope soapEnvelope) throws SOAPException { soapEnvelope.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema"); soapEnvelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance"); soapEnvelope.addNamespaceDeclaration("enc", "http://schemas.xmlsoap.org/soap/encoding/"); soapEnvelope.addNamespaceDeclaration("env", "http://schemas.xmlsoap.org/soap/envelop/"); } /** * Sets the encoding style to the specified parameter * <code>soapEnvelop</code> * * @param soapEnvelope * the SOAP envelope * @throws SOAPException */ private static void setEncodingStyle(SOAPEnvelope soapEnvelope) throws SOAPException { soapEnvelope.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/"); } /** * Marshals the specified parameter <code>clazz</code> to the specified * <code>soapBody</code> * * @param clazz * the object to be marshaled * @param soapBody * the SOAP body, result of marshal * @throws JAXBException * if marshaling failed */ private static <T> void marshal(T clazz, SOAPBody soapBody) throws JAXBException { JAXBContext jaxbContext = JAXBContext.newInstance(clazz.getClass()); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(clazz, soapBody); } /** * Unmarshals the specified paramter <code>soapBody</code> to the specified * <code>clazz</code> * * @param clazz * object to hold unmarashal result * @param soapBody * the soap body to be unmarshalled * @return the unmarashalled object * @throws JAXBException * if unmarshal failed */ @SuppressWarnings("unchecked") private static <T> T unmarshal(Class<T> clazz, SOAPBody soapBody) throws JAXBException { JAXBContext jaxbContext = JAXBContext.newInstance(clazz); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); Node bindElement = (Node) soapBody.getFirstChild(); while (bindElement.getNodeType() != Node.ELEMENT_NODE) { bindElement = (Node) bindElement.getNextSibling(); } return unmarshaller.unmarshal(bindElement, clazz).getValue(); } /** * Sends the SOAP message request to the SOAP server * * @param url * the endpoint of the web service * @param message * the SOAP message to be send * @return the response, SOAP message * @throws SOAPException * if unable to send request */ private static SOAPMessage sendRequest(String url, SOAPMessage message) throws SOAPException { SOAPConnection connection = null; SOAPMessage response = null; try { connection = createConnection(); response = connection.call(message, url); } finally { if ( connection != null ) { closeConnection(connection); } } return response; } /** * Creates a SOAP connection to the SOAP server * * @return the SOAPconnection object * @throws SOAPException * if unable to create connection */ private static SOAPConnection createConnection() throws SOAPException { SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); return soapConnectionFactory.createConnection(); } /** * Closes the SOAP connection * * @param connection * the SOAP connection * @throws SOAPException * if unable to close connection */ private static void closeConnection(SOAPConnection connection) throws SOAPException { connection.close(); } /** * Sends soap request to the SOAP server. Receives and unmarshals the * response * * @param url * the SOAP server url(endpoint) * @param userName * the user * @param password * the password * @param request * the request object * @param response * the response class * @return the expected object or null */ public static <T, U> T sendRequestReceiveResponse( String url, String userName, String password, U request, Class<T> response) { try { SOAPMessage requestMsg = createRequest(request, userName, password); SOAPMessage responseMsg = sendRequest(url, requestMsg); return unmarshal(response, responseMsg.getSOAPBody()); } catch (SOAPException soapExp) { LOG.error("SOAPException: ", soapExp); } catch (JAXBException jaxbExp) { LOG.error("JAXBException: ", jaxbExp); } return null; } /** * Checks authorization for the specified <code>username</code> and * <code>password</code> * * @param url * webservices url * @param username * the user * @param password * the password * @return true if user is authorized otherwise false */ public static boolean checkAuthorization(String url, String username, String password) { try { SOAPMessage message = createMessage(); addAuthorization(message, username, password); sendRequest(url, message); return true; } catch (SOAPException e) { LOG.error("SOAP Exception: ", e); } return false; } /** * simulates roster response, to be used for example by unit test * * unmarshals the roster xml from the specified <code>file</code> and * returns {@link RosterResponseDTO} * * @param file * file with xml contents * @return exportRosterDTO if unmarshal succeeded otherwise null */ public static RosterResponseDTO unmarshalRosterFromFile(File file) { try { JAXBContext jaxbContext = JAXBContext.newInstance(RosterResponseDTO.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); return (RosterResponseDTO) unmarshaller.unmarshal(file); } catch (JAXBException e) { LOG.error("Error processing response: ", e); } return null; } }