package javacodebook.xml.transport.http.post; import java.net.*; import java.io.*; /** * Die XMLPoster-Klasse benutzt ein URL- bzw. ein URLConnection-Objekt um Strings * an beliebige, z.B. über die Kommandozeile übergebene URLs zu verschicken. Dabei wird * die http-post-Methode verwendet. */ public class XMLPoster { private static final String USAGE = "\nBenutzerhinweis: javacodebook.xml.transport.http.post.XMLPoster " + " [ ...]\n\nwobei\n\n\n" + "die URL ist, an die die XML-Dokumente gepostet werden sollen und\n\n [ ...]\n" + "ein oder mehrere durch Leerzeichen getrennte Dateinamen von XML-Dateien sind, die \n" + "per post verschickt werden sollen"; /** * An die main-Methode müssen die Parameter und eine durch Leerzeichen getrennte Folge von * Dateinamen [ ...] übergeben werden. Es wird ein Objekt vom Typ XMLPoster instanziiert. * Der erste Parameter wird als URL ausgelesen. Für jeden weiteren Paramter wird versucht den Inhalt der entsprechenden * Datei über die loadXML-Methode in einen String zu laden. Dieser String wird dann über die postXML2URL-Methode * des XMLPoster-Objekts an die URL verschickt. */ public static void main(String args[]) { if (args.length < 2) { System.out.println(getUsage()); System.exit(1); } else { String urlString = args[0]; XMLPoster xMLPoster = new XMLPoster(); for (int i = 1; i < args.length; i++) { String fileName = args[i]; try { String xml = xMLPoster.loadXML(fileName); xMLPoster.postXML2URL(xml, urlString); } catch (Exception e) { System.out.println("Probleme bei der Ausführung: " + e); } } } } private String postXML2URL(String xml, String urlString) throws Exception { String answerFromServer = ""; try { // Instanziierung eines URL-Objektes nach RFC 2396: Uniform Resource Identifiers (URI): 'Generic Syntax' // nachgebessert durch RFC 2732: 'Format for Literal IPv6 Addresses in URLs'. URL url = new URL(urlString); // Über das URL-Objekt wird ein URLConnection-Object erzeugt werden. Das URLConnection-Object stellt die // Verbindung zur entfernten Resource mit all ihren Eigenschaften dar. URLConnection con = url.openConnection(); // Die Eigenschaften der Verbindung werden so gesetzt, dass sowohl gesendet als auch empfangen werden kann. // Dabei soll nicht gecached werden. con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); // Setzen der vom HTTP-Standard definierten Request-Property 'CONTENT_LENGTH' con.setRequestProperty("CONTENT_LENGTH", "" + xml.length()); // Von der Verbindung wird eine Referenz auf den OutputStrem geholt, um zum // Server schreiben zu können. OutputStream os = con.getOutputStream(); // Ein OutputStreamWriter-Object wird instanziiert um dann über die write-Methode // den XML-String zum Server zu schreiben. OutputStreamWriter osw = new OutputStreamWriter(os); osw.write(xml); // Auf das OutputStreamWriter-Object muss die flush-Methode aufgerufen werden, um // den String vollständig zu übermitteln. osw.flush(); // Letztlich muss die close-Methode aufgerufen werden um entsprechende Resourcen wieder freizugeben osw.close(); // Durch das Aufrufen, der getInputStream-Methode auf das URLConnection-Objekt wird der // HTTP-Request beim Server abgesetzt. (NICHT wie intuitiv vielleicht erwartet schon beim // schreiben in den Output-Stream) InputStream is = con.getInputStream(); // Nun wird die Antwort ausgelesen InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line = null; while ( (line = br.readLine()) != null) { answerFromServer = answerFromServer + line; } // Auch hier muss der InputStreamReader und somit der InputStream wieder geschlossen werden, da es sonst // zu Resourcenverschwendung kommt. Besonders auf Solaris-Systemen kann das fatale Folgen haben, da für jeden // nicht geschlossenen InputStream ein File-Descriptor offen gehalten wird und die Zahl der erlaubten offenen // File-Descriptoren oft relativ eingeschränkt ist. System.out.println("Answer from Server: " + answerFromServer); isr.close(); } catch (Exception e) { throw new Exception("Probleme beim aufrufen der URL '" + urlString + "' mit: " + e); } return answerFromServer; } /** * Die methode loadXML nimmt einen String als Parameter, der einen Dateinamen * repräsentiert. Diese Datei wird in der Methode in einen String gelesen und * als solcher zurück gegeben. Falls dabei etwas schief geht schmeißt die Methode * eine Exception. */ private String loadXML(String fileName) throws Exception { try { String xml = ""; BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))); String line = br.readLine(); while (line != null) { xml = xml + line + "\n"; line = br.readLine(); } return xml; } catch (Exception e) { throw new Exception("Die Datei '" + fileName + "' konnte nicht geladen werden: " + e); } } public static String getUsage() { return USAGE; } } --- Neue Klasse --- package javacodebook.xml.transport.http.post; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; /** * Der XMLPostReceiver erweitert das HttpServlet und implementiert * die doPost-Methode. Für jeden empfangenen Post-Request wird der * empfangene Stream ausgelesen und der Inhalt in einem String abgelegt, der dann * als pseudo-Verarbeitung in die Standardausgabe geschrieben wird. */ public class XMLPostReceiver extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Über ein Writer-Objekt von dem Response-Objekt wird ein // PrintWriter instanziiert, der benutzt wird, um eine Antwort // zum Client zu schreiben. PrintWriter pw = new PrintWriter(response.getWriter()); try { // Es wird ein BufferedReader erzeugt, um den Stream auszulesen. InputStreamReader isr = new InputStreamReader(request.getInputStream()); BufferedReader br = new BufferedReader(isr); // Inhalte des Streams werden in den String xmlDocument abgelegt. String xmlDocument = ""; String line = br.readLine(); while (line != null) { xmlDocument = xmlDocument + line; line = br.readLine(); } // Weiterverarbeitung des empfangenen XML. System.out.println(xmlDocument); // Da die Verarbeitung erfolgreich war, schicke eine Bestätigung pw.println("processed document"); } // Falls bei der Verarbeitung ein Ausnahmefall auftritt, wird eine // XML-Nachricht zum Client zurück geschrieben, wobei in // diesem Beispiel der Fehlercode -1 für den Ausnahmefall steht. // Innerhalb des message-Elements wird die Fehlermeldung eingefügt. catch (Exception e) { pw.println("" + e.toString() + ""); } // Auf den PrintWriter müssen die flush-Methode und die close-Methode //aufgerufen werden, um keine Resourcen zu verschwenden. pw.flush(); pw.close(); } }