///$Header: /cvsroot-fuse/mec-as2/39/mendelson/comm/as2/servlet/HttpReceiver.java,v 1.1 2012/04/18 14:10:39 heller Exp $ package de.mendelson.comm.as2.servlet; /* * Copyright (C) mendelson-e-commerce GmbH Berlin Germany * * This software is subject to the license agreement set forth in the license. * Please read and agree to all terms before using this software. * Other product and brand names are trademarks of their respective owners. */ /** * Servlet to receive rosettanet messages via HTTP * @author S.Heller * @version $Revision: 1.1 $ */ import de.mendelson.Copyright; import de.mendelson.comm.as2.AS2ServerVersion; import de.mendelson.comm.as2.client.rmi.GenericClient; import de.mendelson.comm.as2.clientserver.ErrorObject; import de.mendelson.comm.as2.clientserver.serialize.CommandObjectIncomingMessage; import de.mendelson.comm.as2.preferences.PreferencesAS2; import de.mendelson.comm.as2.server.AS2Server; import de.mendelson.util.AS2Tools; import java.io.*; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Properties; import java.util.logging.Logger; import javax.servlet.*; import javax.servlet.http.*; public class HttpReceiver extends HttpServlet { private Logger logger = Logger.getLogger(AS2Server.SERVER_LOGGER_NAME); private PreferencesAS2 preferences = new PreferencesAS2(); public HttpReceiver() { } /**A GET request should be rejected*/ @Override public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { PrintWriter out = res.getWriter(); res.setContentType("text/html"); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"); out.println("<html>"); out.println(" <head>"); out.println(" <META NAME=\"description\" CONTENT=\"mendelson-e-commerce GmbH: Your EAI partner\">"); out.println(" <META NAME=\"copyright\" CONTENT=\"mendelson-e-commerce GmbH\">"); out.println(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); out.println(" <title>" + AS2ServerVersion.getProductName() + "</title>"); out.println(" <link rel=\"shortcut icon\" href=\"images/mendelson_favicon.png\" type=\"image/x-icon\" />"); out.println(" </head>"); out.println(" <body>"); out.println("<H2>" + AS2ServerVersion.getProductName() + " " + AS2ServerVersion.getVersion() + " " + AS2ServerVersion.getBuild() + "</H2>"); out.println("<BR> " + Copyright.getCopyrightMessage()); out.println("<BR><br>You have performed an HTTP GET on this URL. <BR>"); out.println("To submit an AS2 message, you must POST the message to this URL <BR>"); out.println(" </body>"); out.println("</html>"); } /**POST by the HTTP client: receive the message and work on it*/ @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //stores if the commit already occured. Do not send an additional error in this case boolean committed = false; File dataFile = null; try { InputStream inStream = request.getInputStream(); //store the data in a file to process it later. This may be useful //for a huge data request that may lead to a out of memory fairly easy. dataFile = AS2Tools.createTempFile("as2", "request"); dataFile.deleteOnExit(); FileOutputStream fileStream = new FileOutputStream(dataFile); this.copyStreams(inStream, fileStream); fileStream.flush(); fileStream.close(); //extract header LinkedHashMap<String, String> headerMap = new LinkedHashMap<String, String>(); Enumeration enumeration = request.getHeaderNames(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); headerMap.put(key.toLowerCase(), request.getHeader(key)); } //check if this is a AS2 message that requests async MDN. In this case return the ok code //before processing the message, there is no need to keep the connection alive. boolean isAS2MessageRequestingAsyncMDN = headerMap.containsKey("receipt-delivery-option") && headerMap.get("receipt-delivery-option") != null && headerMap.get("receipt-delivery-option").trim().length() > 0; if (isAS2MessageRequestingAsyncMDN) { response.setStatus(HttpServletResponse.SC_OK); //close the connection response.getWriter().flush(); response.getWriter().close(); committed = true; this.informAS2ServerIncomingMessage(dataFile, headerMap, request, null); } else { this.informAS2ServerIncomingMessage(dataFile, headerMap, request, response); } } catch (Throwable e) { if (!committed) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } } finally { if (dataFile != null) { dataFile.delete(); } } }//end of doPost /**Informs the AS2 server that a new message arrived and returns the HTTP returncode that has been set * by the processing server */ private void informAS2ServerIncomingMessage(File dataFile, LinkedHashMap<String, String> headerMap, HttpServletRequest request, HttpServletResponse response) throws Exception { GenericClient client = new GenericClient(); CommandObjectIncomingMessage commandObject = new CommandObjectIncomingMessage(); commandObject.setMessageDataFilename(dataFile.getAbsolutePath()); commandObject.setContentType(request.getContentType()); String remoteHost = request.getRemoteHost(); if (remoteHost == null) { remoteHost = request.getRemoteAddr(); } commandObject.setRemoteHost(remoteHost); Iterator<String> headerIterator = headerMap.keySet().iterator(); while (headerIterator.hasNext()) { String key = headerIterator.next(); commandObject.addHeader(key, headerMap.get(key)); } ErrorObject errorObject = client.send(commandObject); if (errorObject.getErrors() > 0) { StringBuilder exceptionBuffer = new StringBuilder(); ArrayList log = commandObject.getLog(); for (int i = 0; i < log.size(); i++) { if (log.get(i) != null) { this.logger.severe(log.get(i).toString()); exceptionBuffer.append(log.get(i).toString() + "\n"); } } throw new Exception(exceptionBuffer.toString()); } //build up response, this is the sync MDN if (response != null) { CommandObjectIncomingMessage responseCommand = (CommandObjectIncomingMessage) client.getCommandObject(); if( responseCommand.getHttpReturnCode() != HttpServletResponse.SC_OK){ response.setStatus(responseCommand.getHttpReturnCode()); } //add MDN data if (responseCommand.getMDNData() != null) { Properties header = responseCommand.getHeader(); Iterator iterator = header.keySet().iterator(); while (iterator.hasNext()) { String key = (String) iterator.next(); response.setHeader(key, header.getProperty(key)); } ByteArrayInputStream inStream = new ByteArrayInputStream(responseCommand.getMDNData()); ServletOutputStream outStream = response.getOutputStream(); this.copyStreams(inStream, outStream); inStream.close(); outStream.flush(); } } } /**Checks if the mbi server runs local or not */ public boolean serverRunsLocal() { try { String server = this.preferences.get(PreferencesAS2.SERVER_HOST); String serverAddress = InetAddress.getByName(server).getHostAddress(); String localname = InetAddress.getLocalHost().getCanonicalHostName(); InetAddress[] localhost = InetAddress.getAllByName("127.0.0.1"); for (int i = 0; i < localhost.length; i++) { if (localhost[i].getHostAddress().equals(serverAddress)) { return (true); } } localhost = InetAddress.getAllByName(localname); for (int i = 0; i < localhost.length; i++) { if (localhost[i].getHostAddress().equals(serverAddress)) { return (true); } } } catch (UnknownHostException ignore) { } return (false); } /**Copies all data from one stream to another*/ private void copyStreams(InputStream in, OutputStream out) throws IOException { BufferedInputStream inStream = new BufferedInputStream(in); BufferedOutputStream outStream = new BufferedOutputStream(out); //copy the contents to an output stream byte[] buffer = new byte[1024]; int read = 1024; //a read of 0 must be allowed, sometimes it takes time to //extract data from the input while (read != -1) { read = inStream.read(buffer); if (read > 0) { outStream.write(buffer, 0, read); } } outStream.flush(); } /** Returns a short description of the servlet. */ @Override public String getServletInfo() { return "Receive AS2 messages via HTTP/S"; } }