Merge from the pain train
[official-gcc.git] / libjava / gnu / xml / pipeline / CallFilter.java
blobda1a2e9c1025e3f3d2b1285beec21df7bbb2c9b5
1 /* CallFilter.java --
2 Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.xml.pipeline;
40 import java.io.IOException;
41 import java.io.OutputStreamWriter;
42 import java.net.URL;
43 import java.net.URLConnection;
44 import java.io.Writer;
46 import org.xml.sax.DTDHandler;
47 import org.xml.sax.ErrorHandler;
48 import org.xml.sax.InputSource;
49 import org.xml.sax.SAXException;
50 import org.xml.sax.SAXNotRecognizedException;
51 import org.xml.sax.XMLReader;
52 import org.xml.sax.helpers.XMLReaderFactory;
54 import gnu.xml.util.Resolver;
55 import gnu.xml.util.XMLWriter;
58 /**
59 * Input is sent as an XML request to given URI, and the output of this
60 * filter is the parsed response to that request.
61 * A connection is opened to the remote URI when the startDocument call is
62 * issued through this filter, and the request is finished when the
63 * endDocument call is issued. Events should be written quickly enough to
64 * prevent the remote HTTP server from aborting the connection due to
65 * inactivity; you may want to buffer text in an earlier pipeline stage.
66 * If your application requires validity checking of such
67 * outputs, have the output pipeline include a validation stage.
69 * <p>In effect, this makes a remote procedure call to the URI, with the
70 * request and response document syntax as chosen by the application.
71 * <em>Note that all the input events must be seen, and sent to the URI,
72 * before the first output event can be seen. </em> Clients are delayed
73 * at least by waiting for the server to respond, constraining concurrency.
74 * Services can thus be used to synchronize concurrent activities, and
75 * even to prioritize service among different clients.
77 * <p> You are advised to avoid restricting yourself to an "RPC" model
78 * for distributed computation. With a World Wide Web, network latencies
79 * and failures (e.g. non-availability)
80 * are significant; adopting a "procedure" model, rather than a workflow
81 * model where bulk requests are sent and worked on asynchronously, is not
82 * generally an optimal system-wide architecture. When the messages may
83 * need authentication, such as with an OpenPGP signature, or when server
84 * loads don't argue in favor of immediate responses, non-RPC models can
85 * be advantageous. (So-called "peer to peer" computing models are one
86 * additional type of model, though too often that term is applied to
87 * systems that still have a centralized control structure.)
89 * <p> <em>Be strict in what you send, liberal in what you accept,</em> as
90 * the Internet tradition goes. Strictly conformant data should never cause
91 * problems to its receiver; make your request pipeline be very strict, and
92 * don't compromise on that. Make your response pipeline strict as well,
93 * but be ready to tolerate specific mild, temporary, and well-documented
94 * variations from specific communications peers.
96 * @see XmlServlet
98 * @author David Brownell
100 final public class CallFilter implements EventConsumer
102 private Requestor req;
103 private EventConsumer next;
104 private URL target;
105 private URLConnection conn;
106 private ErrorHandler errHandler;
110 * Initializes a call filter so that its inputs are sent to the
111 * specified URI, and its outputs are sent to the next consumer
112 * provided.
114 * @exception IOException if the URI isn't accepted as a URL
116 // constructor used by PipelineFactory
117 public CallFilter (String uri, EventConsumer next)
118 throws IOException
120 this.next = next;
121 req = new Requestor ();
122 setCallTarget (uri);
126 * Assigns the URI of the call target to be used.
127 * Does not affect calls currently being made.
129 final public void setCallTarget (String uri)
130 throws IOException
132 target = new URL (uri);
136 * Assigns the error handler to be used to present most fatal
137 * errors.
139 public void setErrorHandler (ErrorHandler handler)
141 req.setErrorHandler (handler);
146 * Returns the call target's URI.
148 final public String getCallTarget ()
150 return target.toString ();
153 /** Returns the content handler currently in use. */
154 final public org.xml.sax.ContentHandler getContentHandler ()
156 return req;
159 /** Returns the DTD handler currently in use. */
160 final public DTDHandler getDTDHandler ()
162 return req;
167 * Returns the declaration or lexical handler currently in
168 * use, or throws an exception for other properties.
170 final public Object getProperty (String id)
171 throws SAXNotRecognizedException
173 if (EventFilter.DECL_HANDLER.equals (id))
174 return req;
175 if (EventFilter.LEXICAL_HANDLER.equals (id))
176 return req;
177 throw new SAXNotRecognizedException (id);
181 // JDK 1.1 seems to need it to be done this way, sigh
182 ErrorHandler getErrorHandler () { return errHandler; }
185 // Takes input and echoes to server as POST input.
186 // Then sends the POST reply to the next pipeline element.
188 final class Requestor extends XMLWriter
190 Requestor ()
192 super ((Writer)null);
195 public synchronized void startDocument () throws SAXException
197 // Connect to remote object and set up to send it XML text
198 try {
199 if (conn != null)
200 throw new IllegalStateException ("call is being made");
202 conn = target.openConnection ();
203 conn.setDoOutput (true);
204 conn.setRequestProperty ("Content-Type",
205 "application/xml;charset=UTF-8");
207 setWriter (new OutputStreamWriter (
208 conn.getOutputStream (),
209 "UTF8"), "UTF-8");
211 } catch (IOException e) {
212 fatal ("can't write (POST) to URI: " + target, e);
215 // NOW base class can safely write that text!
216 super.startDocument ();
219 public void endDocument () throws SAXException
222 // Finish writing the request (for HTTP, a POST);
223 // this closes the output stream.
225 super.endDocument ();
228 // Receive the response.
229 // Produce events for the next stage.
231 InputSource source;
232 XMLReader producer;
233 String encoding;
235 try {
237 source = new InputSource (conn.getInputStream ());
239 // FIXME if status is anything but success, report it!! It'd be good to
240 // save the request data just in case we need to deal with a forward.
242 encoding = Resolver.getEncoding (conn.getContentType ());
243 if (encoding != null)
244 source.setEncoding (encoding);
246 producer = XMLReaderFactory.createXMLReader ();
247 producer.setErrorHandler (getErrorHandler ());
248 EventFilter.bind (producer, next);
249 producer.parse (source);
250 conn = null;
252 } catch (IOException e) {
253 fatal ("I/O Exception reading response, " + e.getMessage (), e);